Git- 解决服务器上分离的 HEAD

Git- Resolve Detached HEAD on server

我对 Git 还很陌生- 自从我开始为我现在的雇主工作后才开始使用它。

我最近对服务器进行了一些更改,合并了一位同事在我本地开发机器上实施的错误修复。为此,我从服务器上拉取了他们已实施错误修复的 branch,并将其与我的本地 master 分支合并,该分支与代码的实时版本保持同步.我在我的本地开发机器上测试了这个,它似乎工作正常,所以我把它推送到服务器。

然而,我所做的更改似乎在实时版本中引入了另一个错误(它引入的错误在本地测试修复时并不明显,并且仅在代码上线后才出现)。

我引入的这个错误实际上导致公司内部网站的一个经常使用的部分无法访问,所以我立即检查了最后一个工作commit并重新启动了服务器,以便该网站可以访问再次.

我现在正在努力解决修复程序在我的本地开发机器上引起的问题,然后再将修复程序再次推送到服务器,但是在服务器上检查了一个旧的 commit 已经离开项目的实时版本处于 detached HEAD 状态。它所处的 detached HEAD 状态目前主要是正常运行的(即它的工作方式与我的同事开始修复此错误之前的状态相同 - 因此该错误仍然存​​在)。

我现在想解析服务器上的detached HEAD,这样我就可以再次从服务器上提取工作代码,从这里重新开始,但我不确定我是如何'match' 我目前正在使用 detached HEAD 的其余代码。

如果我在服务器上 运行 git branch ,输出显示我只有 master 分支(它被破坏了——因为它有我在推送时引入的错误原始错误修复)和 (detached from 0e57d3d),这是当前指向的 HEAD

我看过的其他帖子似乎表明我应该检查 master 以解决 detached HEAD,但我不能这样做,因为我知道 master 目前已损坏。

那么我如何才能再次 'attach' HEAD,以便代码像在 commit HEAD 期间所处的状态一样工作?指的是?我会从那里 运行 一个 git branch,然后检查 branch,并将其设为 master 吗?或者有其他方法可以做到这一点吗?

乍一看,这看起来像是 Fix a Git detached head? 的副本,它在某些方面是重复的,而在其他方面则不是。此外,正如 Thorbjørn Ravn Andersen 在各种评论中所说,您可能还想与其他同事进行协调。但是,让我们做一些笔记,这些笔记不在(并且不真正符合)另一个问题。

分离的 HEAD 不会改变任何东西——至少现在还没有

首先,"detached HEAD" 仅表示您已经签出一个特定的提交,通常是通过其哈希 ID。这与 git checkout <em>branch-name</em> 之间只有一个功能差异,因为 also 检查一个特定的提交,这听起来像是一个循环定义,因为它 :区别在于当你这样做时,你在 b运行 ch,当你这样做时,你不在 b运行ch 上,也就是说,你有一个分离的 HEAD。

因此,所有"detached HEAD"的意思是"not on a branch"。也就是说,如果你签出一个特定的提交 得到一个 b运行ch,你是 "on a branch",正如 git status 会说的那样;但是如果你签出相同的特定提交并且进入b运行ch,你有一个"detached HEAD",正如git status会说的.

git checkout 是您上下车的方式 b运行ch

只有一个 user-oriented Git 命令可以进入任何特定的 b运行ch,或者分离你的 HEAD 以离开 b运行ch,那就是git checkout。如果您 git checkout a b运行ch name,它会检查该提交并将您放在 b运行ch 上。如果你 git checkout 任何其他东西——包括一个标签,或者一个 remote-tracking b运行ch,或者一个原始哈希 ID——它会给你一个分离的 HEAD。因此,就像其他问题的公认答案一样,如果您只想回到 b运行ch master,您只需 git checkout master.

你 运行 git checkout 1234567 或类似的,检查一个旧的提交,现在有一个 "detached HEAD".

但是 git checkout 也会更新您的索引 and/or work-tree

(这里非常简短的提醒:work-tree 是 Git 写入和读回您最终永久保存的副本的地方,作为提交存储库。它的形式是 rest 计算机系统理解的形式,而不是 Git-specific 形式。index 是哪里你和 Git 构建你将要做出的 next 提交;它采用非常 Git-specific 的形式,并且有一些额外的 goop 来协调 Git-specific 内部形式和 "normal computer use" 形式。commits 实际上是保存的索引,减去额外的 goop。)

显然,您的服务器 运行 关闭了 work-tree — 原因 您 运行 git checkout 1234567 在第一名是因为 b运行ch master 的提交是 1234567 以外的提交,它不起作用。如果您 git checkout master 您将 re-break 服务器,通过恢复提示提交。

这是你需要与他人协调的地方,因为为了 re-attach 你的 HEAD,你现在必须至少做以下两件事中的一件:

  • 创建 new b运行ch,或
  • re-break服务器,至少是暂时的。

要创建一个新的 b运行ch,使用 git checkout -b <em>newb运行ch</em>

如果您想要并且被允许,让服务器 "on a branch" 没有 更改 commits,只需创建一个新的 b运行ch,其提示是当前提交。为此,请使用 git checkout -b:

git checkout -b mostly-working

现在您的 HEAD 已附加到您刚刚创建的 b运行ch mostly-working 上。索引和 work-tree 没有任何变化,因为新的 b运行ch 名称 mostly-working names 提交 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

因为我们没有移动提交,索引和work-tree保持不变。

如果您现在进行 new 提交,他们会推进 b运行ch

为了完成上面的内容,让我们看看如果在 work-tree、git addgit commit 中修改某些内容会发生什么。 Git 将在新的 b运行ch mostly-working:

上进行新的提交
             o--o   <-- master
            /
...--o--o--o--*   <-- mostly-working (HEAD)

(顺便说一句,我在这里使用 * 来标记当前提交,la git branch 标记当前 b运行ch)。

分离的 HEAD 也会发生同样的事情

假设您没有执行git checkout -b,但确实修改文件并提交。这将像往常一样进行新的提交——但不是在 b运行ch 上,新的提交将是新的分离的 HEAD。也就是说,我们会像这样绘制新的提交:

             o--o   <-- master
            /
...--o--o--o--*   <-- HEAD

那么,这就是 "on a branch" 和 "on a branch" 之间的区别"detached HEAD"。 "on a branch" 除了新提交的没有什么特别之处,推进b运行ch。 b运行ch name指向b运行ch的尖端。当你 git checkout b运行ch 时,你检查了那个 b运行ch 的 tip-most 提交。当您进行 new 提交时,您通过使名称指向新提交,将它们 添加到 b运行ch。 (新的提交本身指向之前的 HEAD 提交。)因为 HEAD 只是说哪个 b运行ch 是当前的,将 b运行ch 名称更新为指向新提交也会更新 HEAD 以指向新提交。

当你有一个分离的 HEAD 时,过程完全相同:新的提交指向前一个提交,新的提交成为新的 HEAD 提交。这个提交没有 name(好吧,当然 HEAD 除外,但是当你 git checkoutHEAD 会改变!)。