使用单独的git-worktree,为什么我不能签出与主工作副本相同的分支?如果我尝试,我会收到错误:
fatal: 'mybranch' is already checked out at '/path/to/repo'
我可以看到,如果我从一个工作树签入,另一个工作树最终会处于分离的 HEAD 状态,但这有那么糟糕吗,为什么我什至不能签出同一个分支?
使用单独的git-worktree,为什么我不能签出与主工作副本相同的分支?如果我尝试,我会收到错误:
fatal: 'mybranch' is already checked out at '/path/to/repo'
我可以看到,如果我从一个工作树签入,另一个工作树最终会处于分离的 HEAD 状态,但这有那么糟糕吗,为什么我什至不能签出同一个分支?
我可以看到,如果我从一个工作树签入,另一个工作树最终会处于分离的 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
提交在哪里../worktree1
,2
是提交在worktree2
. 两个工作树中的 namemybranch
都指向 commit 2
。两个工作树中的名称HEAD
都包含ref: refs/heads/mybranch
. 当然,两个工作树中的索引文件是不同的。
提交的内容1
是索引中的任何内容worktree1
。bar1
它具有您对和所做的更改bar2
。
提交的内容2
是索引中的任何内容worktree2
。它具有您在 中所做的更改unrelated
,但没有对文件bar1
和bar2
. 实际上,您所做的提交worktree2
还原了这两个文件!
如果您愿意让一个或两个工作树处于“分离 HEAD”状态,您可以使用git checkout --detach mybranch
或以这种方式检查它们git checkout refs/heads/mybranch
。现在至少其中一个将HEAD
直接指向一个提交,而不是分支名称,并且 Git 应该允许两个工作树签出相同的提交。