git checkout branch导致分离头问题

3

我想要检出一个在我的系统上还不存在的远程分支。为了回答这个问题,假设这3个分支都不存在于我的系统中。

git branch -r 显示远程仓库相关的分支列表:

  origin/V2.0005B2
  origin/V2.0005B3
  origin/V2.0005B4

我可以正常运行 git checkout V2.0005B2git checkout V2.0005B4 命令,它会创建一个本地副本并设置为跟踪。

但是,当我尝试运行 git checkout V2.0005B3 命令时,它每次都会使我进入“分离头状态(detached head)” 。我尝试在多台机器上执行此命令都遇到了这个问题。

SourceTree 和 git fork 能够正常检出该分支。但 Git Bash 命令行却有此问题。

我希望这个分支没有问题,否则只要最初使用这些其他工具之一检出,它似乎就可以正常工作。此分支位于 BitBucket 上,我已登录查看是否有异常情况,但与其他分支相比看起来没什么区别。

谢谢, Dave


2
如果您提供进入分离头状态时获取的git消息的快照,那将会很有帮助。另外,您可以尝试使用完整的refspec,即git checkout refs/heads/V2.0005B3吗? - pro_gamer
2
git checkout V2.0005B3 && git branchV2.0005B3也是一个标签吗? - phd
@pro_gamer:不幸的是,git checkout 拒绝以 refs/heads/<name> 的方式选择分支名称。在这种情况下,OP 尚未将该分支作为分支名称,因此即使 Git 允许此语法,它也不起作用,但 Git 会将带前缀的分支名称视为 --detach 请求,因此两种方式都不起作用。 - torek
2个回答

5

LeGEC的答案正确,但我会补充两点。第一点是关于如何获得您想要的内容,而第二点则更长,描述了另一个失败案例以及另一种解决方法。

首先,还有一种比较简短的方式可以从远程跟踪名称创建本地分支,那就是使用git checkout(或git switch)带上--track选项和远程跟踪名称:

git checkout --track origin/V2.0005B3

该表单会定位远程跟踪名称(完整拼写为refs/remotes/origin/V2.0005B3),确认它确实是一个远程跟踪名(以refs/remotes/开头),应用--track选项来去掉refs/remotes/origin部分,得到V2.0005B3,然后使用分支创建选项(-b用于git checkout-c用于git switch)创建具有上游origin/V2.0005B3V2.0005B3
其次:通常遇到此问题的原因是Git首先找到了标签,因为确实有这样的标签:
- git checkout代码首先尝试作为现有分支的名称给出的名称,即尝试在前面添加refs/heads/,看是否结果将解析为提交哈希ID。如果是,则这是一个现有的分支名称,因此是请求切换到该现有分支。 - 如果失败,则转向描述在gitrevisions文档中的通常六个步骤的过程,其中尝试标签名称之前尝试远程跟踪名称。请注意,“尝试名称作为标签名称”是第3步(在第4步之前“尝试名称作为分支名称”:但是git checkout在进入六个步骤的过程之前进行了它自己的私有步骤4)。 - 如果没有标签,Git将继续执行步骤5和6,步骤5将找到远程跟踪名称。这将调用稍后的“ DWIM”代码来创建分支,除非您使用了--no-guess选项。 (该选项在Git 2.21中新增。) - 但是,此自动创建--guess模式失败的另一种方法是如果存在两个或多个远程跟踪名称候选项。因此,例如,如果同时存在origin/V2.0005B3upstream/V2.0005B3远程跟踪名称,则猜测模式不知道要使用哪一个--track选项会告诉Git要使用哪个远程分支,从而巧妙地避开这个困境。此外,在Git 2.19中还有另一个技巧:checkout.defaultRemote选项可以告诉git checkoutgit switch命令中的--guess代码哪个远程分支是首选,如果存在多个匹配项。因此,除了使用--track外,如果问题是多个具有相同分支名称的远程分支,则可以配置首选远程分支以选择正确的远程跟踪分支名称。

5

检查您的本地标签:

git tag --list

如果您有一个名为V2.0005B3的标签,运行git checkout V2.0005B3将导致您处于分离状态HEAD,并指向由该标签指向的提交。

  • 如果您想在那里创建一个分支,请运行:
git checkout -b V2.0005B3
git branch -u origin/V2.0005B3

# or shorter suggested by @torek :
git checkout --track origin/V2.0005B3
  • 如果您想删除标签:
# delete your local tag :
git tag -d V2.0005B3

# delete the remote tag :
git push -d origin refs/tags/V2.0005B3

如果这是一个共享的存储库,请告诉您所有的同事也删除他们本地的标签; 这将避免出现意外行为,并减轻该标签在中央存储库上可能重新出现的可能性。

是的,就是这样!我不知道在删除本地分支副本后,标签会作为引用留下来。 - Dave Ludwig
修改:我重新表述了我的最后一段话;我以为“git push”默认会推送标签,但是我被提醒它并不会。如果标签存在于中央仓库上,git pull命令确实会获取该标签。 - LeGEC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接