撤销快进合并

87

我对我的git仓库进行了一些更改,现在希望撤销这些更改。

我的git仓库看起来像这样:

A-B----     master
   \   /
    C-D     * develop

我当时在develop分支上,忘记了它与master分支的差异,在develop上做出更改,将其合并到master中,然后推送到我的远程仓库(名为publish)。

由于自从B(公共祖先)以来,在master上没有更改,因此Git执行了快进式合并。

现在,我的仓库看起来像这样:

A-B-C-D   master, develop, remotes/publish/master, remotes/publish/develop.

我想撤销最后一次合并,将master还原到B版本。

根据我在如何撤销 Git 中最后的提交?上看到的内容,我使用了git reset sha-of-Bmaster分支还原到版本B。

问题:

  • 如何将develop还原到版本D?
  • 然后如何将这些更改推送回远程/发布版本?

1
博客文章概述并详细说明我做了什么,应该做什么以及我如何修复这个问题:http://www.capnfabs.net/software/git-undoing-a-fast-forward-merge-when-you-shouldve-just-used-a-new-branch/ - Fabian Tamp
1
@SnowCrash 的链接已更新:http://capnfabs.net/blog/2013/01/14/git-undoing-a-fast-forward-merge/ - Fabian Tamp
对于独立开发者来说,这可能都很好,但对于那些合作开发的人来说,使用“还原”而不是“重置”会更有意义吧? - Snowcrash
1
@Snowcrash:git revert -m 1 hashValue 将会失败,提示 hashValue 不是一个合并。因为这是快进式合并。 - Tihomir
3个回答

105

如果你重置了主分支(master branch),它不会影响开发分支(develop branch)。为了将所有内容重新排列,你应该执行以下操作:

git checkout master
git reset --hard sha-of-B
git checkout develop
git reset --hard sha-of-D
git checkout master
git merge develop --no-ff

12
从未建议使用push --force命令,应该使用git push publish --force-with-lease命令。该命令可以实现强制推送的功能,但同时避免了可能覆盖其他人提交的代码的风险。 - Robert Siemer

35
  • 假设你仍在 master 上,你已经合并并推送了代码
  • git reset --hard@{1}
    • 这将重置本地分支"master"到上一步(即“B”)的状态
  • 对于develop分支不需要任何操作,因为它应该仍然在“D”上
  • git push publish develop
    • 这将按照通常的方式推送"develop"分支
  • git push publish master --force-with-lease
    • 使用--force-with-lease命令以安全的方式将分支"master"向后推
    • 使用--force可能会将其他人的工作 悄悄地 覆盖掉,因此我从不使用它
  • 或者使用这个令人惊讶的语法同时进行推送:
    • git push publish develop --force-with-lease=master

7
"git reset --hard @{1}" 对我的情况非常适用。我使用了 "--no-ff" 合并,有100多个提交,不想为每个提交都执行软重置。谢谢!+1 - Brad Bird
我不小心执行了 git checkout develop && git merge - 而不是 git checkout develop && git merge --no-ff -(- 表示最后一个分支)。上面的答案对我非常有效,因为我没有在中间做任何事情,仍然在 develop 分支上:git reset --hard @{1} && git merge --no-ff feature/my-feature-branch - Thomas Praxl
作为可用性/信心提示:在进行重置之前,可能有所帮助的是使用 git checkout @{1} 命令,确保当前分支和历史记录看起来符合您的要求。 - Unixmonkey
git push publish 中的 "publish" 是什么意思?我在 git-push 文档或通过搜索 "git publish" 没有看到这个单词。 - Noumenon
2
@Noumenon是问题中建立的存储库的名称。在git push手册中被称为<repository> - Robert Siemer

0

看起来你在运行 git reset 时被检出到了 develop 分支,这就是导致问题的原因。

你可以按照以下步骤修复 develop 分支:

git checkout develop
git merge --ff-only D

现在,您可以将master恢复回B:

git checkout master
git reset --hard B

回到开发并推送它:

git checkout develop
git push develop

谢谢你的回答!我肯定是在master分支上,只是我看错了gitk图形界面。我会相应地编辑我的问题。 - Fabian Tamp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接