修复Git分离头?


1453

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

svn up .

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

git checkout HEAD^ src/

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

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


69
git checkout master将带您回到master分支。如果您想清除任何工作副本更改,则可能需要这样做git reset --hard
安倍·沃克


如果你有没有犯,你可以做了git checkout -- src/
thesummersign

试试这个:link。简而言之create temp branch - checkout temp branch - checkout master - delete temp branch
fidev

@AbeVoelker您在评论中是working copy changes什么意思?您是否参考签出另一次提交后对文件所做的更改(即,处于分离的头部状态时所做的更改)?
Minh Tran

Answers:


2147

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

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

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

git checkout master

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

git checkout -- path/to/foo

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

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

  1. 运行git branch tmp-这会将您的更改保存在名为的新分支中tmp
  2. git checkout master
  3. 如果您希望合并所做的更改master,请git merge tmpmaster分支运行。master运行后,您应该在分支上git checkout master

6
“这会将文件foo恢复到对其进行任何更改之前的状态。” ->它将恢复到索引中的状态-请编辑
Mr_and_Mrs_D 2013年

87
为什么首先发生此错误?这是我讨厌git的事情之一-有时是完全随机的行为。Mercurial从未遇到过此类问题。
紫罗兰色长颈鹿

97
@VioletGiraffe这既不是错误也不是随机的-它只是您签出上一次提交时存储库所处的状态。“分离的头部”是一个警告,如果您打算从该点开始做任何工作,则可能还希望创建或指向该分支。但是,如果您只是希望查看该标记或提交,则处于分离的头部状态并没有什么错。
尼尔·

22
如果您已致力于分离头,请不要执行此操作,请参阅其他答案。如果这样做,您可以在Previous HEAD position was 7426948...
KCD

9
@VioletGiraffe:基于Mercurial,您对正在发生的事情有一个心理模型,但是您正在使用Git。如果您不愿意调整自己的心理模型以适应Git的模型,那么事情将继续随机出现。就像您戴着VR护目镜在外面走来走去,并且您认为自己正在乘坐飞机,但实际上是在过马路。你会被汽车撞到的。
iconoclast

477

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

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

摘自:

如何处理超脱的提交


27
我发现这是首选的解决方案-特别是如果您希望保留签出单个版本时所做的更改。
adswebwork 2014年

10
@adswebwork:我同意。所有其他答案都建议恢复到先前的状态,并丢失在分离的头部状态下本地进行的更改。
Sk8erPeter 2014年

6
为什么不git stash呢?因为这是我想到的第一件事。创建一个新分支将是一个过大的杀伤力。
sumsumsign

2
您也可以git rebase my-temporary-work然后删除该分支,git branch -d my-temporary-work以便它看起来就像您首先提交给右分支一样。
佐尔坦

@geekay听起来git stash确实是此案例的理想工具。您能否写出建议的答案来实现这一目标?
佐尔坦

156

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

当您已经在此模式下进行了某些更改并且想要保存更改时,如何退出(“修复”)分离的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> …
    

git reset --hard正是是我需要的,因为我想要的上游是源和局部变化应该被删除。
马库斯·泽勒

伟大的答案,这个工作对我来说
MGLondon

130

分离头意味着:

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

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

  git checkout master

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

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

git branch  temp
git checkout master
git merge temp

2
完美,然后删除分支温度后
Davi Menezes

64

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

我提交了更改。

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

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

$ git checkout master
Switched to branch 'master'

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

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

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


2
这应该是答案。它会取回您的裸文件。
BlindWanderer 2014年

2
是的,这确实是最简单的事情-足够简单,无需下次下次搜索网络就可以记住。提交,记下哈希值,返回到您要提交的分支,并git cherry-pick <hash>
梅森

感谢您的解决方案。这有帮助。我还可以补充一点,我必须做一个“ git push origin master”,以便我的master和origin / master指向同一提交。
turnip424

1
这本质上是tanius的答案(发布于一年多以前)。
彼得·莫滕森

感谢这个愉快的选择,恢复了最后的分离头更改
Omega Cube

54

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

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,就像什么也没有发生一样。


2
给这个坏男孩加了书签-节省了创建临时分支的时间。工作了请客。
蒂姆·泰勒

1
在签出git子模块,然后对其进行更改后,我经常以分离的HEAD状态结束。我发现这是修复问题的最佳和最简便的解决方案,因此我可以保留所做的更改。
user5359531 18-10-31

1
如果您已经以分离状态提交更改,则此方法不起作用?
Danijel

40

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

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

git checkout myfile

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

git reset --hard HEAD^

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

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


1
正如我在@ralphtheninja的回答中所说,git checkout path/to/foo可能会与冲突git checkout some-branch,因此最好git checkout -- path/to/foo避免使用这些冲突。
Diego Lago

29

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

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

在此处输入图片说明

换一种说法:

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

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

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

在此处输入图片说明


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

在此处输入图片说明


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

在此处输入图片说明

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

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


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

在此处输入图片说明


6
没有看过,但是对您制作的漂亮照片投了赞成票;)。
卡洛·伍德

@Carlo,谢谢!
MarianD

22

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


1
请注意,在处于分离状态时,您将丢失所做的所有提交。
Ajak6

@ Ajak6您并不会真的丢失那些提交。它们仍然可以通过git reflog或通过新分支或通过git cherry-pick现有分支使用。看到这个问题
tanius

7

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

git cherry-pick

在此之前cherry-pick,a git checkout master是必需的。此外,仅需要commitin detached head


6

附录

如果您希望返回的分支是您最后一次结帐,则可以使用checkout @{-1}。这将带您回到之前的结帐。

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



2

当您处于独立状态并创建新文件时,请首先确保将这些新文件添加到索引中,例如使用:

git add .

但是,如果您仅更改或删除了现有文件,则可以通过以下方式同时添加(-a)和带有消息(-m)的提交:

git commit -a -m "my adjustment message"

然后,您可以使用以下命令以当前状态简单地创建一个新分支:

git checkout -b new_branch_name

您将拥有一个新分支,所有调整都将在该新分支中。然后,您可以根据需要继续推送到远程和/或结帐/拉动/合并。


1

Git告诉我该怎么做。

如果输入:

git checkout <some-commit_number>

保存状态

git add .
git commit -m "some message"

然后:

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

1

我想保留所做的更改,因此,我只是在解决此问题...

git add .
git commit -m "Title" -m "Description"
(so i have a commit now example: 123abc)
git checkout YOURCURRENTBRANCH
git merge 123abc
git push TOYOURCURRENTBRANCH

对我有用


1

通常HEAD指向分支。当它不指向分支时,而是当它指向提交哈希时,69e51则意味着您有一个分离的HEAD。您需要将其指向两个分支来解决此问题。您可以做两件事来修复它。

  1. git checkout other_branch //当您需要该提交中的代码时不可能 hash
  2. 创建一个新分支,并将提交哈希指向新创建的分支。

HEAD必须指向分支,而不是提交哈希是黄金法则。


这就是为什么我有这个错误。我签出了修订版,然后又签出了当前/最新修订版,而不是签出了分支,分支正确地连接了头部。谢谢您的帮助。
拉胡尔·塔库尔

1

分离的头部意味着您尚未正确检出分支或刚刚检出了一次提交。

如果遇到此类问题,请先存储本地更改,以免丢失更改。

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

假设您要分支MyOriginalBranch:

git checkout -b someName origin / MyOriginalBranch


1

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

尝试只是 git checkout your-branch


0
git pull origin master

为我工作。只是要明确给出远程和分支名称。


0

就我而言,我跑步git status,发现我的工作目录中有一些未跟踪的文件。

我只需要清洁它们(因为我不需要它们)即可运行我想要执行的重新设置。


0

这对我有用,它将为分离的头分配一个新的分支:

git checkout new_branch_name detached_head_garbage_name


0

分离的HEAD表示您当前不在任何分支上。如果您想保留当前更改并仅创建一个新分支,请执行以下操作:

git commit -m "your commit message"
git checkout -b new_branch

之后,您可能希望将此新分支与其他分支合并。总是有用的是git “ a dog”命令:

git log --all --decorate --oneline --graph
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.