使用git log命令显示两个分支之间的提交差异,包括共同祖先。

4
在从主分支(例如 master)创建的功能分支上工作时,我们可以使用以下 git 命令查看已添加到 feature 分支但未在 master 分支上的提交记录列表:
git log --oneline master..HEAD

这会输出一个关于feature分支上没有在master分支上的提交的简短总结(请注意,此命令在检出feature分支之后运行):

$ git log --oneline master..HEAD
1ca070a (HEAD -> feature) foo the bar
03a1047 baz the wuz
c9e8279 fop the sip
6ee6d6f up the ante
5812200 bop the binky

问题是,在master分支上它不显示共同的祖先提交记录。我希望这个命令能够包含一个额外的行,即共同的祖先提交记录,就像这样:
1ca070a (HEAD -> feature) foo the bar
03a1047 baz the wuz
c9e8279 fop the sip
6ee6d6f up the ante
5812200 bop the binky
fb37d68 (master) fuzzy the wuzzy

我认为将master替换为master~1将包括共同祖先之前的一个提交,因此包括共同祖先。

git log --oneline master~1..HEAD

无论我指定master还是master~1,日志摘要总是相同的。

$ git log --oneline master~1..HEAD
1ca070a (HEAD -> feature) foo the bar
03a1047 baz the wuz
c9e8279 fop the sip
6ee6d6f up the ante
5812200 bop the binky

我的问题是,如何在日志摘要中包含共同的祖先提交?请注意,共同的祖先不一定是master分支的末尾。


~1 可能已经实现了你想要的功能。(如果没有,那就意味着你已经将提交添加到了 master 分支。)尝试使用 git log --all --decorate --oneline --graph 命令来查看图形,以确定 master~1 实际上是哪个提交,从而找出为什么 master~1..HEAD 在这里失败了。同时,考虑使用 --boundary 标志,但根据我的经验,这会选择太多的提交。 - torek
@torek,你说得完全正确——如果共同祖先提交是master的末尾,则只有使用master~1才会显示祖先提交。(如果我将feature分支变基到master的末尾,则使用master~1会按预期显示祖先提交。) - charlesreid1
2个回答

4

似乎没有一个git命令可以完全做到这一点。 master..HEAD语法表示:

HEAD上的提交,但master没有

以下说法是等效的:

git log --oneline master..HEAD
git log --oneline HEAD --not master

如果你在处理合并提交,特别是当你想要排除历史记录中的某些部分时,向git解释你想要排除哪些部分是很复杂的。

bash 解决方法

但是,你可以告诉git log应该显示多少个提交,因此通过一些bash技巧,以下命令应该能够实现你所需的功能:

git log --oneline -$(( $(git rev-list --count HEAD ^master) + 1))

解释如下:

  • $(git rev-list --count HEAD ^master) 统计当前分支从 master 分支以来的提交数。
  • $(( num + 1 )) 将 num 值增加一。
  • 接着运行 git log --oneline -123(其中 123 是你的分支上提交数加 1),以显示最近的提交。

3

我发现这种 --boundary 经常包含 太多 提交记录,但是:

git log --boundary --right-only --oneline master...HEAD

应该可以接近你想要的结果。添加 --graph (为了完整性,还有 --decorate,尽管你很明显已经设置了 log.decorate),可以得到更有用的内容。不加 --right-only 可以获得最有用的输出。给定了 --right-only,你可以简化为 --boundary master..HEAD,但请继续阅读以了解我建议不使用 --right-only,而使用 --graph 的原因。

这实际上是有点复杂的:

  • 三个点的语法 master...HEAD 请求一个对称差异。也就是说,在三个点的左侧,我们得到了所有从 master 可达的但从 HEAD 不可达的提交,而在右侧,我们得到了所有从 HEAD 可达的但从 master 不可达的提交。

  • 如果指定了 --right-only 选项,则会消除左侧的提交。

  • --boundary 选项将那些被明确选择为不通过对称差异算法显示的提交添加回到图形遍历的提交集中。

考虑以下图形,绘制了父提交在左侧,子提交在右侧(而不是像 git log --graph 那样,将父提交置于上方,子提交置于下方):

          C--D--E   <-- master
         /
...--A--B
         \
          F--G--H   <-- feature (HEAD)

这里的大写字母代表提交哈希 ID。从master可以访问到回溯到C的提交E,而从HEAD(附加到名称feature)可以访问回溯到F的提交H。提交B是这两组提交的合并基础。
在这里,master...feature选择左侧的C-D-E提交和右侧的F-G-H提交。 (请注意,反转名称- feature...master - 选择相同的提交,但现在C-D-E将位于右侧。)因此,将--right-only添加到此集合中几乎可以得到您想要的内容:通过HEAD的提交,不包括可从master访问的提交。这是您从更简单的master..feature中获得的相同输出。
现在,如果我们添加--boundary,Git也将包括提交B。也就是说,git log --boundary master..featuregit log --boundary --right-only master...feature都将显示提交B-F-G-H(以另一种顺序)。
使用--decorate,当git log显示提交H时,它将添加HEAD -> feature修饰。但是提交B没有分支名称,因此不会被修饰。很难看出提交B属于两个分支。
如果没有--right-only并且使用--boundary--graph,Git将在主分支上显示提交C-D-E,在特性上显示提交F-G-H,并将包括边界提交B。生成的图形将清楚地显示B是共享合并基础提交。
当图形变得复杂时,--boundary会添加回太多提交。额外的提交仍然会以相当清晰的方式显示 - 无论如何,当有像git log --graph引入的那么多图形线时,这些事情就会变得清晰。您可以添加--simplify-by-decoration来帮助消除大量视觉杂乱:结果图可能是可读的,并且能让您识别共享提交。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接