【问题标题】:How can I move HEAD back to a previous location? (Detached head) & Undo commits如何将 HEAD 移回以前的位置? (分离头)和撤消提交
【发布时间】:2022-11-20 16:12:37
【问题描述】:

在 Git 中,我试图通过合并到另一个分支来执行 squash commit,然后通过以下方式将 HEAD 重置为之前的位置:

git reset origin/master

但我需要走出这一步。如何将 HEAD 移回之前的位置?

我有我需要将其移动到的提交的 SHA-1 片段 (23b6772)。我怎样才能回到这个承诺?

【问题讨论】:

  • HEAD 只是指向您当前位置(或准确地说是修订版)的指针。 git checkout 23b6772应该可以。
  • @YaroslavAdmin 不应该不是.直接签出提交分离的 HEAD 状态发生的原因(因为远程跟踪分支无法自行检出并自动推迟到它们指向的提交,当您像 OP 那样尝试这样做时)另外,对于死灵评论 :-) 我排序的希望最初的问题已经解决了......

标签: git git-checkout git-reset git-revert git-reflog


【解决方案1】:

在回答之前,让我们补充一些背景知识,解释一下这个HEAD 是什么。

First of all what is HEAD?

HEAD 只是对当前分支上当前提交(最新)的引用。
在任何给定时间只能有一个HEAD(不包括git worktree)。

HEAD 的内容存储在.git/HEAD 中,它包含当前提交的 40 字节 SHA-1。


detached HEAD

如果您不在最新的提交上——这意味着 HEAD 指向历史上的先前提交,它被称为detached HEAD.

在命令行上,它看起来像这样 - SHA-1 而不是分支名称,因为 HEAD 没有指向当前分支的尖端:


关于如何从分离的 HEAD 中恢复的几个选项:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits to go back

这将检出指向所需提交的新分支。
此命令将签出给定的提交。
此时,你可以创建一个分支,从这里开始工作。

# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# Create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

您也可以随时使用reflog
git reflog 将显示更新 HEAD 的任何更改,并检查所需的 reflog 条目会将 HEAD 设置回此提交。

每次修改 HEAD 时,reflog 中都会有一个新条目

git reflog
git checkout HEAD@{...}

这会让你回到你想要的承诺


git reset --hard &lt;commit_id&gt;

“移动”您的 HEAD 回到所需的提交。

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • 注意:(Since Git 2.7) 您也可以使用git rebase --no-autostash


git revert &lt;sha-1&gt;

“撤消”给定的提交或提交范围。
revert 命令将“撤消”在给定提交中所做的任何更改。
将提交带有撤消补丁的新提交,而原始提交也将保留在历史记录中。

# Add a new commit with the undo of the original one.
# The <sha-1> can be any commit(s) or commit range
git revert <sha-1>

此模式说明了哪个命令执行什么操作。
如您所见,reset &amp;&amp; checkout 修改了HEAD

【讨论】:

  • 如果你不在最新的提交上——这意味着 HEAD 指向历史上的一个先前的提交,它被称为分离的 HEAD除非历史上的先前提交是另一个分支的尖端。根据我的经验,如果 HEAD 未指向任何分支也指向的提交,您可以说您是分离的。这不适用于标签。
  • 您可以处于分离的 HEAD 中,同时拥有一个与该分支的 HEAD 具有相同提交的分支。我不明白你的评论
【解决方案2】:

先在本地reset

git reset 23b6772

要查看您是否处于正确的位置,请验证:

git status

你会看到类似这样的东西:

在分支 master 你的分支落后于'origin/master' 17次提交, 并且可以快进。

然后改写历史在您的远程跟踪分支上反映变化:

git push --force-with-lease // a useful command @oktober mentions in comments

使用 --force-with-lease 而不是 --force 会在其他人同时提交到远程分支时引发错误,在这种情况下你应该先获取。 More info in this article

【讨论】:

  • 使用git push --force 时要格外小心。在很多情况下,这会让你暂时成为团队中最不受欢迎的人......
  • 添加到上面的注释中,我刚刚在 about.gitlab.com/blog/2014/11/26/keeping-your-code-protected 看到这句话,不得不添加它:“一个 git push --force 命令很容易毁掉很多人的一天:[186 Jenkins] 存储库有他们的分支负责人倒带指向较旧的提交,实际上较新的提交在错误的 git-push 之后被放错了位置。” --非常不受欢迎的开发者....
  • 谢谢你!这帮助我取消了一个糟糕的合并。由于合并对 revert 的反应与提交不同,我发现自己处于一个非常困难的境地。 force-with-lease让我有信心在不影响其他人工作的情况下重写分支的git历史。太棒了!
【解决方案3】:

最快的解决方案(只需 1 步)

使用git checkout -

你会看到Switched to branch &lt;branch_name&gt;。确认这是你想要的分支。


简要说明:此命令会将 HEAD 移回其最后的位置。见注释结果在这个答案的结尾。


助记符:这种方法很像使用cd - 返回到您之前访问过的目录。语法和适用情况非常匹配(例如,当您实际上希望 HEAD 返回到它原来的位置时它很有用)。


更有条理的解决方案(两步,但令人难忘)

快速方法解决了 OP 的问题。但是,如果您的情况略有不同怎么办:假设您重新启动了 Bash,然后发现自己的 HEAD 已分离。在这种情况下,这里有 2 个简单易记的步骤。

1.选择你需要的分支

使用git branch -v

您会看到现有本地分支机构的列表。获取适合您需要的分支名称。

2. 将 HEAD 移动到它上面

使用git checkout &lt;branch_name&gt;

你会看到Switched to branch &lt;branch_name&gt;。成功!


结果

无论使用哪种方法,您现在都可以像以前一样继续添加和提交您的工作:您的下一次更改将在&lt;branch_name&gt; 上进行跟踪。

请注意,如果您在分离 HEAD 时提交了更改,git checkout -git checkout &lt;branch_name&gt; 都会提供额外的说明。

【讨论】:

  • 这不起作用,因为如果我这样做(假设 8acc968 是 HEAD~2)git checkout 8acc968then git branch -v 在下面的列表中有 MyBranch ...但是 git checkout MyBranch 删除了我的 cmets。
  • 嗨@amuliar - git checkout 8acc968 将签出一个提交,而不是一个分支。如果MyBranch 有你想要的提交,试试git checkout MyBranch。如果它不包含提交 8acc968 中的更改,则您需要在签出分支后合并这些更改。
  • 感谢你的回答!我做了 git checkout 来查看以前的提交并想回到最新的提交。但是没有最新的提交哈希,我几乎迷路了。这个解决方案非常适合我的情况!
  • git checkout -不一定有你说的效果。
【解决方案4】:

这个问题可以理解为:

我在 23b6772HEAD 处于分离状态并输入 git reset origin/master (因为我想压扁)。现在我改变主意了,如何回到HEAD23b6772

直截了当的答案是:git reset 23b6772

但是我遇到了这个问题,因为每次我想引用之前的 HEAD 时,我都厌倦了键入(复制和粘贴)提交哈希或其缩写,并且正在谷歌搜索以查看是否有任何速记。

原来有!

git reset -(或者在我的例子中是git cherry-pick -

顺便说一句,与cd -相同,可以返回到上一个当前目录在*尼克斯!太好了,我用一块石头学到了两件事。

【讨论】:

    【解决方案5】:

    当您运行命令 git checkout commit_id 时,HEAD 将与 13ca5593d(say commit-id) 分离,分支将不再可用。

    移回先前的位置,逐步运行命令 -

    1. git pull origin branch_name(说师傅)
    2. git checkout branch_name
    3. git pull origin branch_name

      您将返回到先前的位置,并从远程存储库更新提交。

    【讨论】:

      【解决方案6】:

      今天,我错误地检查了一个提交并开始处理它,在分离 HEAD 状态下进行了一些提交。然后我使用以下命令推送到远程分支:

      git push origin HEAD: <My-remote-branch>
      

      然后

      git checkout <My-remote-branch>
      

      然后

      git pull
      

      我终于得到了我在分离 HEAD 中所做的分支中的所有更改。

      【讨论】:

        【解决方案7】:

        这可能不是技术解决方案,但它确实有效。 (如果你的队友中有人在当地有相同的分支)

        让我们假设您的分支名称为分支-xxx.

        解决步骤:

        • 不要进行更新或拉取 - 什么都不做
        • 只需创建一个新分支(分支 yyy) 从分支-xxx在他的机器上
        • 就是这样,您现有的所有更改都将在这个新分支中(分支 yyy).您可以继续使用该分支进行工作。

        注意:同样,这不是技术解决方案,但肯定会有所帮助。

        【讨论】:

          【解决方案8】:

          将最后的非推送提交移动到新分支

          如果您的问题是您开始在 WRONG_BRANCH 上提交,并且想将那些最后的非推送提交移动到 RIGHT_BRANCH,那么最简单的事情就是

          1. git checkout WRONG_BRANCH
          2. git branch RIGHT_BRANCH
          3. git reset —-hard LAST_PUSHED_COMMIT
          4. git checkout RIGHT_BRANCH

            此时,如果您运行git log HEAD,您将看到所有提交都在 RIGHT_BRACH 中。

            数据

            • 错误分支是您提交的更改(尚未推送)现在所在的位置
            • 右分支是您承诺的更改(尚未推送)的位置
            • LAST_PUSHED_COMMIT是您要将 WRONG_BRANCH 恢复到的位置

          【讨论】:

            猜你喜欢
            • 2018-10-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-06-18
            • 2010-09-25
            相关资源
            最近更新 更多