git:具有提交限制的累积差异

Tac*_*tex 6 git diff

git log有一些非常有用的提交限制选项,例如--no-merges--first-parent。在为一系列提交生成累积差异补丁/统计/数字统计时,我希望能够使用这些选项。

使用这些命令:

git log --oneline --first-parent --no-merges --patch   29665b0..0b76a27
git log --oneline --first-parent --no-merges --stat    29665b0..0b76a27
git log --oneline --first-parent --no-merges --numstat 29665b0..0b76a27
Run Code Online (Sandbox Code Playgroud)

差异不是累积的(每个提交的更改单独列出)。

使用这些命令:

git diff --patch   29665b0..0b76a27
git diff --stat    29665b0..0b76a27
git diff --numstat 29665b0..0b76a27
Run Code Online (Sandbox Code Playgroud)

差异累积的,但不幸的git diff是不支持提交限制选项。

所以我想要的是git diff结合git log.

我的一个想法是用来git log生成一个提交哈希列表,然后以某种方式将该列表通过管道git diff生成指定提交的累积差异。像这样的东西(显然这种管道散列的方法git diff实际上不起作用):

git log --pretty=format:%h --first-parent --no-merges 29665b0..0b76a27 | git diff
Run Code Online (Sandbox Code Playgroud)

其中--pretty=format:%h输出匹配提交的哈希值。


更新

感谢@torek 和@twalberg,我现在git diff更清楚地了解了的操作。范围语法29665b0..0b76a27确实具有误导性,我现在明白它实际上并没有在一系列提交上执行累积差异。查看文档,我发现了这个:

"diff" 是关于比较两个端点,而不是范围,范围符号 ( <commit>..<commit>and <commit>...<commit>) 并不意味着gitrevisions(7) 的" SPECIFYING RANGES" 部分中定义的范围。

考虑到这一点,我将重新表述我的问题。使用这些命令:

git log --oneline --first-parent --no-merges --patch   29665b0..0b76a27
git log --oneline --first-parent --no-merges --stat    29665b0..0b76a27
git log --oneline --first-parent --no-merges --numstat 29665b0..0b76a27
Run Code Online (Sandbox Code Playgroud)

为每个匹配的提交单独列出更改。如何组合这些单独的更改,以生成累积补丁/统计/数字统计?

链接的可能重复问题的答案很有帮助,提出了一个解决方案:创建一个临时分支,挑选相关提交,然后生成差异。

我刚刚发布了一个使用这种技术的答案,但我仍然很想知道是否有不需要临时分支的解决方案?

tor*_*rek 3

这里至少存在一种基本的误解。具体来说,git diff根本不是真正的累积:相反,它只是成对的。

\n\n

具体来说,这两个命令执行相同的操作:

\n\n
git diff rev1 rev2\ngit diff rev1..rev2\n
Run Code Online (Sandbox Code Playgroud)\n\n

也就是说,在 中git diff,实际上根本就不存在范围这样的东西。

\n\n
\n\n

抛开这些,让我们来看看 的幕后花絮git loggit log范围的作用实际上是1范围交给git rev-list,这会生成范围中每个转速的列表,并一路应用修饰符:

\n\n
git rev-list 29665b0..0b76a27\n
Run Code Online (Sandbox Code Playgroud)\n\n

吐出从0b76a27无法达到的每一个转速29665b0。添加--first-parent--max-parents=1(又名--no-merges)等会过滤掉此处列出的一些转速。

\n\n

最终结果返回给git log,然后按顺序查看每个修订版本git rev-list\xe2\x80\x94,这也可以通过--date-order等等进行控制--topo-order;请参阅git rev-list \xe2\x80\x94 的文档,并显示每个日志条目,可能还包括生成的差异git diff-tree(对于单父提交,将提交与其父提交进行比较)。

\n\n

那么,您可以做的就是git rev-list直接调用您自己,然后从其输出中剥离顶部和底部修订。(在这种特殊情况下--topo-order,您可能也希望确保最后一个转数确实是最早的,从图表角度来看,无论日期如何。)例如,在脚本中:

\n\n
#! /bin/sh\ntempfile=$(mktemp -t mydiff)\ntrap "rm -f $tempfile" 1 2 3 15\ngit rev-list 29665b0..0b76a27 --first-parent --no-merges --topo-order > $tempfile\n# remember that the first rev listed is the last rev in the range\nlast=$(head -1 $tempfile)\nfirst=$(tail -1 $tempfile)\nrm -f $tempfile # done with it, don\'t leave it around while showing diff\ngit diff $first $last\n
Run Code Online (Sandbox Code Playgroud)\n\n

通过使用git rev-parse解析选项并将它们分为 diff 选项与 rev-list 选项,您可以变得更加奇特,但这远远超出了您在这里所需要的。上述改进的主要内容是摆脱硬编码的修订范围。

\n\n
\n\n

1一些 git 命令确实确实将参数传递给git rev-list,因为它们只是使用git rev-list其他 git 命令来处理此问题的 shell 脚本。其他的则构建在一起,因此git loggit rev-list实际上是一个二进制文件,一个部分将工作交给另一部分,但不调用新程序。

\n\n

无论如何,请注意,git log master只需将其master交给git rev-list,它就会生成从分支标签可到达的所有转速的列表master。如果您添加--no-walk,git rev-list则仅产生一版本,因此git log仅显示该版本。

\n

  • 除了它会破坏许多预先存在的(但格式不正确)代码之外,我个人更喜欢“git”人员不允许使用范围符号“git diff”(以及其他几个地方)没有意义)并避免这种类型的混乱...... (3认同)