除了一些涉及合并差异的特殊情况(当你可以使用时--combined
),提交差异总是成对的。这改变了x..y
被解释的方式。不是这个意思“所有可以到达的 revs 不能到达y
的x
”,而是“比较 revx
和 rev y
”。
(这里值得注意的是,链接问题中的答案掩盖了与其他 git 命令x..y
不同的解释这一事实。)git diff
当你请求时E..topic
,git 会解析topic
到一个特定的提交——在这种情况下K
——然后将 in 中的树与 inE
中的树进行比较K
。这就是为什么您会看到来自G
andI
的更改,因为这些更改是J
通过合并引入的。
您可以比较F
and K
,但这仍然会显示 and 中的变化G
,I
因为同样,这些变化实际上是在 中J
。
事实上,只有一种方法可以在J
保持不变的同时忽略发生的事情F
,H
那就是建立一棵树,要么跳过它,要么恢复它。例如,从 开始,您可以根据和H
之间的差异添加补丁:J
K
K' <-- HEAD[detached]
/
B---D---F---H---J---K <-- topic
/ / /
A---C---E---G---I <-- master
(要做到这一点,git checkout topic~2
在 commit 时分离H
,然后git cherry-pick topic
添加,到你现在分离的,从到HEAD
所做的更改)。J
K
现在您可以将提交E
中的树与HEAD
(提交时K'
)中的树进行比较:
git diff E HEAD # or git diff E..HEAD or git diff E..
但总的来说,这不是人们想要审查的。事实上,由于您几乎可以肯定随后会K'
完全放弃 rev(生成它仅用于审查目的),他们将审查一个从未使用过的代码版本!
这就是为什么对链接问题的公认答案是git diff master..topic
- 这意味着与 完全相同的东西git diff master topic
,并且在这种情况下将树I
与树进行比较K
。您提议在分支上提交topic
一棵看起来像 的树K
。这就是将在topic
. 它与 rev I
in 中的代码有些不同master
。它所要做的不同是I
F
, H
,K
和为适应而进行的任何垫片工作的总和J
。它确实进行了更改G
(当然还有这些I
更改本身),但这些不是对 I
, 这些仅仅是合并在 I
.
审查代码的更彻底的方法是展示四个差异以供审查:
E
对比F
F
对比H
H
vs J
(也许是组合的差异,H
-and- I
vs J
)
J
对比K
第一个差异告诉您的审阅者,如果他们接受它,就可以检查出看起来像的树F
(这当然是真的,只是git checkout F
)。第二个差异告诉您的审阅者,F
在他们的存储库中,将有可能签出H
(如果他们接受的话)等等。显然,四个审查比一个更难,这就是为什么人们接受比较I
与K
.