1819

我正在我的存储库中做一些工作,并注意到一个文件有本地更改。我不再想要它们,所以我删除了文件,以为我可以签出一个新副本。我想做的 Git 相当于

svn up .

使用git pull似乎不起作用。一些随机搜索把我带到了一个有人推荐做的网站

git checkout HEAD^ src/

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

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

4

26 回答 26

2635

分离的头意味着你不再在一个分支上,你已经签出了历史中的一个提交(在这种情况下是 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 tmpmastermastergit checkout master
于 2012-04-19T13:32:58.277 回答
538

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

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

摘自:

如何处理在分离的头脑中进行的提交

于 2013-12-09T20:05:28.313 回答
188

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

当您已经在此模式下更改了某些内容并且(可选)想要保存更改时,如何退出(“修复”)分离的 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> …
    
于 2013-06-11T13:23:11.853 回答
150

分离头的意思:

  1. 你不再在树枝上,
  2. 您已签出历史记录中的单个提交

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

  git checkout master

如果您有想要保留的更改:

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

git branch  temp
git checkout master
git merge temp
于 2016-08-29T00:39:15.080 回答
105

HEAD 是一个指针,它直接或间接地指向一个特定的提交:

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

在此处输入图像描述

换句话说:

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

为了更好地理解附加/分离 HEAD 的情况,让我们展示导致上面四组图片的步骤。

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

在此处输入图像描述


现在我们要执行git checkout- 在各个图片中使用不同的目标(它们顶部的命令变暗以强调我们只会应用这些命令):

在此处输入图像描述


这是执行这些命令后的情况:

在此处输入图像描述

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

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


所以现在我们处于与此答案开头相同的情况:

在此处输入图像描述

于 2019-09-27T23:29:32.837 回答
82

如果您进行了更改,然后意识到您处于超然状态,您可以执行以下操作: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'

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

于 2015-01-01T22:40:00.487 回答
79

这是我在意识到自己处于超然状态并且已经做出一些改变之后所做的事情。

我提交了更改。

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

我记得提交的哈希(1fe56ad)。然后我检查了我应该在的分支。

$ git checkout master
Switched to branch 'master'

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

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

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

于 2014-08-02T23:33:49.227 回答
43

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

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

git checkout myfile

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

git reset --hard HEAD^

但是,如果您与其他人共享存储库,则 agit reset可能会造成破坏(因为它会删除存储库历史的一部分)。如果您已经与其他人共享了更改,您通常希望查看git revert它,它会生成一个“反提交”——也就是说,它会创建一个“撤消”相关更改的新提交。

Git Book有更多细节。

于 2012-04-19T13:32:18.720 回答
30

由于“分离头状态”使您处于临时分支上,因此只需使用git checkout -它将您置于您所在的最后一个分支上。

于 2015-11-20T19:30:36.600 回答
16

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

试着只是git checkout your-branch

于 2020-04-01T11:00:57.137 回答
11

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

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

git branch new-branch-name.

这使您可以将当前状态保存在名为的新分支new-branch-name中,而不再处于某个detached head状态。

或者如果你想回到之前的状态,你需要选择之前被选中的分支

git checkout @{-1}

于 2019-02-15T15:16:42.687 回答
9

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

git 樱桃采摘

在 之前cherry-pick,在这种情况下 agit checkout master是必需的。此外,它只需要使用commitin detached head

于 2017-12-06T13:39:17.623 回答
8

附录

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

此外,您可以为该命令设置别名,例如,git global --config alias.prev您只需键入git prev即可切换回上一个结帐。

于 2016-01-22T11:09:35.253 回答
8

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

如果您遇到这样的问题,那么首先存储您的本地更改,这样您就不会丢失您的更改。

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

假设您想要分支 MyOriginalBranch:

git checkout -b someName origin/MyOriginalBranch

于 2020-01-13T06:35:57.967 回答
5

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

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

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

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

于 2020-09-29T16:37:12.047 回答
4

Git告诉我怎么做。

如果您输入:

git checkout <some-commit_number>

保存状态

git add .
git commit -m "some message"

然后:

 git push origin HEAD:<name-of-remote-branch>
于 2019-01-31T19:30:55.820 回答
4

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

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

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

于 2020-01-05T07:39:47.420 回答
3

我想保留我的更改,所以我只是解决这个问题......

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

那对我有用

于 2018-12-04T22:11:11.123 回答
3

当您处于分离头情况并创建新文件时,首先确保将这些新文件添加到索引中,例如:

git add .

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

git commit -a -m "my adjustment message"

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

git checkout -b new_branch_name

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

于 2019-03-21T22:15:15.810 回答
3

merge意识到我有一个超然的头脑而不知道我是如何设法得到它的(比如三个提交) ,我还发现尝试rebasecherry-pick触发了数百个合并冲突,所以我采取了不同的方法:

  1. (假设一切都已提交(工作树是“干净的”))

  2. 保存我的提交信息:git log > /tmp/log

  3. 保存我的工作树:mkdir /tmp/backup && cp -a all_my files_and_directories /tmp/backup

  4. 恢复为mastergit checkout master

  5. 删除所有工作文件和目录:rm ...

  6. 使用备份:cp -a /tmp/backup/. .

  7. git addgit commit使用来自 saved 的消息/tmp/log,也许用不同的文件子集重复它......

缺点是如果一个文件被多次更改,你会丢失你的提交历史master,但最后我有一个干净的master.

于 2020-07-27T12:21:33.447 回答
2

我也有类似的情况。
出于某种原因,我最终得到了一个分离的头——我已经在与我认为我所在的分支相同的路径上进行了提交——例如,HEAD 是分支标签的子标签,但由于某种原因,分支标签一直停留在历史上提交...可能是因为我推了??

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

我不想改变我的任何历史或做任何樱桃采摘,我刚刚在分支上工作了大约 8 周,所以reset --hard让我有点紧张!

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

git branch -f myStuckBranch HEAD
git checkout myStuckBranch

即使 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

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

于 2021-03-31T14:41:56.870 回答
1
git pull origin master

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

于 2014-05-14T14:14:25.840 回答
1

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

git checkout new_branch_name detached_head_garbage_name

于 2020-03-17T17:06:58.730 回答
1

分离的 HEAD 表示您当前不在任何分支上。如果您想保留当前更改并简单地创建一个新分支,您可以这样做:

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

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

git log --all --decorate --oneline --graph
于 2020-04-21T10:00:13.823 回答
1

使用git rebase您可以将 HEAD 移动到所需的提交

假设您的分支处于分离状态,如下所示:

* bfcb8f9 Commit 4
* 540a123 Commit 3
* 4356d64 Commit 2
| * fecb8d2 Commit 2
|/
| * 8012f45 Commit 2x
|/
| * 6676d15 (HEAD -> master) Commit 2 --amend
|/
* 1818f91 Commit 1

分离的头部是通过错误地变基创建的,指向一个分离的提交,该提交是先前由于git commit --amend命令而创建的。

如果您想将 HEAD 引用移动到最近的提交,请使用您想要指向的所需 HASH 提交应用 rebase。在此示例中,哈希是最近提交的:

git rebase bfcb8f9

这将使您的分支的 HEAD 指向所需的提交(在这种情况下是最新的):

* bfcb8f9 (HEAD -> master) Commit 4
* 540a123 Commit 3
* 4356d64 Commit 2 --amend
| * fecb8d2 Commit 2
|/
| * 8012f45 Commit 2x
|/
| * 6676d15 Commit 2
|/
* 1818f91 Commit 1
于 2021-07-12T16:48:55.530 回答
0

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

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

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

git checkout -f master

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

于 2022-01-25T20:12:42.350 回答