修复一个Git分离的头?

Dan*_*iel 1318 git

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

svn up .
Run Code Online (Sandbox Code Playgroud)

使用git pull似乎没有用.一些随机搜索引导我到一个有人推荐做的网站

git checkout HEAD^ src/
Run Code Online (Sandbox Code Playgroud)

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

现在我发现我有一个超然的头.我不知道那是什么.我怎么撤消?

ral*_*nja 1924

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

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

你只需要检查你所在的分支,例如

git checkout master
Run Code Online (Sandbox Code Playgroud)

下次更改文件并希望将其恢复到索引中的状态时,请不要先删除文件,只需执行此操作

git checkout -- path/to/foo
Run Code Online (Sandbox Code Playgroud)

这会将文件foo恢复到索引中的状态.

如果要保持更改与分离的HEAD相关联

  1. git log -n 1; 这将显示分离的HEAD上的最新提交.复制并粘贴提交哈希.
  2. git checkout master
  3. git branch tmp <commit-hash>.这会将您的更改保存在一个名为的新分支中tmp.
  4. 如果您想要合并您所做的更改master,请git merge tmpmaster分支机构运行.master跑完后你应该在树枝上git checkout master.

  • @VioletGiraffe它既不是错误也不是随机的 - 它只是您检查先前提交时存储库进入的状态.如果您打算从那时开始做任何工作,"分离的头部"可以作为警告,您可能还想创建或指向分支.但是,如果您只是希望查看该标记或提交,则处于分离头状态没有任何问题. (87认同)
  • 为什么这个错误首先发生?这是我讨厌git的事情之一 - 有时是完全随机的行为.Mercurial从未遇到过这样的问题. (72认同)
  • 如果你已经致力于分离头,请不要这样做,请参阅其他答案.如果这样做,你可以查看以前的头部git提及`上一个HEAD位置是7426948 ...` (19认同)
  • @VioletGiraffe:你有一个基于Mercurial发生的事情的心智模型,但你正在使用Git.如果你不愿意调整你的心理模型以适应Git的模型,那么事情将继续随机出现.这就像你在外面走动,戴着VR护目镜,你认为你正在驾驶飞机,但你真的正在过马路.你会受到汽车的打击. (6认同)
  • "这会将文件foo恢复到对其进行任何更改之前的状态." - >它会将其恢复到_index_中的状态 - 请编辑 (5认同)
  • @nottinhill你为什么要与一个独立的头部承诺...?如果没有先创建分支,就会有明确的警告*而不是*. (2认同)
  • @Joshua如果你想返回到之前签出的任何提交(1、2或3等步骤),那么你可以看看“git reflog” (2认同)
  • 为了不丢失工作,请先备份您的文件夹(这就是我所做的)。 (2认同)
  • 最后,确保你的提交是`master`,你可以删除`tmp`本地分支:`git branch -d tmp` (2认同)
  • 您可以跳过分支位,直接执行 `git merge &lt;commit has&gt;` 。我不知道你为什么要在这里创建一个分支。 (2认同)
  • @BenRacicot:这也不是随机的——“origin/2020_05_05”是一个远程分支,无法直接签出。如果您不确定这是为什么,请考虑一下您实际上并没有控制远程分支,因为它位于另一台计算机上 - 因此您无法在没有网络连接的情况下提交或编辑它,并且 Git 仅需要一个获取/推/拉操作的网络连接。相反,您必须在本地分支上进行更改,然后推送它们。您可能只需要“git checkout 2020_05_05”,它将创建一个跟踪远程分支的本地分支(您可以编辑)。 (2认同)
  • @iconoclast 与其斥责 Violet Giraffe 有错误的心智模型,不如提供一些关于如何采用正确的 git 心智模型的提示,那就太好了。我从未使用过 Mercurial,但我和紫罗兰长颈鹿一样沮丧。不仅 git 的行为经常莫名其妙地随机,而且我读到的 90% 的解释都是完全无法理解的。每个人都说你必须拥有正确的心智模型,但没有人解释它是什么。新手需要从难以理解的解释中对该模型进行逆向工程——这几乎是不可能的任务。 (2认同)

Ton*_*mez 450

如果您更改了不想丢失的文件,可以推送它们.我已将它们以分离模式提交,之后您可以移动到临时分支以便稍后在master中集成.

git commit -m "....."
git branch my-temporary-work
git checkout master
git merge my-temporary-work
Run Code Online (Sandbox Code Playgroud)

摘自:

如何处理分离头中的提交

  • 我发现这是首选解决方案 - 特别是如果您想要保留在签出单个版本时所做的更改. (26认同)
  • @adswebwork:我同意.所有其他答案建议恢复到以前的状态并且在分离的头状态中丢失在本地进行的更改. (10认同)
  • 为什么不`git stash`?因为这是我想到的第一件事.创建一个新的分支将是一个矫枉过正. (5认同)
  • 你也可以`git rebase my-temporary-work`然后删除分支`git branch -d my-temporary-work`,这样看起来好像你首先提交到了正确的分支. (2认同)

tan*_*ius 144

没有创建临时分支的解决方案.

当您在此模式下已经更改了某些内容时,如何退出("修复")分离的HEAD状态,并且可选地,您希望保存更改:

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

    git commit -a -m "your commit message"
    
    Run Code Online (Sandbox Code Playgroud)
  2. 放弃您不想保留的更改.硬重置将丢弃您在分离的HEAD状态下所做的任何未提交的更改:

    git reset --hard
    
    Run Code Online (Sandbox Code Playgroud)

    (如果没有这个,第3步就会失败,抱怨分离的HEAD中修改过的未提交文件.)

  3. 看看你的分公司.通过检出之前处理过的分支退出分离的HEAD状态,例如:

    git checkout master
    
    Run Code Online (Sandbox Code Playgroud)
  4. 接管你的提交.您现在可以通过挑选来接管您在分离的HEAD状态下所做的提交,如我对另一个问题的回答所示.

    git reflog
    git cherry-pick <hash1> <hash2> <hash3> …
    
    Run Code Online (Sandbox Code Playgroud)


Raz*_*aul 125

分离头意味着:

  1. 你不再是一个分支,
  2. 您已在历史记录中检出了单个提交

如果没有更改:可以通过应用以下命令切换到master

  git checkout master
Run Code Online (Sandbox Code Playgroud)

如果您要保留更改:

在分离的HEAD的情况下,提交工作正常,除了没有命名分支更新.要使用已提交的更改更新主分支,请在您所在的位置创建临时分支(这样临时分支将具有您在分离的HEAD中所做的所有已提交的更改),然后切换到主分支并将临时分支与大师.

git branch  temp
git checkout master
git merge temp
Run Code Online (Sandbox Code Playgroud)

  • 完美,然后除去分支温度 (2认同)

Phi*_*ber 58

这是我刚刚意识到自己处于一个独立的头脑并且已经做出一些改变后我刚刚做的事情.

我承诺了改变.

$ git commit -m "..."
[detached HEAD 1fe56ad] ...
Run Code Online (Sandbox Code Playgroud)

我记得提交的哈希值(1fe56ad).然后我检查了我应该去的那个分支.

$ git checkout master
Switched to branch 'master'
Run Code Online (Sandbox Code Playgroud)

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

$ git cherry-pick 1fe56ad
[master 0b05f1e] ...
Run Code Online (Sandbox Code Playgroud)

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

  • 这应该是答案。它会取回您的裸文件。 (2认同)
  • 是的,这确实是最简单的事情-足够简单,无需下次下次搜索网络就可以记住。提交,记下哈希,返回要提交的分支,然后执行git cherry-pick &lt;hash&gt;。 (2认同)

moj*_*uba 45

如果你做了一些改变,然后意识到你是一个独立的头,有一个简单的解决方案:stash - > checkout master - > stash pop:

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'
Run Code Online (Sandbox Code Playgroud)

您将获得未经修改的更改和正常的"附加"HEAD,就像什么都没发生一样.

  • 已经为这个坏男孩添加了书签 - 节省了制作临时分支的费用。辛苦了。 (3认同)
  • 在检出 git 子模块后,我经常以分离的 HEAD 状态结束,然后对其进行更改。我发现这是修复问题的最佳和最简单的解决方案,因此我可以保留我的更改。 (2认同)
  • 如果您已经在分离状态下提交了更改,这不起作用? (2认同)

lar*_*sks 40

当您签出特定提交时git,您最终处于分离头状态...也就是说,您的工作副本不再反映命名引用的状态(如"master").这对于检查存储库的过去状态非常有用,但如果您实际尝试还原更改,则不是您想要的.

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

git checkout myfile
Run Code Online (Sandbox Code Playgroud)

这将丢弃任何未提交的更改,并将文件还原为当前分支头部的状态.如果要放弃已提交的更改,可能需要使用该reset命令.例如,这会将存储库重置为先前提交的状态,并丢弃任何后续更改:

git reset --hard HEAD^
Run Code Online (Sandbox Code Playgroud)

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

Git Book有更多细节.

  • 正如我在@ralphtheninja 的回答中所说,`git checkout path/to/foo` 可能与 `git checkout some-branch` 冲突,所以最好使用 `git checkout -- path/to/foo` 来避免这些冲突. (2认同)

Mik*_*ike 21

由于"分离头状态"让你在临时分支上,只需使用它就git checkout -会让你进入你所在的最后一个分支.

  • 请小心,您将丢失处于分离状态时所做的任何提交。 (2认同)
  • @Ajak6 你并没有真正丢失这些提交。它们仍然可以通过“git reflog”使用,并且可以接管到新分支或通过“gitcherry-pick”接管到现有分支。请参阅[此问题](/sf/ask/698895641/)。 (2认同)

小智 14

你可能做到了git reset --hard origin/your-branch

尝试只是 git checkout your-branch


Pat*_*RIA 8

在“分离头”中意味着 HEAD 指的是特定的未命名提交(与命名分支相反)(参见:https : //git-scm.com/docs/git-checkout部分Detached head)。实际上,这意味着您已检出提交,但没有与之关联的分支名称。

您可以选择仅通过以下方式创建与您的提交关联的新分支

git branch new-branch-name.

这允许您将当前状态保存在新分支中。

或者你可能想回到之前的状态然后这样做,你需要选择之前选择的分支

git checkout @{-1}


Dhi*_*tam 8

分离头意味着您没有正确检出您的分支,或者您刚刚检出一个提交。

如果您遇到这样的问题,请首先存储您的本地更改,以免丢失您的更改。

之后......使用以下命令签出您想要的分支:

假设您想要分支 MyOriginalBranch:

git checkout -b someName origin/MyOriginalBranch


小智 8

添加到@ralphtheninja 的答案。如果您在使用后收到此消息git checkout master

请在切换分支之前提交您的更改或隐藏它们。正在中止

然后您可以简单地使用 -f 标志强制签出,如下所示:

git checkout -f master
Run Code Online (Sandbox Code Playgroud)

显然,这将导致丢失在分离模式下所做的所有更改。所以使用时要小心。


Tim*_*imo 7

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

git cherry-pick

在此之前cherry-pick,a git checkout master是必要的.此外,它只需要一个commitin detached head.


Mar*_*anD 7

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

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

在此处输入图片说明

换一种说法:

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

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

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

在此处输入图片说明


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

在此处输入图片说明


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

在此处输入图片说明

正如可以看到,头部指向目标的的git checkout命令-的分支(四联的第一3个图像),或者(直接地)给一个提交(四联的最后一个图像)。

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


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

在此处输入图片说明

  • 缺少的是:“当我签出也是某个分支顶部的数字提交时,它会导致分离的头,还是会使用关联的分支?” 我的猜测是:“那就没有独立的头了” (2认同)

ale*_*xhg 7

这种方法可能会丢弃部分提交历史记录,但如果旧主分支和当前状态的合并很棘手,或者您根本不介意丢失部分提交历史记录,那么它会更容易。

为了简单地保持当前状态,而不进行合并,将当前分离的 HEAD 转变为主分支:

  1. 手动备份存储库,以防出现意外错误。
  2. 提交您想要保留的最后更改。
  3. 创建一个临时分支(我们将其命名为detached-head),其中将包含当前状态的文件:
git checkout -b detached-head
Run Code Online (Sandbox Code Playgroud)
  1. (a) 如果不需要保留master分支,则将其删除
git branch -D master
Run Code Online (Sandbox Code Playgroud)
  1. (b) 或者如果您想保留则重命名
git branch -M master old-master
Run Code Online (Sandbox Code Playgroud)
  1. 将临时分支重命名为新的 master 分支
git branch -M detached-head master
Run Code Online (Sandbox Code Playgroud)

图片来源:改编自Gary Lai 的这篇 Medium 文章


Jon*_*Raa 7

我也遇到过类似的情况。
由于某种原因,我最终得到了一个分离的头 - 我在与我认为自己所在的分支相同的路径上进行了提交 - 例如 HEAD 是分支标签的子级,但由于某种原因分支标签保留在历史记录中提交...可能是因为我已经推动了?

它不会让我推动,因为我不被认为是在我认为我所在的分支上。

我不想改变我的任何历史,也不想做任何挑剔,而且我刚刚在分支机构工作了大约 8 周,所以reset --hard让我有点紧张!

解决方案只是执行以下操作:

git branch -f myStuckBranch HEAD
git checkout myStuckBranch
Run Code Online (Sandbox Code Playgroud)

即使 HEAD 和 myStuckBranch 现在指向同一件事,您也需要进行结帐,因为您仍然被认为处于分离头状态(不在分支上)

我不是 git 专家(主要使用 Mercurial,它永远不会造成这种奇怪的情况),但我对这个命令的理解是它只是说“将 myStuckBranch 更改为指向 HEAD”。

我经常发现自己使用此命令在获取后合并 master 的更改,而无需交换我的工作目录 - 否则它会尝试使用 master 的旧(无趣)版本:

git fetch
git branch -f master origin/master  -- err yeah don't just ignore what's been going on remotely - eg point my master at the real master
git merge master -- merge the changes into my local branch
Run Code Online (Sandbox Code Playgroud)

必须一直手动执行此操作有点烦人,但仍然比必须更改工作目录只是为了更新另一个分支以合并其中的更改要好。


Ste*_*iaz 6

Git 告诉我该怎么做。

如果您输入:

git checkout <some-commit_number>
Run Code Online (Sandbox Code Playgroud)

保存状态

git add .
git commit -m "some message"
Run Code Online (Sandbox Code Playgroud)

然后:

 git push origin HEAD:<name-of-remote-branch>
Run Code Online (Sandbox Code Playgroud)


BG *_*uno 6

Git :您当前不在分支上。

Git时不时地显示:

要立即推送导致当前(分离的 HEAD)状态的历史记录,请使用

git push origin HEAD:<name-of-remote-branch>

它的意思是 :

要修复该问题,请运行 2 个命令:

  1. git branch -f {{your_working_branch}} HEAD-- 将分支设置到你的头上
  2. git checkout {{your_working_branch}}--签出==切换分支


Dav*_*wer 5

附录

如果您要返回的分支是您最后一次结账,您可以简单地使用checkout @{-1}.这将带您回到之前的结账时间.

此外,您可以使用例如别名此命令,git global --config alias.prev以便您只需键入git prev以切换回上一个结帐.


归档时间:

查看次数:

1278001 次

最近记录:

6 年 前