ChatGPT解决这个技术问题 Extra ChatGPT

为什么我的 Git 存储库进入了分离的 HEAD 状态?

git

我今天最终得到了一个分离的头,与中描述的问题相同:git push says everything up-to-date even though I have local changes

据我所知,我没有做任何不寻常的事情,只是从我的本地仓库提交和推送。

那么我是如何得到一个 detached HEAD 的呢?

签出远程分支似乎是意外执行此操作的最常见方法。另一种常见的方法是检查 branch-name@{n},即 branch-name 的第 n 个先前位置。但无论如何,在某些时候一定有一个git checkout <rev>。如果这没有响起,那么您可能做了 Will 提到的事情 - 尝试做 git checkout <file> 并意外地指定了一个修订版。
要撤消分离的 HEAD 状态,请参阅 Fix a Git detached head?
当 rebase 期间遇到冲突时,我的 repo 最终处于这种状态。幸运的是,当我运行 git status 时,Git 告诉我该怎么做:all conflicts fixed: run "git rebase --continue"
如果您不小心输入了 git checkout remotes/origin/my-branch 而不是 git checkout my-branchgit checkout origin/my-branch,也会发生这种情况。
@adam Libusa,谢谢它对我有用。 git checkout remotes/origin/my-branch 和 git checkout my-branch 有什么区别。是不是一样。但你说的对我有用。出于好奇,我问。

V
VonC

任何不是您的分支名称的提交的检出都会让您获得一个分离的 HEAD。代表分支尖端的 SHA1 仍然给出分离的 HEAD。只有检出本地分支名称才能避免该模式。

请参阅committing with a detached HEAD

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

https://i.stack.imgur.com/YwJDh.png

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

请参阅git: switch branch without detaching head

含义:git checkout origin/main(或 origin/master in the old days)将导致:

Note: switching to 'origin/main'.

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

HEAD is now at a1b2c3d My commit message

这就是为什么您不应再使用 git checkout,而应使用新的 git switch 命令。

使用 git switch,“签出”(切换到)远程分支的相同尝试将立即失败:

git switch origin/main
fatal: a branch is expected, got remote branch 'origin/main'

要在 git switch 上添加更多内容:

使用 Git 2.23(2019 年 8 月),您不必再使用 confusing git checkout command

git switch 也可以签出一个分支,并获得一个分离的 HEAD,除了:

它有一个明确的 --detach 选项

要在不创建新分支的情况下检查提交 HEAD~3 以进行临时检查或实验: git switch --detach HEAD~3 HEAD 现在位于 9fc9555312 Merge branch 'cc/shared-index-permbits'

它不能错误地分离远程跟踪分支

看:

C:\Users\vonc\arepo>git checkout origin/master
Note: switching to 'origin/master'.

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 switch 命令:

C:\Users\vonc\arepo>git switch origin/master
fatal: a branch is expected, got remote branch 'origin/master'

如果您想创建一个新的本地分支来跟踪远程分支:

git switch <branch> 

如果 未找到,但在一个远程(称为 )中确实存在一个具有匹配名称的跟踪分支,则视为等效于 git switch -c --track /

没有更多的错误!不再有多余的分离 HEAD!

如果您使用 git switch <tag> 而不是 git switch --detach <tag>,则 Git 2.36 will help you to remember the missing --detach option


进入分离头状态的另一种方法是,如果您正处于交互式变基的中间,并且想要编辑其中一个提交。当 Git 在提交编辑时将您丢弃时,您将处于分离的头部状态,直到您完成 rebase。
事实上,每当您通过其 SHA1 签出任何提交时,您都会得到一个分离的 HEAD,无论它是否位于分支的顶端;唯一可以在没有分离 HEAD 的情况下结帐的是分支名称。例如,即使 master 在上图中的 ed489 处,git checkout ed489 会给您一个分离的 HEAD,而 git checkout master 不会。
"You can think of this as an anonymous branch" :) 我喜欢这个比喻
@亲爱的当然。我已经编辑了答案以添加一个示例,在该示例中我检查了一个远程分支......并最终得到了一个分离的 HEAD。
A
Atais

我刚才无意中复制了这个:

列出远程分支 git branch -r origin/Feature/f1234 origin/master 我想在本地签出一个,所以我剪切粘贴: git checkout origin/Feature/f1234 Presto!分离 HEAD 状态 您处于“分离 HEAD”状态。 [...])

解决方案#1:

签出时不要在我的分支规范前面包含 origin/

git checkout Feature/f1234

解决方案#2:

添加从远程创建本地分支的 -b 参数

git checkout -b origin/Feature/f1234

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


这几乎是一个很好的答案,但无法解释为什么您会进入分离的头部状态。
我同意,但它确实提供了我正在寻找的解决方案。谢谢!!
我在这个 other answer 中看到 git checkout -b Feature/f1234 <=> git branch Feature/f1234git checkout Feature/f1234
默认情况下,它看起来在原点,所以当你给 origin/branchname 时,它会寻找 origin/origin/branchname 来告诉你第一个是你使用 -b 的远程名称,如果你不这样做,它会创建一个分离的 anonymous 分支.同样,如果要从不同的遥控器签出,则必须提及 -b 参数,否则 git 无法知道它来自新的遥控器,它会查找 origin/remote/branchname
关于省略“origin/”的提示就像一个魅力。谢谢!
A
André R.

尝试

git reflog 

这为您提供了过去如何移动 HEAD 和分支指针的历史记录。

例如:

88ea06b HEAD@{0}:结帐:从 DEVELOPMENT 移动到 remotes/origin/SomeNiceFeature e47bf80 HEAD@{1}:pull origin DEVELOPMENT:快进

此列表的顶部是人们可能会遇到 DETACHED HEAD 状态的一个原因......检查远程跟踪分支。


T
Tim Skov Jacobsen

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

会导致 Detached HEAD 状态的一些场景:

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

如果您签出特定标签或提交。从这里进行新提交时,它将再次自由浮动,即不连接到任何分支。请注意,当一个分支被签出时,新的提交总是被自动放置在尖端。当您想返回并签出特定的提交或标签以从那里开始工作时,您可以创建一个源自该提交的新分支并通过 git checkout -b new_branch_name 切换到它。这将阻止 Detached HEAD 状态,因为您现在已签出分支而不是提交。


r
radzimir

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

示例:如果“release/0.1”是标签名称,则

git checkout release/0.1

在“release/0.1”处产生分离的 HEAD。如果您希望 release/0.1 是一个分支名称,那么您会感到困惑。


是的。但是你如何解决这个问题?你如何对分行进行结账?
我用这个 stackoverflow.com/a/5719854/573034 解决了这个问题。最后一个命令 (git pull --prune --tags) 不起作用,所以我使用 git tag -l | xargs git tag -d 删除本地标签并使用 git fetch --tags 重新获取远程标签
这正是我的问题。 Git 警告消息没有提供任何关于这种可能性的线索。
m
mfaani

如果 git 要重命名 detached HEAD,我会将其命名为 一个未被分支识别且很快会被遗忘的 HEAD

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

分离提交的标识符就是它的 SHA。因此,假设您检查了一个提交(不是一个分支),即您做了 git checkout d747dd10e450871928a56c9cb7c6577cf61fdf31,您将得到:

注意:查看“d747dd10e450871928a56c9cb7c6577cf61fdf31”。您处于“分离 HEAD”状态。 ...

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

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

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

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

再深入一点,分支是以一种智能的方式构建的。它会在你提交时更新它的 HEAD。另一方面,标签并不意味着那样。如果您签出标签,那么您将再次处于分离的 HEAD 上。主要原因是,如果您从该标签进行新的提交,那么鉴于该提交没有被任何东西(不是任何分支或标签)引用,那么它仍然被认为是一个分离的 HEAD。

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

如需更多信息,请参阅here

HEAD 是一个指针,它直接或间接地指向一个特定的提交:附加的 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

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

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

概括

以下所有情况都会导致头部脱落:

签出任何提交

签出任何标签

签出任何远程分支

如果您已签出本地分支机构,则您只是在附加的头上

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


在 git 的某些内部,这是一个很好的 blog post by SO。分支只是指向提交的指针,以及切换分支如何改变 HEAD 指向的位置。值得一读,但如果您只是想跳到 git 的内部,那么向下滚动到“分支在技术上是如何工作的,在幕后?”。它有一些不错的截图
W
Will

如果您尝试通过重新签出文件来撤消所做的更改并且没有完全正确地获取语法,则很容易发生这种情况。

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


T
Thomas Weller

一个简单的意外方法是将 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

longair.net/blog/2012/05/07/the-most-confusing-git-terminology 中也提到过(查找““HEAD”和“head”)
@VonC:感谢该链接。我正在准备一个 Git 培训,我还想指出为什么它有时会如此令人困惑。我已经有很多示例(例如 checkout -b,它看起来像一个结帐但实际上是分支),但另一个列表是受欢迎的。
d
dspeyer

进入 git detached head 状态的另一种方法是尝试提交到远程分支。就像是:

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

请注意,如果您这样做,任何进一步检查 origin/foo 的尝试都会让您回到分离的头部状态!

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

这可能与您原来的问题无关,但是这个页面在谷歌上对“git detached head”的点击率很高,而且这种情况的记录严重不足。


这种情况似乎是欧文在上面的回答所谈到的——剪切和粘贴“origin/foo”使 git 将其视为“origin/origin/foo”。
N
Nesha Zoric

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

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

解决此问题的另一种方法是为新创建的提交创建一个新分支并对其进行签出。 git checkout -b <branch-name> <commit-hash>

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


F
Francisco C

在 VonC 的评论之后,这是我如何解决同样的“分离 HEAD”问题的简短版本。

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


A
Alexis Määttä Vinkler

分离头

HEAD 是指向当前签出的分支或提交的指针,它回答了以下问题:我现在在存储库中的什么位置? HEAD 可以在任一两种状态,attached(默认)或detached,这取决于您是否签出本地分支。

OP:我是如何得到一个分离的 HEAD 的?

操作比让 HEAD 处于分离状态

最终进入 detached HEAD 状态可能是由于各种原因,以下是 5 种常见情况(也许您做了以下任何一种情况):

使用其哈希检查特定提交,即 $ git checkout 14ko3

显式检出远程分支,即 $ git checkout origin/master

使用分离标志(Git 2.23)切换到分支,即 $ git switch master --detached

签出一个标签,即 $ git checkout v1.0.1

执行交互式变基(或包含冲突更改的常规变基),即 $ git rebase master feature-1 --interactive

detached 状态下可以进行实验性更改,而不会影响任何现有的分支。请参阅下面的信息图,说明处于附加状态与分离状态的 committing 之间的区别。

https://i.stack.imgur.com/1iPL0.png

一个常见的误解是消息 You are in 'detached HEAD' state 是错误的,而实际上它只是描述了 HEAD 如何引用当前快照。

从分离状态转变为附加状态

要从分离状态转移到附加状态,您可以从您所在的位置创建一个新分支,或者切换回现有分支。

注意:如果您切换到另一个现有分支,则在分离状态下创建的任何提交最终都将被丢弃(垃圾回收后),而无需先将更改保留在新分支中。

来源: 以上摘录来自这篇关于该主题的完整帖子:What is HEAD in Git?


D
Dharman

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

创建一个新分支(feb_debugging)。

运行 git 获取

我看到新分支(feb_debugging)被拉

现在,我使用 git checkout origin/feb_debugging

这让我到了 HEAD 现在在....

为了修复,我只需要另一个结帐

git checkout feb_debugging

现在 git 说我在 feb_debugging 分支。