撤销合并与重置合并
我猜你实际上已经是最新版本了。
问题在于git revert不会撤销合并,它只会撤销合并所带来的更改。当你创建一个合并提交时,你正在组合这两个分支的提交历史。
合并
develop
|
A---B---C
\ \
E---F---M
|
newfeature
在上述情况中,
develop
分支被合并到
newfeature
分支中,创建了
M
提交。如果你运行
git log newfeature
命令,你将会看到来自两个分支的所有提交记录,但是从
newfeature
分支的角度来看,所有这些变更都是由
M
提交完成的。
撤销操作
git revert
命令不会删除任何提交记录,而是创建一个新的提交记录,用于撤消先前提交所包含的更改。例如,如果你有一个包含以下差异的提交记录...
-This is the old sentence.
+This is the new sentence.
如果撤销这个提交,撤销命令将创建一个新的提交,只执行相反的差异,它只是翻转符号。
-This is the new sentence.
+This is the old sentence.
这对于撤销其他开发人员已提交的更改非常有用。它可以推进历史记录而不是更改历史记录。
撤销合并
然而,在非快进式合并的情况下,这可能会产生不良影响。
develop
|
A---B---C
\ \
E---F---M---W
|
newfeature
假设 W 是一个还原提交,您可以看到运行命令
git log newfeature
仍将包括来自 develop 分支的所有提交。因此,从 develop 进行额外的合并将不起作用,因为它没有发现您的分支中存在任何缺少的内容。
使用
git reset 而不是 revert。
在以后,如果该合并尚未与其他开发人员共享,您可能需要考虑使用命令
git reset --hard <ref>
(其中
<ref>
是合并的提交哈希值)撤消合并。在上面的示例中,在创建了合并提交
M
后,运行命令
git reset --hard F
将得到以下结果。
develop
|
A---B---C
\ \
E---F---M
|
newfeature
正如您所看到的,这种技术并不会像某些人想象的那样消除提交,而是将您的分支移回到您选择的提交。现在,如果您运行
git log newfeature
,您只会得到提交
F
、
E
和
A
。现在合并实际上已经从您的分支历史中删除了,因此稍后尝试重新合并到
develop
将不会引起任何问题。
这种方法并不是没有其复杂性。请意识到,您现在正在修改历史记录,因此如果
newfeature
分支在
M
合并后被推送到远程分支,则git会认为您仅仅是过时了,并告诉您需要运行
git pull
。如果只有您在远程分支上工作,则可以放心地进行强制推送-
git push -f <remote> <branch>
。这将具有相同的重置效果,但是在远程分支上。
如果该分支被多个开发人员使用,并且他们现在已经从中拉取了内容-那么这是一个坏主意。这正是
git revert
有用的原因,因为它可以撤消更改而不更改实际历史记录。
在历史记录中使用重置选项仅适用于未共享的提交。
解决方案 - 恢复还原。
如果合并提交已经共享,那么最好的方法可能是在该合并上使用git revert
。但是正如我们之前所说的,你不能简单地将分支合并回去并期望从该分支中重新出现所有更改。答案是撤销还原提交。
假设你在 newfeature
中撤销了合并后,在 develop
分支上进行了一些工作。你的历史记录将类似于以下内容。
develop
|
A---B---C---D
\ \
E---F---M---W
|
newfeature
如果你现在将
develop
合并到
newfeature
中,你只会得到
D
,因为它是唯一一个不在
newfeature
分支历史记录中的提交。你还需要撤销那个
W
提交-
git revert W
应该可以解决问题,然后再执行
git merge develop
。
develop
|
A---B---C-----------D
\ \ \
E---F---M---W---M---G
|
newfeature
这将恢复原始合并提交所做的所有更改 - 实际上是由
C
和
B
进行的,但在
W
中被撤销,然后通过新的合并提交
G
引入了
D
。我建议在合并最近的更改到
develop
之前撤销撤销,我怀疑按照这个顺序做会更少地触发冲突。
TL;DR
撤销会创建一个“撤销提交”。当撤销撤销时,您需要在第一次撤销时创建的撤销提交上运行撤销命令。应该很容易找到,git倾向于自动注释撤销,以便它们以“Reverted”单词开头。
git revert <commit>
git revert W
而不是git revert M
。此外,第二个差异是错误的,它解释了一个还原提交。我修复了 +/- 符号。 - eddiemoya