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


当前回答

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

其他回答

在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

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

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

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

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

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

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

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

如何还原错误合并艾伦(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日志

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

git checkout-b newbranch<HASH>

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

git branch -D oldbranch
git checkout -b oldbranch newbranch

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