I am trying to revert a merge, but I don't know whether to use git revert -m 1 <merge commit's sha>
or git revert -m 2 <merge commit's sha>
. How do I find out which parent is -m 1
and which parent is -m 2
?
答案 0 :(得分:9)
嗯,超短的回答是,它总是-m 1
。 :-)但这值得一些解释:
订购了父母,git log
和git show
等命令显示了订单:
commit c13c783c9d3d7d3eff937b7bf3642d2a7fe32644 Merge: 3f7ebc6ec 39ee4c6c2
所以这里3f7ebc6ec
是父#1,39ee4c6c2
是父#2。
后缀^
操作采用以下相同的值:
$ git rev-parse c13c783c9d3d7d3eff937b7bf3642d2a7fe32644^1 3f7ebc6ece46f1c23480d094688b8b5f24eb345c
(当然...^2
将是另一个)。
绘制图表的程序(包括git log --graph
)将向您展示这些连接方式。
但最重要的是,任何合并的第一个父项是您进行合并时当前的提交。
特别是,这意味着如果您在分支main
并运行git merge sidebranch
,那么您现在提交的提交(如果一切顺利)或最终(如果您必须手动解决合并)拥有第一个父级,main
分支的上一个提示。因此,它的第二个父母是sidebranch
的提示。
那么,假设我们从头开始:
...--o--*--A--B------C <-- main
\
D--E--F--G--H <-- sidebranch
当我们运行git merge
时。公共基础提交是*
,Git通过这样做来实现新的合并提交M:
git diff * C
(我们改变了什么?)git diff * H
(他们改变了什么?)然后合并这两组更改并将其应用到*
,为我们提供最终结果:
...--o--*--A--B------C--M <-- main
\ /
D--E--F--G--H <-- sidebranch
现在,如果A-B-C
中的所有内容都发生了变化,那么完全独立于D-E-F-G-H
中所有内容的变化,那么 Git如何做到这一点并不重要因为它在放弃A-B-C
更改的同时保持D-E-F-G-H
更改。
但是,如果B
与F
大致相同,即B
和F
修复错误,该怎么办?在这种情况下,我们不想要撤消B
和F
的共享更改,即Git获取了一份副本。 这是-m 1
部分的来源。
当git revert
撤消某些更改时,它会运行自己的git diff
。它运行的git diff
将您要还原的提交与其父级进行比较。对于任何普通的非合并提交,这很容易:比较B
vs A
,或E
vs D
,或者其他什么,看看发生了什么,然后退出。但是,使用合并提交,要比较哪个父项并不明显(除了它是:-))。这里的第一个父级是C
,所以,如果我们运行,请查看我们得到的内容:
git diff C M
C
和M
之间的变化是我们通过添加从D-E-F-G-H
到我们已经拥有的变更的变化而获得的变化如果我们将A-B-C
与M
进行比较,请在*
中找到em>。换句话说:
如果B
和F
重叠100%,则C
- vs - M
中的更改为D-E-G-H
:所有内容除外重叠。所以我们最终会恢复那些。
如果F
的更多更改<{1}},则B
- vs - C
中的更改为{{ 1}}:我们最终还原了这些更改,但不是M
中的更改。
如果D-E-(some-of-F)-G-H
的更少更改<{1}},则B
- vs - F
中的更改仅为{ {1}}再次,我们最终还原那些。
由于第一个父级是B
,我们要退出C
更改(不包括我们已经通过M
获得的任何更改),我们希望D-E-G-H
在此还原