恢复最近的分离 HEAD 状态

120

我的项目遇到了一个大问题:情况如下。 我在Git下有一个Xcode项目。今天我发现最近一次提交破坏了一些测试,所以我检查了上一次提交。 我使用了SourceTree,出现了以下警告:

这样做将使您的工作副本处于“分离的HEAD”状态,这意味着您不再位于任何分支上。如果您想在此之后提交,您可能需要再次切换到分支或创建新的分支。是否确定?

我工作了整整一天,最后提交了所有内容。 因此,我需要将我的工作合并到develop分支上,所以我切换到develop分支...然后我的工作立即消失了:(

我知道分离我的HEAD是错误的,Sourcetree也警告了我...但是有没有办法恢复我的工作呢?


这里有一个关于同样问题的相关线程链接,以及它发生的技术细节链接 - RBT
这个回答解决了你的问题吗?如何将分离的HEAD与master/origin合并? - mkrieger1
7个回答

343
如果您键入git reflog,它将向您显示HEAD指向的修订历史记录。你的分离头应该在其中。找到后,执行 git checkout -b my-new-branch abc123git branch my-new-branch abc123(其中 abc123 是分离 HEAD 的 SHA-1)以创建指向您分离头的新分支。现在您可以在方便的时候合并该分支。
通常,在从分离头工作后检出分支后,如果需要,Git 应告诉您从哪个分离头转移到的提交。我从未使用过 SourceTree,所以我不知道它是否传递了该消息。但是,如果它确实显示了该消息,则应该能够使用其找到提交,并再次使用 git checkout -b git branch 从该提交创建一个分支。

我是git的新手.. 我遇到了“fatal: A branch named 'mybranch' already exists.”的问题。如何添加到现有分支? - Ramesh Murugesan
1
要简单地回到特定分支上的原始HEAD,只需使用git checkout <mybranch>命令。 - mmell
致命错误:默认修订版“HEAD”无效。 - Aequitas
2
作为对所有感谢Brian的人的公告:如果你正在进行不想丢失的工作,请每隔几个小时将其推送到远程(例如github)。当流星撞击你的电脑时,你会庆幸自己这样做了。如果你还没有准备好与合作者分享它,只需将其放在现在没有人知道的分支中,然后稍后将其重新基于主分支。 - MatrixManAtYrService
4
此外,如果只是单个丢失的提交突然消失了,而你在那里找到了它,你可以使用 git cherry-pick e5b2f7b 将其恢复,其中 e5b2f7b 是该提交的 SHA-1。 - Aidin
显示剩余3条评论

14
在Sourcetree中,您可以使用GUI来执行此操作。
首先,在命令历史记录(视图:显示命令输出)中查找“丢失”的提交信息。它可能在您丢失的提交之后的“切换分支”命令中。在该消息中,希望您能看到包含1234567提交ID的提交注释。
将该提交ID带入下一步。
点击顶部工具栏的“分支”按钮,您应该会得到一个名为“新建分支”的对话框,您可以在其中指定一个特定的提交。在那里输入提交ID,指定一个新的分支名称,点击“创建分支”,就可以获得一个包含您丢失的提交的新分支! 输入图像描述

1
确保你看到了正确的提交ID注释。实际上运行。 - TheTechGuy
@blalond 你好,看完你的回答后,我有一个小问题:当我在SourceTree中双击以前的提交记录(以便检查它)时,我会收到相同的消息,即这将导致分离头部,所以我想知道当人们说你可以简单地使用git回滚到任何以前的版本时,这意味着什么?那么如何回滚到特定的提交记录呢?谢谢。 - user285372

11
  1. 首先,运行 git reflog 命令查看历史记录。
  2. 最早的修订版本将会在列表的最后。
  3. 使用命令 git checkout -b temp e35d2b3 切换到您想要的提交版本。这里的 e35dd23 是您提交版本的哈希值。
  4. 完成了以上步骤后,只需执行 git add . 等命令即可...

如果解决了您的问题,请接受此回答。否则,请提出您的评论。


5

如果您不想保留分离的HEAD更改并希望转到最新的分支提交,请直接使用下面的命令。

git checkout - 

注意:我会删除在分离的HEAD中所做的所有更改。


OP 要求保留他们的工作。这并没有回答原始问题。只是添加将其保留在分支中的选项将使此答案有用。 - manuelvigarcia
恶意回答!!!!!!!!!! - undefined

1
我的一个同事遇到了这种情况。在他的情况下,提交是在分离的头部进行的--他们使用R-Studio--工具确实警告他们可以使用此和那个SHA参考创建分支...但由于唯一的选项是“关闭”--呃!它是一个信息框--他们关闭了对话框并永远失去了信息...感谢reflog命令,我们可以看到更改没有丢失。但在我们的情况下,git branch没有按预期工作...或者一个传入的git pull以某种方式搞砸了它。我们不得不从reflog中提取更改到新创建的分支:
 git cherry-pick 0b823d42..3cce27fc

我们将所有想要的提交放在分支中。然后,我们可以将该分支无问题地合并到develop中。

以防万一这对任何人有用,我们通过查看标记为“checkout”的提交(表示分支切换)之间的提交,在reflog中识别了分离头上的提交:

e09f183b HEAD@{3}: pull: Fast-forward
b5bf3e1d HEAD@{4}: checkout: moving from lost_changes to develop
b5bf3e1d HEAD@{5}: checkout: moving from 3cce27fca50177a288df0252f02edd5da5ee64fd to lost_changes
3cce27fc HEAD@{6}: commit: add statistics
417a99a4 HEAD@{7}: commit: add test
0b823d42 HEAD@{8}: commit: new utility class
d9ea8a63 HEAD@{9}: checkout: moving from develop to d9ea8a635d4c2349fcb05b3339a6d7fad5ae2a09
b5bf3e1d HEAD@{10}: pull: Fast-forward

我们需要的是从HEAD@{8}HEAD@{6}(包括两者)。所以我们通过以下方式获取它们:
git cherry-pick 0b823d42..3cce27fc

然后进行通常的合并解决和最终提交,留下了分离头部工作的分支 lost_changes。将其合并到 develop 分支是快进的。


0

我尝试了这个场景,并发现git告诉我上一个提交的SHA-1:

vors@localhost:~/git-test$ git checkout master 
Warning: you are leaving 1 commit behind, not connected to
any of your branches:

  ec600e6 333

If you want to keep them by creating a new branch, this may be a good time
to do so with:

 git branch new_branch_name ec600e6eb2473dd4f3732539c5c1fa5829f631b7

Switched to branch 'master'

你看到这条消息了吗?


不行或者可能是我没有注意到。我正在寻找Time Machine的备份;( - IgnazioC
1
@IgnazioC 你不需要查看备份。你看了我的回答吗?git reflog应该能显示你需要的内容。 - Brian Campbell

0

只要你不想做任何更改,分离的 HEAD 就没问题。

如果你想撤销一个提交,可以在特定分支上使用 git revert。

如果你想在分离的 HEAD 上工作并进行提交,请创建一个新分支(稍后合并它)。


是的!我们确实知道规则。但当同事们在脱离主题的情况下工作,然后提交代码时,他们寻求的是答案,而不是规则。 - manuelvigarcia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接