我有一个简单的存储库,我需要在另一个目录中签出一个分支。为此,我使用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 会覆盖此保护措施,将 <新分支> 重置为 <分支>
答案 0 :(得分:1)
这是对-B
选项的基本误解。它告诉Git,分支名称(在这种情况下为hello
)可以存在。 添加的工作树目录(在这种情况下为../hello
)已经存在是永远不可能的事情。
(根据您的问题,您已经知道了很多,这是供其他读者使用的。)
首先:git worktree add
添加一个新的工作树,而不仅仅是目录。添加的工作树带有增加的索引:每个工作树有一个Git索引。 git worktree add
操作成功后,您将在添加的工作树中找到一个名为.git
的文件,其中包含原始Git存储库的路径。您可以cd ../hello
或以其他方式导航到添加的工作树,并以与在主工作树中相同的方式进行工作。您可以随意添加添加的工作树;其Git索引与您的主要工作树的Git索引无关。
第二:在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
存在正确的提交,或者看起来根本没有发生过:已经是分支名称hello
,它将保持不变。
消息:
(resetting branch 'hello'; was at 0465e02)
告诉您分支名称确实存在,并且确实指向了(包含其哈希ID)其缩写哈希ID为0465e02
的提交。由于实际命令最终失败,因此分支名称hello
应该继续存在并继续指向提交0465e02
。
最后,master
命令的git worktree add
部分将Git应该签出的提交的哈希ID提供给添加的工作树。如果您运行:
git rev-parse master
Git将打印出通过此步骤获得的哈希ID(假设尚未修改名称master
来标识其他提交)。
总的来说,这件事失败了,因为我们已经注意到../hello
已经存在(并且可能包含文件),某些Git操作允许目录只要它们为空就已经存在,而我不会立即记住git worktree add
是过去,现在还是将来将是其中之一)。要解决此问题,只需选择其他名称,或者-如果../hello
中的所有文件都没有价值,请完全删除../hello
。
1 要使分支名称的删除微不足道,您需要能够通过其他方式找到通过该分支名称可以找到的提交。您也不必为git config
删除存储在Git配置文件中该分支名称下的配置信息(例如分支的上游)而烦恼,也不必为立即删除该分支的引用日志而烦恼。 (有人猜测有一天会保留“分支取消删除”操作的引用,但很长一段时间都没有。)