16

使用单独的git-worktree,为什么我不能签出与主工作副本相同的分支?如果我尝试,我会收到错误:

fatal: 'mybranch' is already checked out at '/path/to/repo'

我可以看到,如果我从一个工作树签入,另一个工作树最终会处于分离的 HEAD 状态,但这有那么糟糕吗,为什么我什至不能签出同一个分支?

4

1 回答 1

17

我可以看到,如果我从一个工作树签入,另一个工作树最终会处于分离的 HEAD 状态

实际上,它不会,这就是问题所在!

每个工作树都有自己的HEAD和自己的索引(也称为暂存区或缓存)。所有共享实际的底层存储库,以及底层分支提示文件,例如.git/refs/heads/mybranch.

那么,假设两个不同的工作树(我将把它们都与主仓库分开,这样就没有明显的“首选”一个)都HEAD指向mybranch,并且你从两个工作中的一个进行提交-树木:

repo$ cd ../worktree1
worktree1$ ... hack away ...
worktree1$ git add bar1 bar2 && git commit -m 'foo some bars'

现在发生的情况很正常:Git 将索引写入一棵或多棵树,使用新树写入新提交,并将任何提交mybranch解析为其父提交,并更新mybranch以指向新提交。现在的索引worktree1与新提交匹配。现在我们这样做:

worktree1$ cd ../worktree2
worktree2$ ... modify unrelated file, not bar1 or bar2 ...
worktree2$ git add unrelated && git commit -m 'unrelated change'

现在发生的事情是 Git 写入索引……等等,索引哪个指数?好吧,索引- 中的索引worktree2。没有从worktree1. (它确实有这两个bar文件,除非它们是全新的,但它有旧版本。)好的,所以 Git 将索引写入一棵或多棵树,使用新树写入新提交,并且任何提交mybranch解析为它的父级,并更新mybranch以指向新的提交。

提交链现在看起来像这样:

...--o--1--2

1提交在哪里../worktree12是提交在worktree2. 两个工作树中的 namemybranch都指向 commit 2。两个工作树中的名称HEAD都包含ref: refs/heads/mybranch. 当然,两个工作树中的索引文件是不同的。

提交的内容1是索引中的任何内容worktree1bar1它具有您对和所做的更改bar2

提交的内容2是索引中的任何内容worktree2。它具有您在 中所做的更改unrelated,但没有对文件bar1bar2. 实际上,您所做的提交worktree2 还原了这两个文件!

如果您愿意让一个或两个工作树处于“分离 HEAD”状态,您可以使用git checkout --detach mybranch或以这种方式检查它们git checkout refs/heads/mybranch。现在至少其中一个将HEAD直接指向一个提交,而不是分支名称,并且 Git 应该允许两个工作树签出相同的提交。

于 2016-09-23T19:49:51.910 回答