乍一看,这看起来像是Fix a Git detached head? 它在某些方面是,而不是在其他方面。此外,正如 Thorbjørn Ravn Andersen 在各种评论中所说,您可能还想与其他同事进行协调。但是,让我们做一些不在(并且实际上不适合)其他问题的注释。
一个分离的 HEAD 不会改变任何东西——反正现在还没有
首先,“分离的 HEAD”仅仅意味着你已经签出了一个特定的提交,通常是通过它的哈希 ID。this 和 之间只有一个功能差异,因为它还检查了一个特定的提交,这听起来像是一个循环定义,因为它是:不同之处在于,当你这样做时,你在一个分支上,而当你这样做时这个,你不在一个分支上,也就是说,你有一个分离的 HEAD。git checkout branch-name
因此,所有“分离的 HEAD”意味着“不在分支上”。也就是说,如果您签出一个特定的提交并进入一个分支,那么您就是“在一个分支上”,正如git status
将要说的那样;但是,如果您签出相同的特定提交并且没有进入分支,那么您将有一个“分离的 HEAD”,正如git status
将要说的那样。
git checkout
是您上或下分支的方式
只有一个面向用户的 Git 命令可以进入任何特定的分支,或者分离你的 HEAD 以离开一个分支,那就是git checkout
. 如果您git checkout
是一个分支名称,它会检查该提交并将您置于分支上。如果你git checkout
有其他任何东西——包括标签、远程跟踪分支或原始哈希 ID——它会给你一个分离的 HEAD。因此,就像在其他问题的已接受答案中一样,如果您只想回到 branch master
,您只需git checkout master
.
你跑了git checkout 1234567
或类似的,检查一个较旧的提交,现在有一个“分离的 HEAD”。
但git checkout
也会更新您的索引和/或工作树
(这里非常简短的提醒:工作树是 Git 写入和读回的地方,您最终将作为提交永久保存在存储库中的内容的副本。它采用计算机系统的其余部分可以理解的形式,而不是 Git-特定的形式。索引是你和 Git 构建下一次提交的地方;它是非常特定于 Git 的形式,并且有一些额外的 goop 可以在特定于 Git 的内部形式和“正常计算机使用”形式之间进行协调。提交实际上是保存的索引,减去额外的 goop。)
显然,您的服务器正在运行工作树 - 而您首先运行的原因git checkout 1234567
是因为分支的尖端提交master
,即 1234567 以外的某个提交,不起作用。如果您git checkout master
要通过恢复提示提交来重新破坏服务器。
这是您需要与他人协调的地方,因为要重新连接您的 HEAD,您现在必须至少执行以下两项操作:
要创建新分支,请使用git checkout -b newbranch
如果您想并且被允许让服务器“在一个分支上”而不更改提交,只需创建一个新分支,其尖端是当前提交。为此,请使用git checkout -b
:
git checkout -b mostly-working
mostly-working
现在您的 HEAD 已附加到您刚刚创建的分支上。索引和工作树没有任何反应,因为新的分支mostly-working
名称提交 1234567(或您之前签出的任何一个)。
这个提交可能在后面的某个地方master
。git checkout -b
也就是说,如果我们要绘制提交图的一部分,在我们做这件事之前,它看起来像这样:
...--o--o--*--o--o <-- master
^
commit 1234567
HEAD
所做git checkout -b
的只是添加一个指向同一个提交的新名称。为了用纯文本绘制它,我们需要向上或向下推动一些提交(我会选择向上):
o--o <-- master
/
...--o--o--* <-- mostly-working (HEAD)
^
still commit 1234567
由于我们没有移动commits,索引和工作树保持不变。
如果您现在进行新的提交,他们会推进分支
为了完成上述内容,让我们看看如果您修改工作树中的某些内容会发生什么git add
, 和git commit
。Git 将在新分支上进行新的提交mostly-working
:
o--o <-- master
/
...--o--o--o--* <-- mostly-working (HEAD)
(顺便说一句,我在*
这里使用标记当前提交,git branch
标记当前分支)。
分离的 HEAD 也会发生同样的事情
假设您没有执行git checkout -b
,但确实修改了文件并提交。这将像往常一样进行新的提交——但不是在分支上,新的提交将是新的分离的 HEAD。也就是说,我们将像这样绘制新的提交:
o--o <-- master
/
...--o--o--o--* <-- HEAD
那么,这就是“在分支上”和“分离的 HEAD”之间的区别。“在一个分支上”并没有什么特别之处,只是新的提交在提交时会推进那个分支。分支名称指向分支的尖端。当您git checkout
创建分支时,您会检查该分支的最尖端提交。当您进行新的提交时,您可以将它们添加到分支中,方法是将名称指向新的提交。(新的提交本身指向前一个HEAD
提交。)因为HEAD
只是说哪个分支是当前的,更新分支名称以指向新的提交也会更新HEAD
以指向新的提交。
当你有一个分离的 HEAD 时,过程完全一样:新的提交指向前一个提交,新的提交成为新的HEAD
提交。这个提交没有名字HEAD
(当然,除了,但是HEAD
当你改变时git checkout
!)。