Git中的“分离 HEAD”状态:它是什么以及如何修复它?
作者:互联网
使用 Git 时,一个常见的混淆来源是当你看到这样的输出时不知道这一切意味着什么:
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 switching back to a branch.
这是什么意思呢?
要真正了解正在发生的事情,我们需要深入了解 Git。
Git 提交是不可变的——这意味着你可以创建新的提交,但里面已经存在的内容永远不会改变。这就是我们的存储库为我们保证数据安全的方式。对存储库进行更改的唯一方法是创建新的提交。
Git 提交为我们提供了对存储库更改的稳定、完整的历史记录。在这个稳定的基础之上,我们有一个动态的部分:分支。一开始可能令人惊讶的是,分支只是标签。他们指向一个提交。除了名称和位置之外,它们实际上没有其他数据。
除此之外的任何东西——例如,
- 主要或主人的特殊含义,
feature/<info>
, 或— 之类的模式<branch-owner>/<description>
只是团队使用的约定。从 Git 的角度来看,您的main
ormaster
分支与lorem-ipsum
.
当前提交
HEAD 是指向当前提交的指针——你现在在存储库中的位置。它被用作:
- 当您想查看对工作副本的最后更改时的参考点
git diff
- 创建新提交时将用作父提交的提交
您的 HEAD 是存储库状态的核心部分。
正常状态
Git 的典型工作流程如下:
- 你在某个分支上,
- 您创建新的提交,并且
- Git 将您的分支移动到这个新提交。
如果你限制自己只检查分支,你将永远不会离开这个状态。当你运行时git status
,它会告诉你你在哪个分支:
$ git status
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
分离头
到目前为止,HEAD(当前提交)和分支处于正常的对齐状态。当您检查不是分支的东西时,事情会变得复杂——例如,当您通过其 ID 切换到提交时:
$ git checkout abc01e7
whereabc01e7
是存储库中任何提交的 ID——它可以在任何分支内,在其中一个分支之上,或者在存储库历史记录的另一个位置。
因为您不再在分支上,所以git status
更改为:
$ git status
HEAD detached at abc01e7
nothing to commit, working tree clean
为了提醒您注意这种情况,Git 将颜色HEAD detached
设置为红色。
为什么要切换到提交而不是分支?
因为你可以,而且它有时很有用。一个常见的场景是查看应用程序在几个提交之前是如何工作的——例如,用于故障排除。我们注意到了一些错误,例如某个功能没有按预期工作,我们检查了我们希望可以正常工作的最后一次提交。通过这种方式,我们可以确定问题的确切引入时间。
它如何影响工作?
因为您不在分支上,所以当您创建新提交时,Git 没有要更新的分支。因此,您在那里创建的所有提交都被存储但仍然悬而未决:没有办法轻松地访问它们,因此,它们被认为是不重要的。在某个时候,垃圾收集器会将它们从存储库中永久删除。
这是怎么发生的?
你离开了分支,把你的 HEAD 移到了别处。它可能发生:
- 通过非分支参考结帐:
git checkout <commit ID>
-如上git checkout HEAD^
——最后一次提交git checkout <tag>
——标签类似于分支,但它们是不可变的,不会作为分支更新
- 当你
git rebase
中途停止时——由于冲突或让你对提交进行更改, - 期间
git bisect
如何修复它
幸运的是,当您查看非分支参考时,您可以直接在 CLI 中获得一些说明:
$ git checkout abc01e7
Note: switching to 'abc01e7'.
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 switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
创建一个新分支
您可以在您所在的位置创建一个新分支——包括您可能从那里创建的所有提交。您可以使用以下语法创建分支:
git switch -c <new-branch-name>
或命令形式的 Git 版本早于 2.23:
git checkout -b <new-branch-name>
这些命令创建一个新分支,并将其设置为您的当前分支。
或者,您可以在当前提交上创建一个新分支并保持分离 HEAD 状态:
git branch <new-branch-name>
切换到一个分支并合并你的提交
或者,您可以选择一个现有的分支并合并您的悬空提交或挑选它们。如果您不确定这些术语的含义,请坚持创建一个新分支,因为它可以让您做同样的事情,但设置不会那么混乱。
标签:Git,HEAD,git status,模式,标签 来源: