我在一个分支中工作,需要撤消几个提交。所以我做到了

$> git reset --hard bd53134

这有了预期的效果,只是我现在有了一个独立的脑袋:(
$> git status
HEAD detached at bd53134

我该怎么解决?

最佳答案

看起来你可能还在胡思乱想,所以这里有一点背景。你在一篇评论中提到你开始了一个git rebase并且总是抱怨。(这真的应该是最初问题的一部分。)
首先注意:git rebase --continue可以正常(“未分离”?)或“分离”。“normal”HEAD只包含一个分支名称。如果您是“on branchHEAD”,master只会说“on branch master”。“分离的头”听起来像是法国大革命的东西,它由一个原始的sha-1提交id组成。我喜欢在下面的图形中写附加的头,作为HEAD,然后显示分支指向的位置,使用箭头指向一个特定的提交。
在开始一个rebase之前,您有一个commit图,它可能如下所示:

...- A - B - E - F         <-- master, origin/master
           \
             C - D         <-- HEAD=branch

在本例中,我假设您从HEAD=branch执行了git checkout -b branch操作,并在master上执行了一些提交操作(创建branchC),然后可能执行了Dgit checkout master操作,这将从“remotegit pull执行提交操作EF。然后用origin返回branch(因此git checkout branch)。
然后,您决定应在HEAD=branch的基础上重新建立CD的基础,给出更为线性的提交序列:
...- A - B - E - F         <-- master, origin/master
                  \
                   C' - D' <-- HEAD=branch

(稍后我将展示为什么这些是FC'而不是D'C)因此运行D将提交和git rebase master移动到C的顶端。
rebase实际上并不移动提交。它所做的是复制一些现有的提交,做出新的“做同样的事情”,“也一样好”(我们希望!)因此,rebase保持Dmaster左右。它使用一个特殊的标签C,来跟踪commitD(以及一堆额外的ORIG_HEAD文件来跟踪整个rebase操作的所有进度这些文件实际上是git如何知道rebase是“进行中”的)。
rebase通过添加这个D和“分离头”开始这个过程。它将“分离头”设置为直接指向rebase的目标(在本例中为commit.git/rebase-apply/)。(通过翻来翻去,似乎文档中也有关于它重置分支的内容。但这在旧版本的git中可能有所不同;我认为文档在某一点上是准确的)。
...- A - B - E - F         <-- master, origin/master
          \       \
           \       \...... HEAD [detached]
            \
             C - D         <-- ORIG_HEAD, branch

然后,对于每个提交(ORIG_HEADF这里),它获取在提交中所做的更改,并尝试将这些相同的更改应用于C提交。如果一切顺利,它通常会用与旧提交相同的消息进行新的提交。这就是承诺:
...- A - B - E - F         <-- master, origin/master
          \       \
           \       C'..... HEAD [detached]
            \
             C - D         <-- ORIG_HEAD, branch

成功地将D应用到HEAD以使C'退出C后,rebase命令继续尝试将F应用到新的(但仍分离的)C'F。但是,这次出现了问题:修补程序不适用:
CONFLICT ...
Failed to merge in the changes.
Patch failed at ...
The copy of the patch that failed is found in:
    ...

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".

此时,您的提交图看起来就像我在上面绘制的(有些混乱)图。
作为rebase prints,您可以:
手动解决问题并D,或
选择用HEAD删除提交(C',在本例中)或
git rebase --continue退出这一切。
选择最后一个选项,告诉rebase停止rebase尝试,将D恢复原样,并删除“rebase in progress”状态/跟踪文件。这还将删除整个新提交(但尚未标记为分支)链。(从技术上讲,他们仍然在那里,在重新登录。通常你不会看到他们。)
执行第一个(“手动解决”)或选择中间(“跳过”)选项,让rebase继续前进。假设您解决了问题并git rebase --skip。一旦rebase用完提交,并且最后一个提交是git rebase --abort,它就会将分支名称移到最后一个提交,并再次将HEAD设置为分支名称。在这种情况下,你会得到:
...- A - B - E - F         <-- master, origin/master
          \       \
           \       C' - D' <-- HEAD=branch
            \
             C - D         <-- ORIG_HEAD

由于git rebase --continue所指向的提交通常不会显示,因此看起来DHEAD已不存在,而副本(ORIG_HEADC)是仅存的提交。(与往常一样,DC'实际上仍在其中,并将停留一段时间,直到重新登录条目过期。)
考虑到所有这些,一旦您处于“分离的头”状态,D'就没有分支名称可影响。它将移动C,并更改工作目录,但D仍将直接指向提交。所以,你在一个回扣中间做的任何事情,嗯,充其量也很奇怪。(如果你继续这样做,他们会处理rebase发生的事情,因为继续一个rebase只会增加到当时git reset --hard点的位置。)
在更正常的情况下(当您“在分支上”时),HEAD具有分支的名称。然后(并且只有在那时),HEAD可以并且确实将分支名称指向的提交更改为。
如何判断git reset将采取哪些行动,以及发生了什么?答案是使用HEAD。如果你不确定发生了什么,HEAD是用来帮助你的。在过去的几年里,它在实际帮助方面也变得更好了!:-)

关于git - git:'git reset后分离的头--hard bd53134,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19923958/

10-10 09:52
查看更多