相对于共同祖先,在git中比较分支的更改

30

我经常遇到这样的情况,想要查看一个分支自从分离后引入的所有更改的差异。原始的方式

$ git diff ..branch

不太好用,因为它还会考虑 master 中的更改。我要找的基本上是一种更好的运行方式。

$ git diff $(git merge-base master branch)..branch

或者用图形表达:

---A---B---C---D---E  <== master
        \
         F---G---H    <== branch

我应该如何优雅地查找BH之间的差异?

编辑:正如我在下面的回答中所指出的,master...branch是解决我的问题的一种方式。但是,鉴于引用的man页面片段,我仍然不知道为什么会这样。

为什么diff master...branch只显示自合并基以来的差异,而man rev-parse说它也应该包括master的提交?

为什么diff master..branch显示master的当前状态与branch之间的差异,而man rev-parse说它应该忽略master独有的提交?


感谢您的回答。在评论中,@ELLIOTTCABLE指向了Git提交范围中双点“..”和三点“...”之间的区别是什么?的完整故事。正如那里的一条评论所指出的那样:“对于日志和差异,..和...的含义完全相反,这真是太荒谬了:log A..B是从合并基础到B的更改,这就是diff A...B所做的。” - nealmcb
4个回答

32

经过广泛查看git help rev-parse并进行实验后,我发现了这条信息:

   <rev1>..<rev2>
       Include commits that are reachable from <rev2> but exclude those
       that are reachable from <rev1>. When either <rev1> or <rev2> is
       omitted, it defaults to HEAD.

   <rev1>...<rev2>
       Include commits that are reachable from either <rev1> or <rev2>
       but exclude those that are reachable from both. When either <rev1>
       or <rev2> is omitted, it defaults to HEAD.

不知何故,我一直认为master..branch是我需要的,而忘记了master...branch(三个点的那个)。

但是实验表明,三个点的符号正是我要找的:

$ git diff master...branch

仅显示基于 master 分支起点的变更差异。


1
请注意:我不知道为什么。即使我已经第N次阅读了man页面,我仍然认为master..branch应该能够实现我的需求。 - Boldewyn
7
这绝对是答案;而且,由于这是第一个谷歌搜索结果(至少在我的搜索范围内!),你可能想将自己的答案标记为“已接受”。至于为什么会这样,基本上是为了向后兼容。rev-parse文档实际上不适用于此;它直接在git help diff中记录。 (请参见https://dev59.com/NXRB5IYBdhLWcg3w7rmV#463027) - ELLIOTTCABLE
1
谢谢你,@ELLIOTTCABLE!很高兴知道这个区别的来自。 - Boldewyn
不正确(我认为)。这适用于像log这样的命令,但diff是不同的。请参阅git help diff: git diff [] .. [--] [...] 这与之前的形式(没有“..”)同义,用于查看两个任意之间的更改。 git diff [] ... [--] [...] 此形式用于查看包含并且到第二个的分支上的更改,从两个的共同祖先开始。“git diff A...B”等同于“git diff $(git merge-base A B)B”。 - blais
我可能错了,但这不是ELLIOTTCABLE在上面两个评论中说的基本内容吗?换句话说,我不明白,就“是否解决了问题?”而言,我的回答如何可能是不正确的,尽管解释中存在不准确之处。 - Boldewyn

3

What I'm looking for is basically a nicer way to run

$ git diff $(git merge-base master branch)..branch
创建一个别名怎么样?
git config alias.diffbr '!f() { git diff $(git merge-base master $1)..$1; }; f'

然后,您只需执行git diffbr branch命令即可。

如果您希望该别名在您机器上的所有存储库中都可用,请将--global参数添加到git config命令中。了解更多


抱歉,我不知怎么错过了您的回答。是的,目前我正在考虑使用别名。您是否知道修订注释,可以更轻松地解决问题?(有时我会用“diff”做一些奇怪的东西,这时候别名可能会妨碍到我。) - Boldewyn
@Boldewyn,我不清楚你在修订注释方面需要什么。但看起来你已经找到了另一个更简单的解决方案。除非我听到其他消息,否则我会认为你已经准备好了。 - Chris
是的,确实如此(尽管我仍然被那个人手册困惑)。谢谢你的回答! - Boldewyn

3
如果您想将当前分支与其分支点进行比较,只需添加...。因此,命令如下:
git diff master...

这与git diff master...HEAD相同。我正在运行git版本2.17.1。在较旧的版本中可能会有不同的行为。


2

我知道这不是你在这里寻找的答案,但它可能会帮助其他人。使用像 gitk 这样的图形工具,您可以:

  • 打开 gitk
  • 点击 H,右键单击并选择“标记此提交”
  • 点击 B,右键单击并选择“将此差异 -> 标记的提交”

现在,您可以在右侧看到所有更新的文件,左侧可以查看每个文件的所有修改行。


谢谢回答!但是是的,我正在寻找一种CLI方式。(无论如何都已经点赞了。) - Boldewyn

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