我今天最终得到了一个分离的头,与中描述的问题相同: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>
并意外地指定了一个修订版。
git status
时,Git 告诉我该怎么做:all conflicts fixed: run "git rebase --continue"
git checkout remotes/origin/my-branch
而不是 git checkout my-branch
或 git checkout origin/my-branch
,也会发生这种情况。
任何不是您的分支名称的提交的检出都会让您获得一个分离的 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>
如果
没有更多的错误!不再有多余的分离 HEAD!
如果您使用 git switch <tag>
而不是 git switch --detach <tag>
,则 Git 2.36 will help you to remember the missing --detach
option。
我刚才无意中复制了这个:
列出远程分支 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
它会自动回退到原点
git checkout -b Feature/f1234
<=> git branch Feature/f1234
和 git checkout Feature/f1234
。
origin/branchname
时,它会寻找 origin/origin/branchname
来告诉你第一个是你使用 -b
的远程名称,如果你不这样做,它会创建一个分离的 anonymous
分支.同样,如果要从不同的遥控器签出,则必须提及 -b
参数,否则 git 无法知道它来自新的遥控器,它会查找 origin/remote/branchname
。
尝试
git reflog
这为您提供了过去如何移动 HEAD 和分支指针的历史记录。
例如:
88ea06b HEAD@{0}:结帐:从 DEVELOPMENT 移动到 remotes/origin/SomeNiceFeature e47bf80 HEAD@{1}:pull origin DEVELOPMENT:快进
此列表的顶部是人们可能会遇到 DETACHED HEAD 状态的一个原因......检查远程跟踪分支。
Detached HEAD
表示当前签出的不是本地分支。
会导致 Detached HEAD
状态的一些场景:
如果您签出远程分支,请说 origin/master。这是一个只读分支。因此,当从 origin/master 创建提交时,它将是自由浮动的,即不连接到任何分支。
如果您签出特定标签或提交。从这里进行新提交时,它将再次自由浮动,即不连接到任何分支。请注意,当一个分支被签出时,新的提交总是被自动放置在尖端。当您想返回并签出特定的提交或标签以从那里开始工作时,您可以创建一个源自该提交的新分支并通过 git checkout -b new_branch_name 切换到它。这将阻止 Detached HEAD 状态,因为您现在已签出分支而不是提交。
如果您有一个与分支名称相同的标签,则可能会发生这种情况。
示例:如果“release/0.1”是标签名称,则
git checkout release/0.1
在“release/0.1”处产生分离的 HEAD。如果您希望 release/0.1 是一个分支名称,那么您会感到困惑。
git pull --prune --tags
) 不起作用,所以我使用 git tag -l | xargs git tag -d
删除本地标签并使用 git fetch --tags
重新获取远程标签
如果 git 要重命名 detached HEAD
,我会将其命名为 一个未被分支识别且很快会被遗忘的 HEAD。
我们作为人们可以很容易地记住分支名称。我们做git checkout new-button-feature
/ git checkout main
。 main
和 new-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 log
的输出 - 您可以在此处粘贴自上次成功提交以来的日志尾部,我们都可以看到您做了什么。或者,您可以将其粘贴并在 freenode IRC 上的 #git
中很好地询问。
一个简单的意外方法是将 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
checkout -b
,它看起来像一个结帐但实际上是分支),但另一个列表是受欢迎的。
进入 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”的点击率很高,而且这种情况的记录严重不足。
当您签出提交 git checkout <commit-hash>
或远程分支时,您的 HEAD 将被分离并尝试在其上创建新提交。
任何分支或标签无法访问的提交将在 30 天后被垃圾收集并从存储库中删除。
解决此问题的另一种方法是为新创建的提交创建一个新分支并对其进行签出。 git checkout -b <branch-name> <commit-hash>
本文说明了如何进入 detached HEAD 状态。
在 VonC 的评论之后,这是我如何解决同样的“分离 HEAD”问题的简短版本。
在我的遥控器中创建了一个分支; origin/feature/dev 在我的本地运行 git fetch,所以现在我的本地将知道这个新的远程分支现在运行 git switch feature/dev,我们就完成了!
分离头
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?
就我而言,它是这样发生的:
创建一个新分支(feb_debugging)。
运行 git 获取
我看到新分支(feb_debugging)被拉
现在,我使用 git checkout origin/feb_debugging
这让我到了 HEAD 现在在....
为了修复,我只需要另一个结帐
git checkout feb_debugging
现在 git 说我在 feb_debugging 分支。
master
在上图中的ed489
处,git checkout ed489
会给您一个分离的 HEAD,而git checkout master
不会。"You can think of this as an anonymous branch"
:) 我喜欢这个比喻