TL;DR 答案: git diff根本不做对称差异(也没有任何集合)。它只是找到一些提交对,并区分那对提交。
首先(顺便说一句,为了清楚起见,以防各种访问者在“对称差异”中遇到“差异”一词,git diff而不是几乎不相关的命令),让我在这里注意对称差异是git rev-list指to 是图论对称差,即集合并集减去集合交集。在这种情况下,联合和相交的两个集合是可以从两个命名提交中的任何一个访问的所有提交的集合:git rev-list a...b解析a以获取提交 ID,然后找到从该提交可访问的所有提交;它解析和处理b类似;然后交叉点从合并基础本身开始,然后返回历史记录。
在您的示例中,这只留下了两个分支提示提交。您添加了--boundary哪些原因git rev-list包括分支点提交(两个历史记录在集合交集的尖端连接)以获得此:
$ git log --oneline --graph --boundary a...b
* aaaaa Commit to Branch a
| * bbbbb Commit to branch b
|/
o 000000
没有--boundary我们会省略提交o(使--oneline --graph无用)。
您当然也正确,使用两个点,a..b您可以从无法到达的提交b中获得可访问的提交(通常这也会省略其自身标识的提交,但再次将其放回结果集中)。aa--boundary
git diff 不同
git logandgit rev-list命令对完整的提交集进行操作。例如,如果您正在查看一组 75 个提交,git log则会显示所有 75 个提交(除非您使用 限制它-n)。
git diff命令不一样。它产生两个提交的比较(差异),并且——只要我们忽略仅适用于合并提交的“组合差异”——它只会查看两个提交。鉴于:
$ git diff HEAD~5 HEAD
很明显,这将 commitHEAD~5与 commit进行比较HEAD,但即使HEAD~5..HEAD名称为 5 个或更多1 个提交:
$ git diff HEAD~5..HEAD
仍然只是比较相同的两个提交,HEAD~5反对HEAD.
(注意:
$ git diff HEAD..HEAD~5
比较相同的两个提交,但告诉您如何修改HEAD提交以产生HEAD~5提交,而不是更典型的“如何修改HEAD~5产生HEAD”。所以顺序确实很重要,但本质git diff上只是在这里用空格替换两个点。)
该git diff命令同样采用三点表示法。因为它仍然只会查看两个提交,所以当你给它三点符号时,它会像往常一样找到合并基础提交,但不是修改输入来假装你只是分别命名了左侧和右侧提交,它修改输入以假装您在左侧命名为合并基础,在右侧命名为右侧提交。
对于实际的对称差异(集合操作),操作数的顺序无关紧要。但是由于git diff找到一对,然后用合并基替换左操作数,并将其与右操作数进行比较,这里的顺序很重要:将“最终结果”提交名称放在右边,因为git diff会将合并基放入作为左边。
HEAD~5..HEAD产生所有可到达的提交HEAD,但无法从HEAD~5. 在线性结构中,这是五个提交:
... - HEAD~5 - HEAD~4 - HEAD~3 - HEAD~2 - HEAD~1 - HEAD
- excluded - -------- included: five commits ---------
但是,对于分支和合并结构,其他提交位于此集中:
HEAD~3
/ \
... - HEAD~5 - HEAD~4 HEAD~2 - HEAD~1 - HEAD
\ /
HEAD~2^2
例如,这个结构在结果集中有六个提交。