使用工作树将现有目录添加为git的分支

时间:2019-12-24 23:33:04

标签: git

我有一个简单的存储库,我需要在另一个目录中签出一个分支。为此,我使用git worktree。通常,git worktree add -B hello ../hello masterhello创建一个名为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 会覆盖此保护措施,将 <新分支> 重置为 <分支>

1 个答案:

答案 0 :(得分:1)

TL; DR

这是对-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配置文件中该分支名称下的配置信息(例如分支的上游)而烦恼,也不必为立即删除该分支的引用日志而烦恼。 (有人猜测有一天会保留“分支取消删除”操作的引用,但很长一段时间都没有。)