foo/bar
,那么正确的命令是什么(我假设是git diff
的参数),以查看整个差异?(这个分支接收了许多来自其他分支的不同合并。)
编辑:也许我对整个分支差异的要求没有那么清楚,但我的意思是取两个提交:
- 分支的最后一个提交。
- 分支的父提交。
git diff
命令。有没有一种-快捷-的方法来指定这两个提交?foo/bar
,那么正确的命令是什么(我假设是git diff
的参数),以查看整个差异?(这个分支接收了许多来自其他分支的不同合并。)
编辑:也许我对整个分支差异的要求没有那么清楚,但我的意思是取两个提交:
git diff
命令。有没有一种-快捷-的方法来指定这两个提交?不存在所谓的“分支差异”。只有提交的差异。1选择任意两个提交,您就可以比较它们。但是一个分支……请参见我们所说的“分支”究竟是什么? 一个分支不是两个提交。分支名称可以选择一个提交,或者您可以将分支名称与其他内容一起使用以选择许多提交。但是一个提交不够,而许多提交又太多了。您必须精确地选择两个提交。
请注意,git diff branch1 branch2
和git diff branch1..branch2
的含义完全相同:将名称branch1
转换为一个特定的提交,将名称branch2
转换为一个特定的提交,然后对这两个特定的提交进行差异比较。再次参见我们所说的“分支”究竟是什么?
1您还可以将提交与您的工作树或索引进行比较;您还可以将您的索引与您的工作树进行比较。除此之外,还有专门的差异形式来查看仅一个文件,甚至是Git存储库外的文件;您可以让Git计算几个不同的差异,然后将它们组合成一个单独的合并差异。但是,合并差异仅设计用于合并提交,并将最终合并结果与每个父提交进行比较。它不适用于查看许多任意提交,仅用于检查合并的最终结果。
您可能能够得到您想要的,但实际上也不存在所谓的“分支的父提交”。例如,请考虑以下图表片段:
...--o--A--o--o--o <-- br1
\
o--B--o <-- br2
\
o--o <-- feature
...--A--o--o--B--o--C--o <-- devel
\ / /
o----o--o--D--E--F <-- feat
在这里,feat
已经多次被引入到devel
中,在B
和C
处。它可以再次被引入; 如果是这样,那么将引入相对于D
的E
和F
所做的更改。但是从这个图形绘制中可以明显看出,feat
最初是从提交A
“增长”的,因此A
是您想要的父级吗,还是与B
或C
更相关?如果不是C
,则会有问题,因为Git不会独立地记录A
或B
(它也不会独立地记录C
,但我们有一个简单的方法来查找,嗯,不是C
,而是D
;但是D
可能是您想要的)。此外,虽然A
似乎很明显是起点,但这仅仅是因为我绘制了这个图形片段的方式。不同的视角可能会让人们清楚地看到存在更早的起点——实际上,除非您专门记录一个起点(标签非常适合此目的),否则根本没有真正的“起点”。
A
或B
,以及在第二个图表中找到D
Git支持——因为它必须支持,因为git merge
需要它——合并基础的概念。如果像上面那样绘制提交的图形,则两个提交的合并基础很容易(有点)看出来。这些提交通常是两个不同的分支尖端提交(如果不是,我们只是假装它们是)。您只需从每个提示开始,然后向左/向后跟随其连接线。最终,这需要在某个公共提交处“汇合”。那就是第一个提交,它在这些分支上都存在,并且该提交是合并基础。
这是那张第一个图表:
...--o--A--o--o--o <-- br1
\
o--B--o <-- br2
\
o--o <-- feature
从feature
和br1
的顶端开始,检查是否已经有共同的提交。没有,所以向后看一下。在br1
上往回看,有一个点在提交A
处进入。我们能够从feature
到达提交A
吗?可以:我们从feature
的顶端开始,往回走两步到B
,再往回走两步到A
。那就是第一个共享提交——既在br1
上,又在feature
上的第一个提交。因此,这就是合并基础。
br1
和br2
的合并基础同样是提交A
,br2
和feature
的合并基础是提交B
。因此,给定两个分支名称或仅两个提交ID,我们可以找到它们的合并基础。
第二个图的合并基础更加棘手。提交C
是一个合并提交。这意味着它有两个父箭头,一个指向仅在devel
分支上的提交,另一个指向feat
上的提交D
。(顺便说一下,这意味着我们在做提交C
之前已经做了提交D
。这里的图形标识有点误导人!对此我感到抱歉。)这使得提交D
从devel
的顶端可达,因此提交D
在两个分支上都存在——加上它距离分支顶部最近,就使提交D
成为devel
和feat
的合并基础。
git merge-base
命令git merge-base A B
将查找这两个命名分支的合并基础。理想情况下,这将是一个单独的提交ID。(如果两个分支实际上没有共同的历史记录,即它们具有不相关的历史记录,则可能没有ID;这很少见,或者可能有多个合并基础,在这种情况下,git merge-base
会随意选择一个。但是很难获得多个合并基础,因此通常您不必担心这个问题。)
因此,如果此时的目标是在第二个图中找到提交D
,并将其与feat
的顶端进行比较,可以执行以下操作:
git merge-base devel feat # and note the commit ID
git diff <hash> feat
因为这是相对常见的需求,git diff
已经将其内置。语法借用了三个点的语法,这在每个其它Git命令中都有不同的含义:
git diff devel...feat
git diff
,并且仅限于git diff
,这意味着“查找这两个分支尖端提交之间的合并基础,然后将其与第二个提交进行差异比较”。br1
或br2
来查找A
或B
,并将其与feature
的末端进行比较。git diff br1...feature
只需简单地输入git diff commit_hash1 commit_hash2
其中commit_hash1
是您分支上第一个提交的父提交哈希值(请注意,它不是您分支的一部分),而commit_hash2
是您分支当前指向的提交(即您分支目前所在的提交)。
git diff branch^..branch
- Pocketsgit diff master...foo/bar
。如果你想要自从当前分支与上游分支分离以来的所有内容,那么就是git diff @{upstream}...
或者git diff @{u}...
。请注意三个点,这是“自合并基础以来”的意思,它是特定于diff的,因为你的请求非常普遍。 - jthill