单独使用 git revert <commit_hash>
是行不通的。 -m
必须指定,我对此感到很困惑。
以前有人经历过吗?
git
的设计与每个人都使用的 git-flow
式工作流程不匹配的示例。如果您已 develop
签出,当然您希望恢复引入错误的 2-commit 功能分支,而不是多年的共享开发分支。需要用 -m 1
来选择它感觉很荒谬。
-m
选项指定父编号。这是因为合并提交有多个父级,并且 Git 不会自动知道哪个父级是主线,哪个父级是您要取消合并的分支。
当您在 git log
的输出中查看合并提交时,您将看到其父项列在以 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 revert -m 2
将恢复 7c6b236
中的树。
为了更好地理解父 ID,您可以运行:
git log 8989ee0
和
git log 7c6b236
这是一个完整的示例,希望对某人有所帮助:
git revert -m 1 <commit-hash>
git push -u origin master
其中 <commit-hash>
是您要恢复的合并的提交哈希,如 this answer 的解释中所述,-m 1
表示您要恢复到之前的第一个父级树合并。
git revert ...
行实质上是提交您的更改,而第二行通过将更改推送到远程分支来公开您的更改。
git revert
命令已经提交了创建的提交对象。为了不发生这种情况,您必须输入 --no-commit
标志
revert
命令包含提交。
Ben 已经告诉过您如何恢复合并提交,但您意识到这样做非常重要
“...声明您永远不希望合并带来的树更改。因此,以后的合并只会带来不是先前恢复合并的祖先的提交引入的树更改。这可能是也可能不是你想要什么。” (git-merge 手册页)。
从手册页链接的 article/mailing list message 详细说明了所涉及的机制和注意事项。只要确保您了解,如果您恢复合并提交,您不能稍后再次合并分支并期望相同的更改回来。
您可以按照这些步骤恢复不正确的提交或将远程分支重置为正确的 HEAD/状态。
注意:此解决方案仅适用于您自己的分支,不适用于共享分支。
将远程分支签出到本地仓库。 git checkout your_branch_name 从 git log git log -n5 复制提交哈希(即错误提交之前的提交 ID)
应该显示如下内容:
commit 7cd42475d6f95f5896b6f02e902efab0b70e8038 "Merge branch 'wrong-commit' into 'your_branch_name'" commit f9a734f8f44b0b37ccea769b9a2fd774c0f0c012 "this is a wrong commit" commit 3779ab50e72908da92d2cfcd72256d7a09f446ba "this is the correct commit"
将分支重置为在上一步中复制的提交哈希 git reset
git revert -m 1 <merge-commit>
1
以及何时不想使用的答案。
为了保持日志干净,因为没有发生任何事情(这种方法有一些缺点(由于 push -f)):
git checkout <branch>
git reset --hard <commit-hash-before-merge>
git push -f origin HEAD:<remote-branch>
'commit-hash-before-merge' 来自合并后的日志(git log)。
push -f
git log
来确定 commit-hash-before-merge 并不简单,因为提交会随着时间的推移交织在一起 - 我想知道这是否总是 MERGECOMMIT^
(这似乎表明是 git-tower.com/learn/git/faq/undo-git-merge/… )?
所有答案已经涵盖了大部分内容,但我会加上我的 5 美分。简而言之,恢复合并提交非常简单:
git revert -m 1 <commit-hash>
如果您有权限,您可以将其直接推送到“master”分支,否则只需将其推送到您的“revert”分支并创建拉取请求。
您可以在此处找到有关此主题的更多有用信息:https://itcodehub.blogspot.com/2019/06/how-to-revert-merge-in-git.html
有时最有效的回滚方法是退后一步并替换。
git log
使用第二个提交散列(完整散列,在列出的错误之前要恢复的散列),然后从那里重新分支。
git checkout -b newbranch <HASH>
然后删除旧分支,将新分支复制到它的位置并从那里重新启动。
git branch -D oldbranch
git checkout -b oldbranch newbranch
如果已广播,则从所有存储库中删除旧分支,将重做的分支推送到最中心,然后将其拉回全部。
如果您想恢复 merge
提交,您必须执行以下操作。
首先,检查 git 日志以找到您的合并提交的 id。您还会发现与合并关联的多个父 ID(见下图)。
https://i.stack.imgur.com/lZScB.png
记下黄色显示的合并提交 ID。父 ID 是写在下一行 Merge: parent1 parent2
中的那些。现在...
短篇故事:
切换到进行合并的分支。然后只需执行 git revert
很长的故事:
切换到进行合并的分支。就我而言,它是测试分支,我正在尝试从中删除 feature/analytics-v3 分支。 git revert 是恢复任何提交的命令。但是在恢复合并提交时有一个讨厌的技巧。您需要输入 -m 标志,否则它将失败。从这里开始,您需要通过以下方式决定是否要恢复分支并使其看起来与 parent1 或 parent2 上的完全相同:
git revert <merge commit id> -m 1
(恢复为 parent2
)
git revert <merge commit id> -m 2
(恢复为 parent1
)
你可以 git log 这些父母来弄清楚你想走哪条路,这就是所有混乱的根源。
我从这个 link 中找到了关于How To Revert The Merge 的很好的解释,我复制并粘贴了下面的解释,如果下面的链接不起作用,它会很有帮助。
如何恢复错误的合并 Alan(alan@clueserver.org) 说:
我有一个主分支。我们有一个分支,一些开发人员正在研究它。他们声称它已经准备好了。我们将它合并到主分支中。它破坏了一些东西,所以我们恢复合并。他们对代码进行更改。他们达到了他们说没问题的地步,然后我们再次合并。经过检查,我们发现在还原之前所做的代码更改不在 master 分支中,但之后的代码更改在 master 分支中。并寻求帮助从这种情况中恢复过来。
“恢复合并”之后的历史记录如下所示:
---o---o---o---M---x---x---W
/
---A---B
其中 A 和 B 处于不太好的侧开发,M 是将这些过早的更改带入主线的合并,x 是与侧分支所做的和已经在主线上所做的无关的更改,W 是“合并 M" 的还原(W 看起来不是 M 倒置吗?)。 IOW,“diff W^..W”类似于“diff -RM^..M”。
这种合并的“恢复”可以通过以下方式进行:
$ git revert -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 revert W 这个历史将(忽略 W 和 W..Y 更改之间可能发生的冲突)等同于历史中根本没有 W 或 Y:
---o---o---o---M---x---x-------x----
/
---A---B-------------------C---D
并且再次合并侧分支不会因为之前的revert和revert的revert而产生冲突。
---o---o---o---M---x---x-------x-------*
/ /
---A---B-------------------C---D
当然,在 C 和 D 中所做的更改仍然可能与任何 x 所做的冲突,但这只是正常的合并冲突。
当您在 git log
的输出中查看合并提交时,您将看到其父项列在以 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 revert -m 2
将恢复 7c6b236
中的树。
为了更好地理解父 ID,您可以运行:
git log 8989ee0
和
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 历史是这样的:
d
C
b <<< 合并
一个
...
我从 a 创建一个新分支,樱桃挑选 c 和 d,然后从 b 中清除新分支。我可以决定再次在我的新分支中合并“b”。如果不再需要“b”或仍在另一个(功能/修补程序)分支中,旧分支将被弃用,并将被删除。
现在唯一的问题是计算机科学中最困难的事情之一:你如何命名新分支? ;)
好的,如果你失败了,尤其是。在 devel 中,您如上所述创建 newdevel,删除旧的 devel 并将 newdevel 重命名为 devel。任务完成。您现在可以在需要时再次合并更改。就像以前从未合并过一样......
正确标记的答案对我有用,但我不得不花一些时间来确定发生了什么。所以我决定为像我这样的案例添加一个简单直接的步骤的答案。
假设我们有分支 A 和 B..您将分支 A 合并到分支 B 并将分支 B 推送到自身,所以现在合并是它的一部分..但是您想回到合并之前的最后一次提交.. 怎么办你做?
转到您的 git 根文件夹(通常是项目文件夹)并使用 git log 您将看到最近提交的历史记录-提交具有提交/作者/日期属性,而合并也具有合并属性-因此您会看到它们如下所示:提交:
如果您希望恢复刚才推送的更改,这是一个非常简单的答案:
commit 446sjb1uznnmaownlaybiosqwbs278q87
Merge: 123jshc 90asaf
git revert -m 2 446sjb1uznnmaownlaybiosqwbs278q87 //does the work
我发现在两个已知端点之间创建一个反向补丁并应用该补丁会起作用。这假定您已经从主分支创建了快照(标签),甚至是主分支的备份,例如 master_bk_01012017。
假设您合并到 master 的代码分支是 mycodebranch。
收银员。在主服务器和备份服务器之间创建一个完整的二进制反向补丁。 git diff --binary master..master_bk_01012017 > ~/myrevert.patch 检查你的补丁 git apply --check myrevert.patch 应用带有签名的补丁 git am --signoff < myrevert.patch 如果你需要引入这个代码再次修复后,您需要分支恢复的 master 并签出修复分支 git branch mycodebranch_fix git checkout mycodebranch_fix 在这里您需要找到恢复的 SHA 密钥并恢复恢复 git revert [SHA] 现在您可以使用你的 mycodebranch_fix 来解决问题,一旦完成,提交并重新合并到 master 中。
关于 git revert -m 的 git doc 提供了一个链接来准确解释这一点:https://github.com/git/git/blob/master/Documentation/howto/revert-a-faulty-merge.txt
-m1 是当前正在修复的分支的最后一个父级,-m 2 是合并到此分支的原始父级。
如果命令行令人困惑,Tortoise Git 也可以在这里提供帮助。
我在已合并到 GitHub 存储库的主分支的 PR 上也遇到了这个问题。
因为我只想修改一些修改过的文件,而不是 PR 带来的全部更改,所以我不得不用 git commit --am
来amend
merge commit
。
脚步:
转到您要更改/还原一些修改过的文件的分支根据修改过的文件执行您想要的更改运行 git add * 或 git add
为什么有趣:
它保持 PR 的作者提交不变
它不会破坏 git 树
您将被标记为提交者(合并提交作者将保持不变)
Git 就像你解决了冲突一样,它会删除/更改修改文件中的代码,就像你手动告诉 GitHub 不要按原样合并它一样
正如 Ryan 所说,git revert
可能会使合并变得困难,因此 git revert
可能不是您想要的。我发现在这里使用 git reset --hard <commit-hash-prior-to-merge>
命令更有用。
完成硬重置部分后,您可以强制推送到远程分支,即 git push -f <remote-name> <remote-branch-name>
,其中 <remote-name>
通常被命名为 origin
。从那时起,您可以根据需要重新合并。
不定期副业成功案例分享
8989ee0
,7c6b236
,去哪一个。我怎么理解?git log 8989ee0
和git log 7c6b236
,您应该知道答案。