我是怎么得到一个分离的 HEAD 的?

How did I end up with a detached HEAD?

我从master那里签出一个commit/branch,然后又签回来给master写了点东西。在那之后,我提交了它,但我最终得到了一个分离的 HEAD。为什么?

这是我所做的:

  1. 创建一个新项目并创建 git 存储库。
  2. git 添加
  3. git 提交
  4. 输入一些字词
  5. git 提交
  6. 签出之前的提交
  7. 结帐回来

  8. 输入一些单词

  9. 尝试提交;提示有脱头

IntelliJ IDEA 的控制台显示:

17:08:58.143: cd C:\Users\jiahao\IdeaProjects\testtt\src
17:08:58.143: git init
Initialized empty Git repository in C:/Users/jiahao/IdeaProjects/testtt/src/.git/
17:09:16.331: cd C:\Users\jiahao\IdeaProjects\testtt\src
17:09:16.331: git -c core.quotepath=false add --ignore-errors -- C.java
17:09:24.407: cd C:\Users\jiahao\IdeaProjects\testtt\src
17:09:24.407: git -c core.quotepath=false commit --only -F C:\Users\jiahao\AppData\Local\Temp\git-commit-msg-0.txt -- C.java
[master (root-commit) 22d1c79] first commit
 1 file changed, 6 insertions(+)
 create mode 100644 C.java

17:09:38.060: cd C:\Users\jiahao\IdeaProjects\testtt\src
17:09:38.060: git -c core.quotepath=false commit --only -F C:\Users\jiahao\AppData\Local\Temp\git-commit-msg-0.txt -- C.java
[master 69084f3] second commit
 1 file changed, 1 insertion(+)

17:09:44.136: cd C:\Users\jiahao\IdeaProjects\testtt\src
17:09:44.136: git -c core.quotepath=false checkout 22d1c7919eab50925411d9bbb8a9ad1575608c27
Note: checking out '22d1c7919eab50925411d9bbb8a9ad1575608c27'.
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 22d1c79... first commit
17:09:46.576: cd C:\Users\jiahao\IdeaProjects\testtt\src
17:09:46.576: git -c core.quotepath=false checkout 69084f344b79a48da92855d3fb633a28a672a302
Previous HEAD position was 22d1c79... first commit
HEAD is now at 69084f3... second commit
17:18:26.999: cd C:\Users\jiahao\IdeaProjects\testtt\src
17:18:26.999: git -c core.quotepath=false commit --only -F         C:\Users\jiahao\AppData\Local\Temp\git-commit-msg-0.txt -- C.java
[detached HEAD 783fbf2] third commit
1 file changed, 1 insertion(+)

要恢复 detached-HEAD,您可以:

git checkout master

问题与解决方案

仔细检查 IntelliJ-IDEA 日志可以揭示问题的本质。创建前两次提交后,您处于以下情况:

不知何故,您检查了第一次提交,这使您处于 detached-HEAD 状态:

然后,类似地,您检查了第二次提交(恰好是 master 分支的顶端)。这仍然使您处于 detached-HEAD 状态:


你写:

I checked out a commit/branch from master [...]

小心。检查恰好是分支尖端的提交 等同于检查该分支!


请注意 HEAD 现在直接指向一个提交, 而不是 一个分支。即"detached HEAD"的定义。 HEAD 指向与 master 相同的提交这一事实并没有改变您的 HEAD 分离的事实。


有些 IDE 可能无法明确指示您实际上处于 detached-HEAD 状态。 Even git log --decorate, for a long time, gave you no clue as to whether HEAD was pointing to master, or detached and pointing directly at master's tip.


然后您进行了第三次提交,正如预期的那样,仍然留下了一个分离的 HEAD;您的 master 分支仍然指向第二个提交。

要摆脱分离 HEAD-state,您需要将 HEAD 重新附加到一个分支(此处为 master)。如何取决于你想做什么。在下文中,我假设您可以访问 Git CLI:

  • 如果您想放弃第三次提交,只需 运行

    git checkout master
    

    你最终会回到这种情况:

  • 如果你想保留你的第三次提交并让 master 指向它,运行

    git branch -f master HEAD
    

    然后

     git checkout master
    

临别提示

在 IDE 中学习 Git 是 灾难的良方 。我建议您首先在命令行上建立您的理解,然后才开始在 GUI 中使用 Git,如果您认为这样做会改善您的工作流程。

我在使用 IntelliJ 2020.2 开发 Java Spring 项目时不小心 运行 进入了分离式 HEAD。这就是我恢复正常的方式。

在git工具window[Alt+9]中,b运行ch“日志:origin/master”,有3个标签: 黄色 = 头部,绿色 = 主人,紫色 = origin/master:

'HEAD' 和 'origin/master' 已应用于最新提交 'master' 已应用于较早的提交

要退出 detached-head 并将其重置为所需状态“HEAD & master & origin/master all applied to b运行ch's latest commit',右键单击 'master' 节点 'Remote' 列表(位于 Log 下 b运行ch 历史的左侧)并选择 'Checkout'

这样在 b运行ch 的最新提交中恢复到正常状态