为什么我的Git repo进入了独立的HEAD状态?

时间:2010-10-19 05:54:02

标签: git

我今天最终得到了一个独立的头,与git push says everything up-to-date even though I have local changes

中描述的问题相同

据我所知,我没有做任何与众不同的事情,只是从我当地的回购中提交和推送。

那我怎么最终得到detached HEAD

12 个答案:

答案 0 :(得分:242)

任何提交的签出都不是您的分支之一的名称,它将为您提供一个独立的HEAD。代表分支尖端的SHA1仍会提供分离的HEAD。只有签出本地分支名称才能避免该模式。

请参阅committing with a detached HEAD

  

当分离HEAD时,提交正常工作,除了没有更新命名分支。 (您可以将其视为匿名分支。)

alt text

例如,如果你先检查一个“远程分支”而不先跟踪它,你最终可能会得到一个分离的HEAD。

请参阅git: switch branch without detaching head

答案 1 :(得分:93)

我偶然重现了这个:

  1. 列出远程分支

    git branch -r
          origin/Feature/f1234
          origin/master
    
  2. 我想在本地结帐,所以我剪了粘贴:

    git checkout origin/Feature/f1234
    
  3. 的Presto!分离的HEAD状态

    You are in 'detached HEAD' state. [...])
    
  4. 解决方案#1:

    检查时,请不要在我的分支规范前面加origin/

    git checkout Feature/f1234
    

    解决方案#2:

    添加-b参数,该参数从远程

    创建本地分支

    git checkout -b origin/Feature/f1234

    git checkout -b Feature/f1234它会自动回归原点

答案 2 :(得分:12)

尝试

git reflog 

这将为您提供HEAD和分支指针的历史记录 在过去的地方。

e.g。 :

88ea06b HEAD @ {0}:checkout:从开发转移到遥控器/ origin / SomeNiceFeature e47bf80 HEAD @ {1}:拉动原点开发:快进

此列表的顶部是一个可能遇到DETACHED HEAD的人 州......检查远程跟踪分支。

答案 3 :(得分:8)

如果您尝试撤消通过重新签出文件所做的更改并且不能正确理解语法,则很容易发生。

你可以查看git log的输出 - 你可以在上次成功提交后粘贴日志的尾部,我们都可以看到你做了什么。或者你可以粘贴它并在freenode IRC的#git中很好地提问。

答案 4 :(得分:5)

如果 git 重命名 detached HEAD,我会将它命名为一个没有被分支识别并且很快就会被遗忘的 HEAD

我们作为人很容易记住分支名称。我们做git checkout new-button-feature / git checkout mainmainnew-button-feature 很容易记住。我们只需执行 git branch 并获得所有分支的列表。但是要对提交执行相同的操作,您必须执行 git reflog,这非常乏味。因为你有成千上万的提交,但只有很少的分支。

分离提交的标识符只是它的 SHA。所以假设你检查了一个提交(不是一个分支),即你做了 git checkout d747dd10e450871928a56c9cb7c6577cf61fdf31 你会得到:

<块引用>

注意:检查 输出'd747dd10e450871928a56c9cb7c6577cf61fdf31'。

您处于“分离头”状态。

...

然后,如果您进行了一些更改并进行了提交,您仍然不在分支上。

你认为你会记得提交 SHA 吗?你不会!

git 不希望这种情况发生。因此,它会通知您的HEAD 未与分支关联,因此您更倾向于签出新分支。因此,该消息下方还显示:

<块引用>

如果你想创建一个新的分支来保留你创建的提交,你 可以通过再次将 -b 与 checkout 命令一起使用来执行此操作(现在或以后)。 示例:

git 结帐 -b


为了更深入一点,分支的构建方式非常智能。它会在您提交时更新其 HEAD。另一方面,标签并不意味着那样。如果你签出一个标签,那么你又在一个分离的 HEAD 上。主要原因是,如果您从该标签进行新的提交,那么鉴于该提交未被任何内容(不是任何分支或标签)引用,那么它仍然被视为分离的 HEAD。

附加的 HEAD 只能在您在分支上时发生。

更多信息见here

<块引用>

HEAD 是一个指针,它直接或间接地指向一个 特定提交:

Attached HEAD 意味着它附加到某个分支(即它 指向一个分支)。

分离的 HEAD 意味着它没有附加到任何分支,即它 直接指向某个提交。

换个角度看,如果你在树枝上做 cat .git/HEAD 你会得到:

ref: refs/heads/Your-current-branch-name

然后,如果您执行 cat refs/heads/Your-current-branch-name,那么您还会看到您的分支指向/引用的提交的 SHA。

但是,如果您使用独立的 HEAD,您和 cat .git/HEAD 只会获得提交的 SHA,仅此而已:

639ce5dd952a645b7c3fcbe89e88e3dd081a9912

仅此而已,我的意思是头部没有指向任何分支。它只是直接指向一个提交。


由于所有这些,无论何时您检出提交(不使用分支名称检出),即使该提交是您的分支的最新提交,您也仍然在一个分离的 HEAD 中,因为你的 HEAD 没有指向你的任何本地分支。因此,即使签出标签也会让您处于分离的 HEAD 中。除此之外,即使检查已提取到计算机中的远程分支也会导致分离的头部,即 git checkout origin main 也将最终成为分离的头部...

总结

以下所有情况都会导致分离头:

  • 签出任何提交
  • 签出任何标签
  • 签出任何远程分支

如果你已经签出一个本地分支

,你只是在一个附加的头上

特别感谢 Josh CaswellSaagar Jha 帮助我解决这个问题。

答案 5 :(得分:4)

如果您的标签名称与分支相同,则会发生这种情况。

示例:if&#34; release / 0.1&#34;是标签名称,然后

git checkout release/0.1

在&#34; release / 0.1&#34;处生成分离的HEAD。如果您希望release / 0.1成为分支名称,那么您会感到困惑。

答案 6 :(得分:3)

一种简单的偶然方式是将git checkout head作为HEAD的拼写错误。

试试这个:

git init
touch Readme.md
git add Readme.md
git commit
git checkout head

给出了

Note: checking out 'head'.

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.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at 9354043... Readme

答案 7 :(得分:1)

进入git分离头状态的另一种方法是尝试提交到远程分支。类似的东西:

git fetch
git checkout origin/foo
vi bar
git commit -a -m 'changed bar'

请注意,如果你这样做,任何进一步检查origin / foo的尝试都会让你回到一个独立的头状态!

解决方案是创建自己的本地foo分支,跟踪origin / foo,然后选择性地推送。

这可能与你原来的问题无关,但是这个页面在google点击率很高,并且#34; git detached head&#34;这种情况严重缺乏记录。

答案 8 :(得分:0)

当您签出提交git checkout <commit-hash>或远程分支时,HEAD将被分离并尝试在其上创建新提交。

任何分支或标记无法访问的提交将在30天后被垃圾收集并从存储库中删除。

解决此问题的另一种方法是为新创建的提交和结帐创建一个新分支。 git checkout -b <branch-name> <commit-hash>

本文说明了如何进入detached HEAD州。

答案 9 :(得分:0)

Detached HEAD表示当前签出的不是本地分支。

某些会导致处于Detached HEAD状态的情况:

  • 如果您签出远程分支机构,请说origin/master。这是一个只读分支。因此,从origin/master创建提交时,它将自由浮动,即未连接到任何分支。

  • 如果您签出特定标签或提交。从此处进行新提交时,它将再次为自由浮动,即未连接到任何分支。请注意,当签出 branch 时,新提交始终总是自动放在提示处。

    当您想返回并签出特定的提交或标记以从那里开始工作时,可以创建一个源自该提交的新分支,并通过git checkout -b new_branch_name切换到该分支。这将防止Detached HEAD状态,因为您现在有一个已检出分支而不是提交的分支。

答案 10 :(得分:0)

就我而言,它是这样发生的:

  • 创建一个新分支 (feb_debugging)。
  • 运行git fetch
  • 我看到新分支 (feb_debugging) 被拉取
  • 现在,我使用 git checkout origin/feb_debugging

这里让我 HEAD 现在在......

为了修复,我只需要再次结帐

  • git checkout feb_debugging
  • 现在 git 说我在 feb_debugging 分支。

答案 11 :(得分:0)

根据 VonC 的评论,这里是我如何解决相同的“分离头”问题的简短版本。

  1. 在我的遥控器中创建了一个分支; origin/feature/dev
  2. 在我的本地运行 git fetch,所以现在我的本地会知道这个新的远程分支
  3. 现在运行 git switch feature/dev,我们就完成了!