仅使用git-restore<commit_hash>是行不通的。显然,必须指定-m。


当前回答

接受的答案和其他一些答案演示了如何使用git-restore命令还原合并提交。然而,对于父提交存在一些混淆。这篇文章旨在通过一个图形表示和一个真实的例子来阐明这一点。

还原合并提交不像git revert<commit hash>那样简单,因为git在从合并提交返回时会因为两个父提交而感到困惑。要指定所需的父级,请使用-m标志。由于git无法确定哪个父级是主线,哪个分支是要自动取消合并的分支,因此必须指定此项。

iss53分支被合并到master中,创建了一个合并提交C6。C6有两个父母C5和C4。

需要恢复C6并将存储库恢复到C4的状态。因此,它必须指定要用于revert命令的父级。

为此,请检查git日志(此处表示实际的提交哈希值和图中的代码名称)>git日志提交C6合并:C4 C5作者:Mozz<mozz@example.com>日期:2月29日星期三23:59:59 2020+0100将分支“iss53”合并到主分支...从git日志输出中,记下Merge:--附带的父ID。它的格式为Merge:parent1 parent2,此处为Merge:C4 C5。C4提交在主分支中,我们需要恢复到它,即父1,这里需要-m1(使用gitlogC4验证先前的提交以确认父分支)。切换到进行合并的分支(这里是主分支,我们的目标是从中删除iss53分支)使用-m 1标志执行git还原。#在主分支中恢复到C4数字还原C6-m 1#C6-是合并提交哈希

对于一些其他情况,

# revert to C5 in iss53 branch
git revert C6 -m 2

# General
git revert <merge commit id> -m 1 (reverts to parent1)
git revert <merge commit id> -m 2 (reverts to parent2)
# remember to check and verify the parent1 and parent2 with git log command.

实际示例

在只有主分支的现有项目上创建了一个新的分支还原测试,提交图现在看起来像这样。

(对于提交的图形化视图,请使用带有git-log[SO ans-ref]的-graph或这个更具交互性的VS代码扩展-git-grraph)

现在,我已经添加了一些新文件,修改了现有文件,并在每个分支上创建了单独的提交,然后将它们推送到源。图形现在看起来如下:

然后,从GitHub创建一个拉取请求,并将恢复测试分支合并到main。

我想撤消合并提交并返回到主分支中的最后一次提交,即12a7327

注意,合并提交-2ec06d9现在有两个父级-12a7327(在主级)和15bde47(在还原测试中),现在检查gitlog,

> git log

commit 2ec06d9d315a3f7919ffe4ad2c2d7cec8c8f9aa3 (HEAD -> main, origin/main, origin/HEAD)
Merge: 12a7327 15bde47
Author: Akshay <63786863+akshay@users.noreply.github.com>
Date:   Sun Feb 5 00:41:13 2023 +0530

    Merge pull request #1 from Akshay/revert-test
    
    Revert test

要恢复合并提交并返回到12a7327需要执行的操作,

# To the First parent
git revert 2ec06d9 -m 1

现在,编辑器中将显示一条提交消息,指定详细信息、检查和验证。

因此,这将创建一个Revert提交,该提交执行合并提交的反向更改。

最后推送更改,现在合并提交更改消失,日志将如下所示:,

其他回答

在git-restore-m中,-m选项指定父编号。这是需要的,因为合并提交有多个父级,Git无法自动知道哪个父级是主线,哪个父级就是要取消合并的分支。

当您在git日志的输出中查看合并提交时,您将看到其父级列在以merge开头的行中:

commit 8f937c683929b08379097828c8a04350b9b8e183
Merge: 8989ee0 7c6b236
Author: Ben James <ben@example.com>
Date:   Wed Aug 17 22:49:41 2011 +0100

Merge branch 'gh-pages'

Conflicts:
    README

在这种情况下,git revert 8f937c6-m 1将获得8989ee0中的树,而git rever-m 2将恢复7c6b236中的树。

为了更好地理解父ID,可以运行:

git log 8989ee0 

and

git log 7c6b236

如果您希望恢复刚才所做的更改,这是一个非常简单的答案:

commit 446sjb1uznnmaownlaybiosqwbs278q87
Merge: 123jshc 90asaf


git revert -m 2 446sjb1uznnmaownlaybiosqwbs278q87 //does the work

git文档关于git revert-m提供了一个链接,准确地解释了这一点:https://github.com/git/git/blob/master/Documentation/howto/revert-a-faulty-merge.txt

我在一个已合并到GitHub回购主分支的PR上也遇到了这个问题。

因为我只是想修改一些修改过的文件,而不是PR带来的全部更改,所以我不得不用gitcommit-am修改合并提交。

步骤:

转到要更改/还原某些已修改文件的分支根据修改的文件执行所需的更改运行git-add*或git-add<file>运行gitcommit--am并验证运行git push-f

为什么有趣:

它使公关的作者承诺保持不变它不会破坏git树您将被标记为提交人(合并提交作者将保持不变)Git就像你解决了冲突一样,它会删除/更改修改文件中的代码,就像你手动告诉GitHub不要按原样合并它一样

正如Ryan所提到的,git-restore可能会使合并变得困难,因此git-restore也许不是您想要的。我发现在这里使用git reset-hard<commit hash before merge>命令更有用。

完成硬重置部分后,可以强制推送到远程分支,即git push-f<remote name><remote branch name>,其中<remote name>通常被命名为origin。从那时起,如果您愿意,可以重新合并。