修复一个Git分离的头?

时间:2012-04-19 13:07:05

标签: git

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

svn up .

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

git checkout HEAD^ src/

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

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

26 个答案:

答案 0 :(得分:1736)

分离头意味着你不再在分支上,你已经在历史记录中检出了一个提交(在这种情况下是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. 如果您希望将所做的更改合并到master,请从git merge tmp分支运行master。运行master后,您应该在git checkout master分支上。

答案 1 :(得分:422)

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

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

摘自:

What to do with commit made in a detached head

答案 2 :(得分:137)

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

如果在此模式下已经更改某些内容,则退出(“修复”)分离的HEAD状态,并且可选择保存更改:

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

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

    git reset --hard
    

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

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

    git checkout master
    
  4. 接管您的提交。您现在可以通过挑选来接管您在分离的HEAD状态下所做的提交,如my answer to another question所示。

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

答案 3 :(得分:114)

分离头意味着:

  1. 你不再是一个分支,
  2. 您已在历史记录中检出了一次提交
  3. 如果您没有更改:,您可以通过应用以下命令切换到主人

      git checkout master
    

    如果您要保留更改:

    如果是分离的HEAD,则提交正常工作,但不会更新任何命名分支。要使用已提交的更改更新主分支,请在您所在的位置创建临时分支(这样临时分支将具有您在分离的HEAD中所做的所有已提交的更改),然后切换到主分支并将临时分支与主人。

    git branch  temp
    git checkout master
    git merge temp
    

答案 4 :(得分:53)

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

我做出了改变。

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

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

$ git checkout master
Switched to branch 'master'

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

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

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

答案 5 :(得分:41)

如果你做了一些改变,然后意识到你是一个独立的头,有一个简单的解决方案:stash - &gt;结帐大师 - &gt; 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,就像没有发生任何事情一样。

答案 6 :(得分:40)

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

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

git checkout myfile

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

git reset --hard HEAD^

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

The Git Book有更多详情。

答案 7 :(得分:19)

因为&#34;脱离头状态&#34;你有一个临时分支,只需使用"123"将你带到你所在的最后一个分支上。

答案 8 :(得分:14)

HEAD位于指针中,因此它直接或间接指向特定提交(

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

enter image description here

换句话说:

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

要更好地了解带有HEAD或分离的HEAD的情况,让我们显示导致上述图片四合一的步骤。

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

enter image description here


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

enter image description here


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

enter image description here

如您所见,HEAD指向git checkout命令的 target -指向分支(四元组的前三个图像),或者(直接)到 commit (提交)(四元组的最后一个图像)。

工作目录的内容也进行了更改,以符合适当的提交(快照),即HEAD指向(直接或间接)指向该提交。


所以我们现在处在与答案开头相同的状态:

enter image description here

答案 9 :(得分:8)

您可能做过git reset --hard origin/your-branch

尝试仅git checkout your-branch

答案 10 :(得分:6)

分开的头意味着您没有正确检出分支或刚刚检出了一次提交。

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

之后...使用命令检出所需分支:

假设您要分支MyOriginalBranch:

git checkout -b someName origin / MyOriginalBranch

答案 11 :(得分:6)

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

git cherry-pick

cherry-pick之前,在这种情况下需要git checkout master。此外,只需commit中的detached head即可。

答案 12 :(得分:5)

<强>附录

如果您要返回的分支是您最后一次结帐,则只需使用checkout @{-1}即可。这将带您回到之前的结账时间。

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

答案 13 :(得分:2)

位于“分离头”中意味着HEAD指的是特定的未命名提交(与命名分支相反)(参见:https://git-scm.com/docs/git-checkout部分独立头

要解决此问题,只需选择

之前选择的分支

git checkout @{-1}

答案 14 :(得分:2)

此方法可能会丢弃部分提交历史记录,但是如果将旧的master分支和当前状态合并起来比较棘手,或者如果您不介意丢失部分提交历史记录,则会更容易提交历史记录。

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

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

信用:改编自this Medium article,由Gary Lai提供。

答案 15 :(得分:1)

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

select p.p_kode, p.name as p_name, coalesce(sum(m.money), 0) as jum
from person p
left join money as m 
    on  m.p_kode = p.p_kode
    and m.date >= '2020-04-10' 
    and m.date <= '2020-04-13'
group by p.p_kode

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

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

答案 16 :(得分:1)

意识到我有一个超脱的头脑,却不知道该如何设法做到(就像三个承诺一样),我还发现尝试mergerebasecherry-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使用来自保存的/tmp/log的消息,也许用不同的文件子集重复它...

缺点是,如果自master起一个文件被多次更改,则会丢失提交历史记录,但最终我得到了干净的master

答案 17 :(得分:1)

Git告诉我该怎么做。

如果您输入:

git checkout <some-commit_number>

保存状态

git add .
git commit -m "some message"

然后:

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

答案 18 :(得分:1)

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

git checkout new_branch_name detached_head_garbage_name

答案 19 :(得分:0)

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

git add .

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

git commit -a -m "my adjustment message"

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

git checkout -b new_branch_name

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

答案 20 :(得分:0)

我想保留自己的更改,所以,我只是解决此问题...

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

对我有用的

答案 21 :(得分:0)

在我的情况下,我运行git status,我看到我的工作目录中有一些未跟踪的文件。

我只需要清理它们(因为我不需要它们)来运行我想要执行的rebase。

答案 22 :(得分:0)

git pull origin master

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

答案 23 :(得分:0)

我也遇到过类似的情况。
出于某种原因,我最终得到了一个独立的头 - 我在与我认为我所在的分支相同的路径上进行了提交 - 例如, 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

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

答案 24 :(得分:0)

使用 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 提交应用变基。在这个例子中,哈希是最近提交的:

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

答案 25 :(得分:-1)

在我的情况下,当我这样做时发生了分离的 HEAD 警告

git checkout origin/some_branch

代替

git checkout some_branch

就我而言,只做 git checkout some_branch 就解决了问题。

相关问题