git diff / log以及指定的开始/结束提交的顺序

时间:2017-08-21 09:05:03

标签: git

运行git loggit diff时,似乎提交指定的顺序非常重要。

我的分支提示是: 8ad4ff890446 ,我的分支基地是: 6e91a6615

当我从头到脚运行git log时,我得到:

$ git log --oneline 8ad4ff890446..6e91a6615
d9b526fb ...
a5f4ad92 ...
af96bb6c ...
8d416ba9 ...
c7a37d4f ...

如果我反转参数并从基数到提示运行git log我得到:

$ git log --oneline 6e91a6615..8ad4ff890446
2d6055e7 ...
656ac5b3 ...
3a4e2bbc ...

最后一次调用实际上是我所期望的 - 自基数以来只引入了3次提交。

base -> tip开始,为什么我只获得3次提交(正确),而从tip -> base开始提交时只提交5次?

2 个答案:

答案 0 :(得分:3)

double dot语法并不意味着"从X到Y",这意味着:

  

最常见的范围规范是双点语法。这基本上要求Git解决一系列提交,这些提交可以从一个提交到达,但是不能从另一个提交到达。

演示输出的一个非常简单的例子是:

                             master
                                v
A---B---C---D---E---F---G---H---I
             \
              \-J---K---L
                        ^
                      branch

在这里,master通过5次提交超越你的分支,你的分支在3次提交之前领先于master。

在这种情况下,这个命令:

git log branch..master

应该列出5个提交E-I,而这个:

git log master..branch

应该列出3个提交J-L。

如果您使用的是Windows,则可以打开命令提示符并导航到某处的临时或新(空)文件夹,然后粘贴这些命令,执行它们:

git init
for %f in (a b c d e f g h i) do (echo %f>test.txt && git add . && git commit -m "%f")
git checkout HEAD~5 -b branch
for %f in (j k l) do (echo %f>test.txt && git add . && git commit -m "%f")

然后您可以执行这些命令并检查输出

git log branch..master
git log master..branch

答案 1 :(得分:1)

TL; DR:git diff作弊;不要把它当作git log那样做,因为它没有。

Lasse V. Karlsen's (correct) answer on git log之外,您需要知道git diff(ab)使用两点和三点符号,其方式与其他Git命令不同。

我发现git diff最合理的语法是:

git diff <commit1> <commit2>

这会将<commit1>的存储树与<commit2>存储的树进行比较,因此很容易看出它是如何工作的:实际上,Git提取了两个提交,然后比较他们。输出是一系列指令:将此行添加到文件1,从文件2中删除该行,并可能完全删除文件3。如果您将这些说明应用于<commit1>的树,则会获得<commit2>的树。

如果你反转两次提交,差异就会在交换提交的情况下完成,所以你得到的说明是:删除文件1的第一行, add < / em>第二行到文件2,创建一个全新的文件3,带有全新的内容。这些说明会将<commit2>的树转换为<commit1>的树。

到目前为止一直很好 - 但是当你运行git diff <commit1>..<commit2>时会发生什么? git log语法意味着此处可能存在许多提交,但git diff无法向您显示多次提交。 diff代码主要是 1 只比较两个提交,而不是一些任意大量的提交。

秘诀是,当A..B语法被赋予时,git diff 会完全抛弃..部分。所以git diff A B完全相同。如果您反转这两项git diff B..A,Git就会像运行git diff B A那样完全相同。

真正棘手的部分是当您使用三个 -dot(或对称差异)语法git diff A...Bgit log A...B时会发生什么。同样,git diffgit log不同(如果我可以在这里使用该词:-))。使用git log及其面向脚本的姐妹命令git rev-list,三点语法工作as advertised,生成所有提交的集合,可以从两个指定提交中的一个提交到达,不包括可提交的提交&#34;同时&#34;来自两个提交。

git diff所做的是找到AB合并基础,并针对提交B进行区分。 The code it uses to do this is flawed,但适用于大多数情况和大多数论点。

1 这个词&#34;主要是&#34;因为git diff会在某些情况下产生组合差异,特别是在查看合并提交时。组合差异are documented,但in a rather scattered fashion,并且描述得有点棘手。关于仅显示从所有父母修改的文件的关键句子仅在第二个链接部分中,当您查找有关读取输出的描述时,很容易错过。