无法检出特定分支,“分离的 HEAD 状态”

53

我和我的朋友有一个他创建的代码仓库。然后他创建了一个名为“lexer”的分支供我们共同开发。

问题在于,尽管他可以在主分支和lexer分支之间切换,但我无法这样做。

最终,我不得不重新开始(使用 rm -rf repo 然后克隆存储库),但是还是无法切换到lexer分支?

在新克隆的存储库上:

git branch 会给出:

<code><code>$ git branch
* master
</code></code>

git checkout lexer 给出:

$ git checkout lexer
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

我可以检出 origin/lexer,但最终会进入分离的 HEAD 状态?

$ git checkout origin/lexer master
Note: checking out 'origin/lexer'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

我可以通过执行以下操作将代码推到词法分析器分支:

git push origin HEAD:lexer

但是,我真的很想整理这个混乱局面。这很奇怪,它对他起作用,但对我没有用?他说他也没有从Git存储库中获取任何本地更改...

有人有任何线索吗?

9个回答

67

我猜想您在顶层目录下有一个名为lexer的目录。由于git checkout既用于切换分支,又用于重置树中的文件,它可能检测到您没有名为lexer的分支,但您确实有一个路径,并选择第二种模式。

对您的朋友有效,因为他已经拥有了一个lexer分支。

最简单的解决方法可能是使用git branch创建该分支。

git branch --track lexer origin/lexer

应该为您做到这点。然后,您可以使用 git checkout 切换到它。

另一个选项可能是使用 -- 标志来执行 git checkout。我没有尝试过,但我认为它应该可以工作:

git checkout lexer --

当你添加--时,它前面的单词被视为一个分支/提交/树形结构,后面的单词则是路径。


1
第一个解决方法也适用于分支和标签名称相同的情况。 - mjobrien
1
这对我有用,但我仍然不知道冲突在哪里。我创建了一个全新的分支来保留我的当前更改,推送到我的远程,rm -rf'd一切。重新克隆,获取,通过git checkout origin/recently-created-branch检出我最近创建的分支,然后嘭,HEAD分离。你的第一个建议立即为我解决了所有问题。 - Shadoninja
我一直在想Git命令中的--是什么意思,已经有一年了。谢谢! - GrayedFox
2
我遇到了这个问题——没有同名的冲突目录。 第二个命令将允许检出,但仍然是分离的HEAD。 第一个(添加跟踪信息)是正确的答案。另一个有用的变体:git checkout -t origin/lexer。谢谢! - geipel
git branch --track lexer origin/lexer 对我有效 - Yang Wang

25
您可能需要这个:

您可能需要这个:

git checkout -t origin/lexer

来自 Git 手册:

--track 参数不加 -b 时意味着创建分支...

并且

-t, --track... 在创建新分支时,设置“上游”配置... 如果没有给出 -b 选项,则新分支的名称将从远程跟踪分支派生


这总是有效的,如果您第一次在新存储库上使用它,否则它将显示消息致命:分支名为......等。 - TheExorcist
Yessssssssss!*1e6 - scrat.squirrel

22

简而言之:这可能只是一个语法问题。不要使用

git checkout origin/mybranch

试试:

git checkout mybranch

以下是给定命令时git执行的步骤:


git checkout origin/mybranch
  1. git在本地仓库中寻找名称为'origin/mybranch'的分支。
  2. 如果没有找到,它将在可用的远程仓库中查找名为'origin/mybranch'的分支。
  3. 如果还是找不到,它会尝试将其视为提交标签,并针对特定提交找到标签'origin/mybranch'。它会以分离状态为您检出该提交。

但这并不是你想要的!你想要的是叫做'mybranch'的分支。如果只有一个远程仓库中有这样的分支(并且没有本地分支混淆),那么git将假设你意味着这种用法,并自动填充<remote>

git checkout -b <branch> --track <remote>/<branch>

如果找不到与名称匹配的分支,它将默认为此:

git checkout [--detach] <commit> 

这就是“detached HEAD”消息的出现原因。

请参阅git checkout文档,并仔细注意<branch><remote>之间的区别。


这是我的问题。 - JobHunter69
这让我花了很长时间才弄明白。 - LuXxenatorX
这是我的问题,必须删除远程/origin。 - SSS
感谢Phil详细解答并解释了根本原因。您已经解决了缺失的概念。太棒了。 - Ahmed

14

1
这个答案是完全错误的 - 在当前版本的git中,使用相应的分支名称检出一个不存在的本地分支将默认创建并检出该分支的本地版本。请参见https://git-scm.com/docs/git-checkout:“如果<branch>未找到,但确实存在一个跟踪分支在仅一个远程(称其为<remote>)中具有匹配的名称…” - eis
确实,这是git的默认行为,但也许你错过了文本“(肯定还有一个同名文件夹)”,它改变了这种行为,这也是主要问题所在。而且你可以看到被接受的答案完全说了同样的事情。所以,不,我不认为我的回答是完全错误的... - Philippe
“你无法检出词法分析器,因为你的本地仓库中没有该分支[...]首先你需要[...]”是“完全错误”的部分。是的,文件夹似乎是问题所在,这个答案的其他部分与此无关。 - eis

4
您进入了一个分离的HEAD状态,因为origin/lexer是一个远程跟踪分支,因此只读。您想要检出lexer,并在其上进行工作。然后,当您推送时,origin/lexer将被更新。 编辑:重新阅读您的问题,我发现您已经尝试检出lexer,但最终仍停留在主分支上。奇怪的是,git checkout没有报错。请尝试git checkout -t origin/lexer

2
另一个猜测:您可能有一个具有相同名称的标签。
git checkout lexer

实际上是检查标签,而不是分支


这是我的问题。谢谢! - Parker Kemp

1
当你执行以下命令:git checkout origin/lexer master时,你只是把你的HEAD指向我们remote分支中最新的提交。这是一个只读分支。
如果你想了解HEAD是什么,请阅读:
如何将HEAD移回到以前的位置?(Detached head) 在你的情况下,你只需要执行以下操作:

使用所有分支和标签更新你的代码库

# Update your local repository with all the remote branches
# --prune = remove all deleted data locally which was removed on the remote
git fetch --all --prune

现在你应该在本地拥有最新的分支。

删除旧的本地分支

!!! 重要提示:
如果你进行了修改并且没有推送,请勿删除本地分支。

git branch -D lexer 

检出所需的分支

# don't use the remote simply the branch name
git checkout lexer 

现在您已经从远程分支检出了名为lexer的本地分支。

0

我发现如果一个分支不存在,或者我们在分支名称中犯了一些错误,比如feature/或origin/等等,那么我会得到一个脱离的HEAD。 仔细检查分支名称,然后可以使用checkout branchname命令。


-1

我只是替换了命令

$ git checkout v4.9.0

使用

$ *git checkout -b v4.9.0

而且它对我来说是有效的。


2
-b选项只是创建一个新分支。在创建新分支之后,需要从远程分支拉取代码。 - Gautham M

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