如何解决如何 git diff 分歧分支 TL;DR长ish有趣的范围
我在我的分支上重写了一些提交历史,所以我的分支与远程分支不同:
Switched to branch 'dev'
Your branch and 'origin/dev' have diverged,and have 3 and 3 different commits each,respectively.
是否有一种简单的方法可以在不同版本(即我的本地分支和远程分支)之间git diff
?
我知道我可以使用 git diff commit1..commit2
来区分 2 个提交,但在这种情况下,我想区分我分支上的三个本地提交和三个远程提交。
解决方法
使用 git fetch
获取后
git diff <mainbranch_path> <remotebranch_path>
例如git diff develop origin/develop
TL;DR
使用 git range-diff
——在本例中为 git range-diff origin/dev...dev
(注意这里的三个点)。
长(ish)
首先,让我们绘制设置。以下是两组提交,如在您自己的存储库中所见:
F'-G'-H' <-- dev
/
...--D--E
\
F--G--H <-- origin/dev
提交 F
、G
和 H
——这里的字母代表真实的哈希 ID,它们太大太丑了,无法打扰——是之前的三个你做了你的工作;他们新改进的替代品分别是 F-prime、G-prime 和 H-prime。
通过仅比较这两个提交来比较最终结果非常容易:git diff dev origin/dev
或 git diff origin/dev dev
将比较提交 H
和 H'
(dev
选择 H'
,origin/dev
选择 H
)。但这不是你想要的,不是真的:
- 您想先比较
F
与F'
;然后 - 您想比较
G
与G'
;最后 - 您想比较
H
与H'
。
单个 git diff
命令只能生成这三个中的最后一个。
暴力解决方案是自己运行三个 git diff
,一次一个。要命名提交 F'
,您可以编写 dev~2
;要命名提交 G'
,您可以编写 dev~1
(或 dev~
或 dev^
——所有这些工作;有关更多信息,请参阅 the gitrevisions documentation)。要将提交命名为 F
,请使用 origin/dev~2
,依此类推。
不过,自 Git 2.19 以来,有一个新命令可以为您执行此操作。如上面的 TL;DR 所述,这是 git range-diff
。
range-diff 命令需要知道要比较的两个范围。你可以明确地给他们:
git range-diff origin/dev~3..origin/dev dev~3..dev
我们在这里使用 ~3
而不是 ~2
,因为用两点 ..
表示法表示的范围在数学上是半开区间:它们包括最终提交,但不包括开始提交。 (在心理上,您可以将其视为想要在结果中进行 3 次提交,因此 X~3..X。事实是 (X~3 .. X] 当然很重要,因为 [X~3 .. X ) 会忽略范围的错误结束,但无论哪种方式,半开区间都会补偿通常的 fencepost error。) 再次参见 gitrevisions。
在这种情况下更容易,不过,我们可以使用 三-dot 表示法,git range-diff
稍微特殊处理。如 gitrevisions 文档中所述,三点表示法意味着在集合论方面的对称差运算,因此:
git range-diff origin/dev...dev
暗示该命令应该检查由要么 origin/dev
可访问的提交——即,在后面提交H
——或 dev
,即在背面提交 H'
;但应该不检查可从两个名称访问的提交,即提交 E
及更早。因此,这正好选择了所需的两组提交:F-G-H
和 F'-G'-H'
。
有趣的范围
剩下的问题是:
-
这是如何工作的?为什么我们不必在任何地方提及
X~3
,对于某些X
? -
这些顺序是否正确?如果不正确,您将得到一个范围差异,它描述了从新的和改进的提交中向后的情况——可能是由于 rebase ——致那些又老又烂的人。
让我们先解决问题 1,然后解决问题 2。我们实际上已经回答了问题 1,但只是借助了一些人可能不熟悉的集合论。
Symmetric difference 是根据集合定义的:它是联合减去交集。给定两个集合A和B,对称差A⊖B或AΔB可以计算为A∖B(读作“A排除B”)和B∖A(或等效地,作为从中减去交集的结果)的并集em> 工会,这是我自己通常认为的,并在此处首先说明)。
在上面,我们写到:从 dev
可达的所有提交的集合,不包括从 dev~3
} 可达的所有提交的集合。那是我们的dev~3..dev
。这是一种非常准确的方法,可以从 E
开始的 每次提交中去除从 H'
开始的每个提交并向后工作,然后向后工作。但毕竟我们不必如此精确。我们可以偷懒,说:每次从 H'
开始向后工作的提交,去掉从 H
开始的每一次提交并向后工作。而 F-G-H
是在那个集合中,要求将它们从那个集合中剥离是无害的:A∖B不需要B中的东西首先是A。
因此,我们可以使用 dev~3..dev
代替 origin/dev..dev
向后去除 E
中的提交。当然,origin/dev
需要输入 10 个字符,而 dev~3
只有 5 个字符,所以我们在这里没有真正获得任何东西。
问题是,出于同样的原因,我们可以编写 dev..origin/dev
以从向后从 H 提交中排除向后提交 E
。这次它确实节省了一些输入,而且——甚至更好——如果我们有某种符号让我们只需输入A和B 在这里,我们只需键入每个名称一次。 这是我们的对称差分符号,因此我们可以只输入 origin/dev...dev
(三个点)或 dev...origin/dev
(仍然是三个点)。
现在让我们解决问题 2,获取正确的顺序。我们现在咨询 the git range-diff
documentation,它说:
<rev1>...<rev2>
相当于传递 <rev2>..<rev1>
和 <rev1>..<rev2>
。
现在,最初我建议:
git range-diff origin/dev~3..origin/dev dev~3..dev
也就是说,我们将 old 范围的提交放在第一位,新 范围的提交放在第二位。如果我们运行:
git range-diff origin/dev...dev
那么 <rev2>
是 dev
,所以“相当于”部分变成:
git range-diff dev..origin/dev origin/dev..dev
这使用了第 1 项中的技巧来制作两个单独的范围表达式,并确保 second 范围表达式(确定哪些提交是“新的”)以指定的 second 结尾rev,即dev
。所以 origin/dev...dev
是正确的顺序。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。