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


在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

Ben已经告诉过您如何恢复合并提交,但您必须意识到这样做非常重要

“…声明您永远不希望合并带来的树更改。因此,以后的合并只会带来由不是先前还原的合并的祖先的提交引入的树更改,这可能是您想要的,也可能不是您想要的。”(git merge手册页)。

从手册页链接的文章/邮件列表消息详细说明了所涉及的机制和注意事项。只需确保您理解,如果您恢复合并提交,您不能只是稍后再次合并分支并期望相同的更改返回。


下面是一个完整的示例:

git revert -m 1 <commit-hash> 
git push -u origin master

git还原。。。提交您的更改。

-m1表示您希望在合并之前恢复到第一个父级的树,如下面的答案所述。<commit hash>是要还原的合并的提交哈希。

git推。。。将更改推送到远程分支。


有时,回滚的最有效方法是后退并替换。

git日志

使用第二个提交哈希(完整哈希,在列出错误之前要恢复到的哈希),然后从那里重新广播。

git checkout-b newbranch<HASH>

然后删除旧分支,将新分支复制到原来的位置,然后从那里重新启动。

git branch -D oldbranch
git checkout -b oldbranch newbranch

如果已广播,则从所有存储库中删除旧分支,将重做的分支推到最中心,然后将其拉回到所有存储库。


您可以按照以下步骤恢复不正确的提交或将远程分支重置回正确的HEAD/状态。

注意:此解决方案仅适用于您自己的分支,而不适用于共享的树枝

签出远程分支到本地回购。git签出您的branch_name从git日志中复制提交哈希(即错误提交前的提交id)git日志-n5

应该显示如下内容:

提交7cd42475d6f95f5896b6f02e902efab0b70e8038“合并分支“错误提交”到“your_branch_name”“提交”f9a734f8f44b0b37ccea769a2fd774c0f0c012“这是错误的提交”提交3779ab50e72908da92d2cfcd72256d7a09f444ba“这是正确的提交“

将分支重置为上一步中复制的提交哈希git reset<commit hash>(即3779ab50e72908da92d2cfcd72256d7a09f444ba)运行gitstatus以显示错误提交中的所有更改。只需运行gitreset——很难还原所有这些更改。强制将您的本地分支推到远程,并注意到您的提交历史记录与被污染之前一样干净。git push-f origin your_branch_name


我发现在两个已知端点之间创建一个反向补丁,然后应用该补丁即可。这假设您已经创建了主分支的快照(标记),甚至是主分支的备份,比如master_bk_011012017。

假设你合并到master的代码分支是mycodebranch。

签出主机。在主服务器和备份服务器之间创建一个完整的二进制反向修补程序。gitdiff—二进制主文件。。master_bk_01017>~/myrevert.patch检查您的补丁git apply--检查myevert.patch签署后应用修补程序git am--签出<myevert.patch如果修复后需要再次引入此代码,则需要从还原的主节点分支并签出修复分支git分支分支分支修复git校验mycodebranchfix在这里,您需要找到还原的SHA密钥并还原还原git还原现在,您可以使用mycodebranch_fix来解决问题,提交并在完成后重新合并到master中。


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

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


git revert -m 1 <merge-commit>

为了保持日志的整洁(这种方法有一些缺点(由于push-f)):

git checkout <branch>
git reset --hard <commit-hash-before-merge>
git push -f origin HEAD:<remote-branch>

“合并前提交哈希”来自合并后的日志(gitlog)。


正确标记的答案对我有用,但我必须花一些时间来确定发生了什么。所以我决定为我这样的情况添加一个简单明了的答案。。

假设我们有分支A和B。您将分支A合并到分支B中,并将分支B推到自身,因此现在合并是它的一部分。但是您希望返回到合并之前的最后一次提交。。你是做什么的?

转到git根文件夹(通常是项目文件夹)并使用git日志您将看到最近提交的历史记录-提交具有提交/作者/日期财产,而合并也具有合并属性-因此您可以这样看它们:提交:<commitHash>合并:<parentHashA><parentHashB>作者:<Author>日期:<Date>使用gitlog<parentHashA>和gitlog<ParetHashB>-您将看到这些父分支的提交历史记录-列表中的第一个提交是最新的获取所需提交的<commitHash>,转到git根文件夹并使用git checkout-b<newBranchName><commitHash>,这将从合并前选择的最后一次提交开始创建一个新分支。。瞧,准备好了!


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


所有的答案已经涵盖了大部分内容,但我还要加上我的5美分。简而言之,恢复合并提交非常简单:

git revert -m 1 <commit-hash>

如果您有权限,可以将其直接推送到“主”分支,否则只需将其推送到“还原”分支并创建拉取请求。

您可以在此处找到有关此主题的更多有用信息:https://itcodehub.blogspot.com/2019/06/how-to-revert-merge-in-git.html


如果您想恢复合并提交,以下是您必须执行的操作。

首先,检查git日志以查找合并提交的id。您还可以找到与合并关联的多个父id(参见下图)。

记下黄色显示的合并提交id。父ID是在下一行中作为“合并:parent1 parent2”写入的ID。现在

短篇故事:

切换到进行合并的分支。然后,只需执行git-restore<mergecommit-id>-m1,它将打开vi控制台以输入提交消息。写,保存,退出,完成!

长话短说:

切换到进行合并的分支。在我的例子中,它是测试分支,我试图从中删除feature/analytics-v3分支。git-restore是还原任何提交的命令。但在恢复合并提交时有一个令人讨厌的技巧。您需要输入-m标志,否则它将失败。从这里开始,您需要决定是否要还原分支,并通过以下方式使其看起来与parent1或parent2完全相同:

git revert<merge commit id>-m 1(还原为parent2)

git revert<merge commit id>-m 2(还原为parent1)

你可以把这些父母记录下来,看看你想走哪条路,这是所有困惑的根源。


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

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

步骤:

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

为什么有趣:

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


我从这个链接找到了如何恢复合并的很好的解释,我复制粘贴了下面的解释,如果下面的链接不起作用,这将很有帮助。

如何还原错误合并艾伦(alan@clueserver.org)他说:

我有一个主分支。我们有一个分支开发人员正在进行工作。他们声称它已经准备好了。我们将其合并进入主分支。它打破了一些东西,所以我们恢复合并。他们对代码进行更改。他们会说没关系,我们再次合并。当检查时,我们发现在还原之前所做的代码更改不在主分支中,但之后的代码更改位于主分支中树枝并请求帮助从这种情况中恢复过来。

“恢复合并”后的历史记录如下所示:

---o---o---o---M---x---x---W
              /
      ---A---B

其中A和B处于不太好的侧开发中,M是将这些过早的更改引入主线的合并,x是与侧分支在主线上所做的和已经做的更改无关的更改,W是“合并M的恢复”(W看起来不是M颠倒了吗?)。IOW,“diff W^..W”类似于“diff-R M^..M”。

合并的“还原”可以通过以下方式进行:

$git还原-m 1 m在分支的开发人员纠正错误后,历史可能如下:

---o---o---o---M---x---x---W---x
              /
      ---A---B-------------------C---D

其中C和D将修复A和B中的损坏,并且您可能已经在W之后的主线上进行了一些其他更改。

如果您合并更新后的分支(顶端有D),那么在A或B中所做的任何更改都不会产生结果,因为它们被W还原。这就是Alan看到的。

Linus解释了情况:

恢复常规提交只会有效地撤消该提交确实如此,而且相当简单。但同时恢复合并提交撤消提交更改的数据,但它确实与合并对历史的影响无关。因此,合并仍将存在,并且仍将被视为加入这两个分支合并在一起,将来的合并将看到最后一个共享状态-以及还原合并带来的还原不会影响这一点。因此,“还原”可以撤消数据更改,但它在很大程度上不是“撤销”是指它不会撤销提交对存储库历史记录。所以,如果你把“恢复”看作“撤消”,那么你将永远错过了这部分回复。是的,它撤销了数据,但不,它没有撤消历史记录。在这种情况下,您需要首先还原上一个还原,这将使历史看起来像这样:

---o---o---o---M---x---x---W---x---Y
              /
      ---A---B-------------------C---D

其中Y是W的回复。这种“回复回复”可以通过以下方式完成:

$git还原W这段历史(忽略W和W..Y之间可能发生的冲突)相当于历史中根本没有W或Y:

---o---o---o---M---x---x-------x----
              /
      ---A---B-------------------C---D

并且再次合并侧分支将不具有由较早的恢复和恢复的恢复引起的冲突。

---o---o---o---M---x---x-------x-------*
              /                       /
      ---A---B-------------------C---D

当然,在C和D中所做的更改仍然可能与任何x所做的操作发生冲突,但这只是正常的合并冲突。


这是一个非常古老的线索,但我认为缺少另一个方便的解决方案:

我从不恢复合并。我只是从修订版中创建了另一个分支,其中所有内容都正常,然后从中间添加的旧分支中选择所有需要选择的内容。

因此,如果GIT历史是这样的:

dcb<<<合并一...

我从a、cherry pick c和d中创建了一个新分支,然后新分支从b中清除。我可以再次决定在新分支中合并“b”。如果不再需要“b”或“b”仍在另一个(功能/修补程序)分支中,旧分支将被弃用,并将被删除。

现在唯一的问题是计算机科学中最困难的事情之一:如何命名新分支

好的,如果你特别是在devel中失败,你可以如上所述创建newdevel,删除旧的devel并将newdevel重命名为devel。任务完成。现在,您可以在需要时再次合并更改。这就像以前从未合并过。。。。


-m1是被修复的当前分支的最后一个父级,-m2是合并到其中的分支的原始父级。

如果命令行令人困惑,Tortoise Git也可以在这里提供帮助。


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

commit 446sjb1uznnmaownlaybiosqwbs278q87
Merge: 123jshc 90asaf


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

当您在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

采取备份分支

git checkout -b mybackup-brach

git reset --hard 8989ee0 
git push origin -u mybackup-branch

所以现在您在合并之前进行了更改,如果一切正常,请签入上一个分支并用备份分支重置

git reset --hard origin/mybakcup-branhc

接受的答案和其他一些答案演示了如何使用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提交,该提交执行合并提交的反向更改。

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