修复 Git 分离头?

我在存储库中进行了一些工作,发现文件有本地更改。我不再想要它们了,所以我删除了文件,以为我可以签出新副本。我想做相当于

svn up .

使用git pull似乎没有用。一些随机搜索将我带到一个有人建议这样做的站点

git checkout HEAD^ src/

src是包含已删除文件的目录)。

现在我发现我有一个超脱的头。我不知道那是什么。我该如何撤消?

答案

分离的头部意味着您不再在分支上,您已签出历史记录中的单个提交(在这种情况下,是 HEAD 之前的提交,即 HEAD ^)。

如果要删除与分离的 HEAD 相关的更改

您只需要签出您所在的分支,例如

git checkout master

下次更改文件并想将其还原到索引中的状态时,不要先删除文件,只需执行

git checkout -- path/to/foo

这会将文件 foo 恢复为索引中的状态。

如果您想使更改与分离的 HEAD 相关联

  1. 运行git log -n 1 ; 这将在分离的 HEAD 上显示最新的提交。复制提交哈希。
  2. 运行git checkout master
  3. 运行git branch tmp <commit-hash> 。这会将您的更改保存在名为tmp的新分支中。
  4. 如果要将所做的更改git merge tmpmaster ,请从master分支中运行git merge tmp 。运行git checkout master之后,您应该在master分支上。

如果您不想丢失文件,可以将其推送。我已将它们提交为分离模式,然后您可以移至临时分支以稍后集成到 master 中。

git commit -m "....."
git branch my-temporary-work
git checkout master
git merge my-temporary-work

摘自:

如何处理超脱的提交

不创建临时分支的解决方案。

当您已经在此模式下进行了某些更改并且想要保存更改时,如何退出(“修复”)分离的 HEAD 状态:

  1. 提交要保留的更改。如果要接管在分离的 HEAD 状态下所做的任何更改,请提交它们。喜欢:

    git commit -a -m "your commit message"
  2. 放弃您不想保留的更改。硬重置将放弃您在分离的 HEAD 状态下所做的所有未提交的更改:

    git reset --hard

    (否则,第 3 步将失败,抱怨在分离的 HEAD 中修改了未提交的文件。)

  3. 查看您的分支。通过检出您之前处理过的分支来退出分离的 HEAD 状态,例如:

    git checkout master
  4. 接管您的提交。现在,您可以通过选择樱桃来接管处于分离 HEAD 状态的提交,如我对另一个问题的回答所示。

    git reflog
    git cherry-pick <hash1> <hash2> <hash3> …

分离头意味着:

  1. 您不再在分支机构
  2. 您已经在历史记录中签出了一次提交

如果没有更改:可以通过应用以下命令切换到主服务器

git checkout master

如果您要保留更改,请执行以下操作:

如果是分离的 HEAD,则提交工作与正常工作相同,只是没有命名分支得到更新。要使用已提交的更改更新 master 分支,请在您所在的位置创建一个临时分支(这样,该临时分支将具有您在分离的 HEAD 中所做的所有提交的更改),然后切换到 master 分支并合并与大师。

git branch  temp
git checkout master
git merge temp

这是我意识到自己处于超脱状态并且已经进行了一些更改之后所做的事情。

我提交了更改。

$ git commit -m "..."
[detached HEAD 1fe56ad] ...

我记得提交的哈希值(1fe56ad)。然后,我签出了我应该一直在的分支。

$ git checkout master
Switched to branch 'master'

最后,我将提交的更改应用于分支。

$ git cherry-pick 1fe56ad
[master 0b05f1e] ...

我认为这比创建临时分支要容易一些。

如果您进行了一些更改然后意识到自己处在分离状态,则有一个简单的解决方案:存放 -> 结帐母版 -> 存放弹出:

git stash
git checkout master   # Fix the detached head state
git stash pop         # ... or for extra safety use 'stash apply' then later 
                      # after fixing everything do 'stash drop'

您将拥有未提交的更改和正常的 “附加” HEAD,就像什么也没有发生一样。

当您在git签出特定的提交时,您最终会处于分离的头部状态…… 也就是说,您的工作副本不再反映命名引用(例如 “master”)的状态。这对于检查存储库的过去状态很有用,但是对于您实际上想要还原的更改却不是您想要的。

如果您对特定文件进行了更改,而只想放弃它们,则可以使用checkout命令,如下所示:

git checkout myfile

这将丢弃所有未提交的更改,并将文件还原到当前分支头中的任何状态。如果要放弃已提交的更改,则可能要使用reset命令。例如,这会将存储库重置为上一次提交的状态,并丢弃所有后续更改:

git reset --hard HEAD^

但是,如果您要与其他人共享存储库,则git reset可能会造成破坏(因为它会删除存储库历史记录的一部分)。如果您已经与他人共享更改,则通常需要查看git revert ,它会生成一个 “反提交”(anticommit)- 也就是说,它会创建一个新的提交来 “撤消” 有问题的更改。

《 Git Book》有更多详细信息。

由于 “头分离状态” 使您处于临时分支,因此只需使用git checkout -它将使您进入上一个分支。

HEAD 在指针中,因此它直接或间接指向特定的提交:

附加的 HEAD 表示它已附加到某个分支 (即,它指向一个分支)。
分离的 HEAD 表示它没有连接到任何分支,即它直接指向某个提交。

在此处输入图片说明

换一种说法:

  • 如果直接指向提交,则 HEAD 被分离
  • 如果它间接指向一个提交(即,它指向一个分支,而分支又指向一个提交),则将附加 HEAD。

为了更好地了解已连接 / 已分离的 HEAD 的情况,让我们展示导致上述图片四合一的步骤。

我们从存储库的相同状态开始(所有象限中的图片都相同):

在此处输入图片说明


现在,我们要执行git checkout -在各个图片中使用不同的目标(它们上方的命令变灰以强调我们仅应用这些命令):

在此处输入图片说明


执行以下命令就是这种情况:

在此处输入图片说明

如您所见,HEAD 指向git checkout命令的目标 - 指向一个分支 (四足动物的前 3 个图像),或(直接)指向一个提交 (四足动物的最后一个图像)。

工作目录的内容也被更改为与适当的提交(快照)一致,即与 HEAD 指向(直接或间接)提交有关。


因此,我们现在处于与此答案开头相同的状态:

在此处输入图片说明

为了进一步阐明 @Philippe Gerber 的答案,这里是:

git cherry-pick

cherry-pick之前,这种情况下需要git checkout master 。此外,只需要一个commitdetached head