这里至少存在一种基本的误解。具体来说,git diff
根本不是真正的累积:相反,它只是成对的。
具体来说,这两个命令执行相同的操作:
git diff rev1 rev2
git diff rev1..rev2
也就是说,在git diff
,首先确实不存在范围这样的东西。
With that out of the way, let's take a look behind the scenes at git log
. What git log
does with a range is really1 to hand the range to git rev-list
, which produces a list of every rev in the range, applying the modifiers along the way:
git rev-list 29665b0..0b76a27
吐出每一个可达到的转速0b76a27
也无法从以下位置到达29665b0
。添加--first-parent
, --max-parents=1
(aka --no-merges
),依此类推,过滤掉此处列出的一些转速。
最终结果返回给git log
,然后查看顺序中的每个修订git rev-list
将它们吐出来——这也可以通过以下方式控制--date-order
and --topo-order
等等;看到git rev-list 的文档- 并显示每个日志条目,可能还包括由git diff-tree(对于单父提交,将提交与其父提交进行比较)。
那么你能做的就是调用git rev-list
你自己直接,然后从其输出中剥离顶部和底部的修订。 (在这种特殊情况下,您可能想要--topo-order
同样,以确保最后的转数确实是最早的,从图表角度来看,无论日期如何。)例如,在脚本中:
#! /bin/sh
tempfile=$(mktemp -t mydiff)
trap "rm -f $tempfile" 1 2 3 15
git rev-list 29665b0..0b76a27 --first-parent --no-merges --topo-order > $tempfile
# remember that the first rev listed is the last rev in the range
last=$(head -1 $tempfile)
first=$(tail -1 $tempfile)
rm -f $tempfile # done with it, don't leave it around while showing diff
git diff $first $last
你可以通过使用变得更加花哨git rev-parse
解析选项并将它们拆分为 diff 选项与 rev-list 选项,但这远远超出了您在这里所需要的。上述改进的主要内容是摆脱硬编码的修订范围。
1Some git commands really really do hand arguments off to git rev-list
, as they're just shell scripts that use git rev-list
and other git commands to handle this. Others are built together, so that git log
and git rev-list
are actually a single binary, and one part hands a job off to another part, but without invoking a new program.
无论如何,请注意git log master
简单的双手master
off to git rev-list
,它生成从分支标签可到达的所有转速的列表master
。如果你添加--no-walk
, git rev-list
仅产生一转,因此git log
仅显示该修订版。