我有一个简单的存储库,我需要在另一个目录中签出一个分支。为此,我使用git worktree
。通常,git worktree add -B hello ../hello master
从hello
创建一个名为master
的新分支,并将其检出到../hello
下。
这实际上正是我在寻找的东西,除了目录已经存在。According to the documentation-B
应该忽略它,而只使用目录中的文件,但是它仍然抱怨:
$ git worktree add -B hello ../hello master
Preparing worktree (resetting branch 'hello'; was at 0465e02)
fatal: '../hello' already exists
为什么我使用的命令不起作用?请参阅以下文档的报价。我会误解文档吗?
从文档中引用:
默认情况下,-b拒绝创建新分支(如果已经存在)。 -B将覆盖此保护措施,将重置为
这是对-B
选项的基本误解。它告诉Git,分支名称(在这种情况下为hello
)可以存在。 对于添加的工作树目录,永远不行-在这种情况下,../hello
-已经存在。
((根据您的问题,您已经知道很多,这是给其他读者的。)
First:git worktree add
添加一个新的work-tree,而不仅仅是目录。添加的工作树带有增加的索引:每个工作树有一个Git索引。 git worktree add
操作成功后,您将在添加的工作树中找到一个名为.git
的文件,其中包含原始Git存储库的路径。您可以cd ../hello
或以其他方式导航到添加的工作树,并以与在主工作树中相同的方式进行工作。您可以随意添加添加的工作树;它的Git索引与您的主要工作树的Git索引无关。
Second:一个branch像Git中的master
一样,它只是一个名称-您可以随时更改,甚至在某些情况下甚至完全删除而没有明显影响1-您会找到一个特定的commit。重要的是提交,而不是分支名称。 commits保留文件,每个提交都有其唯一的真实名称,即其哈希ID。不过,分支名称仅包含一个现有提交的哈希ID。
现在:
$ git worktree add -B hello ../hello master
这告诉Git创建一个名为../hello
的新目录。该新目录应该位于您的当前工作树之外(并且可能以../hello
作为路径),该目录必须为[[不存在。由于../hello
实际上确实存在,所以这一步失败了。
-B hello
命令的git worktree add
部分告诉它,在成功创建此新的空目录然后检出对该工作树的某些提交后,我们将在时刻—它应该执行一个事务操作,使分支名称hello
成立(如果之前不存在),或者现在确定(如果之前存在)您选择的提交。形容词transactional此处意味着此步骤应完全成功,以使分支名称hello
通过正确的提交存在,或者看起来根本没有发生:如果已经有一个分支名称[C0 ]它将保持原状。
消息:
hello
告诉您分支名称确实存在,并且确实指向(包含其哈希ID)该缩写哈希ID为(resetting branch 'hello'; was at 0465e02)
的提交。由于实际命令最终失败,因此分支名称0465e02
应该继续存在并继续指向提交hello
。最后,0465e02
命令的master
部分将Git应该签出的提交的哈希ID提供给添加的工作树。如果您运行:
git worktree add
Git将打印出通过此步骤获得的哈希ID(假设名称git rev-parse master
尚未被修改以标识其他提交,就是这样。)>]
正如我们已经指出的,整个事情失败了,因为要使分支名称的删除微不足道,您需要能够通过某种其他方式找到通过该分支名称可以找到的提交。您也不必为master
已经存在(并且可能包含文件,有些Git操作允许目录只要是空的就已经存在,如果[C0 ]是过去,现在或将来的其中之一。要解决此问题,只需选择其他名称,或者-如果../hello
中的文件都不有价值,请完全删除git worktree add
。
1
../hello
删除存储在Git配置文件中该分支名称下的配置信息(例如分支的上游)而烦恼,也不必为立即删除该分支的引用日志而烦恼。 (关于某天保留“分支取消删除”操作的引用的一些模糊的猜测,但是很长一段时间都没有出现。)