【问题标题】:How to compare changesets in Git?如何比较 Git 中的变更集?
【发布时间】:2011-06-29 11:16:07
【问题描述】:

Git 可以很容易地比较提交之间的差异,例如使用 git 命令 diff 和 difftool。同样在 TortoiseGit 中,您只需选择两个提交来比较它们。

但是有没有办法比较变更集?换句话说:查看一组提交的差异与另一组提交的差异之间的差异。

这对于比较(一组)精心挑选或已重新设置的提交非常方便。

【问题讨论】:

  • 这有点刻薄,但一个答案是尝试永远不需要这样做。如果您确实有两个相似但不相同的变更集,那么它们应该希望从一个合理的共同祖先开始,这样您就可以区分它们。如果您选择/变基,希望您不会在此过程中实际修改变更集,因此没有什么可区分的;否则,如果您稍后修改移植版本,您应该能够区分原始移植版本和新版本。
  • 确实很讽刺。我不需要经常这样做。然而,分支经常被重新定位(交互式 + 非交互式)。所以,作为一个非常非常小的团队的集成商,我想知道重新定位的分支是否仍然包含相同的变更集,或者看看变更集中有什么变化。
  • 当然,另一件事是,如果您正在寻找是或否,您可以简单地生成两个变更集的组合差异并区分它们。可能已经足够了。
  • 我刚刚找到了stackoverflow.com/questions/2069177/diffing-diffs-with-diff,这导致了做一些接近你想要的事情的其他方式。

标签: git compare diff commit tortoisegit


【解决方案1】:

扩展jeff-bradberry的回答:

比较两个单一提交引入的变更集:

diff <(git show -U0 <sha-A>) <(git show -U0 <sha-B>)

比较两个提交序列引入的更改集:

diff <(git show -U0 <sha-A>...<sha-B>) <(git show -U0 <sha-C>...<sha-D>)

注意:-U0 是为了避免比较“上下文”行(即围绕您的编辑而改变的行,但不是由他们直接改变的行)。

【讨论】:

    【解决方案2】:

    以下是我比较两个变更集的方法:

    git diff [base_sha_a]..[final_sha_a] > ./a.diff
    git diff [base_sha_b]..[final_sha_b] > ./b.diff
    diff ./a.diff ./b.diff
    

    如果diff 命令的结果为空,则变更集相同。否则你会看到两个差异之间的差异。

    【讨论】:

      【解决方案3】:

      也许diff &lt;(git show rev1) &lt;(git show rev2) 会做你想做的事?

      【讨论】:

      • 比较两个单一提交的变更集非常好,但不适用于一组。上面的代码适用于 linux,但不适用于 msysgit 的 git bash。但是我可以编写一个脚本来比较 gui difftool 中的两个变更集。
      • 能够做这样的事情是我喜欢 cygwin git 而不是 msysgit 的原因。
      【解决方案4】:

      我认为,一般来说,为了得到你想要的,你必须进行某种合并/重新设置操作,以便创建一些可以比较的东西。

      当您真正考虑它时,变更集之间差异的想法是模糊的。我在这里假设您处于这样的情况:

      [other history]   [ "changeset 1" ]
      o - o - o - o - o ( - o - o - o - o)
       \
        (o - o - o - o - o)
        [ "changeset 2" ]
      

      那么比较这两者意味着什么?也许在您的情况下,其他历史记录中的差异与两个变更集的差异完全不相交,但总的来说,变更集 1 的内容可能取决于其他历史记录!这意味着 git 没有很好的通用方法来执行这样的操作;要正确地做到这一点,它基本上必须说“如果我重新定位,两个末端提交之间的区别是什么?”换句话说,我相信变更集之间差异的唯一合理定义是如果它们被重新定位为具有共同祖先,则最终提交之间的差异。当然,如果这是你想要的,那么你将不得不在工作树中执行一个操作——没有其他方法可以解决这样的差异。显而易见的事情是变基,并比较新的端点(分支):

      [other history]   [ "changeset 1" ]
      o - o - o - o - o ( - o - o - o - o)
                       \
                        (o - o - o - o - o)
                        [ "changeset 2'" ]
      

      不过,变基并不总是最有趣的,我可以想出一个小方法来解决这个问题。假设您适当地解决了冲突,rebase 的结果工作树应该与合并的结果相同:

      [other history]   [ "changeset 1" ]
      o - o - o - o - o ( - o - o - o - o)
       \               \
        \               ------
         \                    \
         (o - o - o - o - o) - X
          [ "changeset 2" ]
      

      因此您可以执行该临时合并,并将生成的提交与另一个变更集的最终提交进行比较。这将比做 rebase 快得多。 (无论哪种方式,您当然会使用一次性分支,而不是变更集 2 的真正分支。)

      【讨论】:

      • 最后一张图是个好主意。只要没有需要解决的冲突
      • 第二张图对于我的团队来说就像是在做与其他开发人员一样的工作。
      • @Paul:这里的部分想法是,如果有冲突需要解决,它们本质上就是在两个变更集之间构建差异的一部分。也许如果你这样想:你想要的是两个末端提交之间的差异,所有由“其他历史”产生的差异都被删除了。将这些差异与变更集 1 的差异分开就相当于解决冲突。
      【解决方案5】:
      git diff end_rev_1...end_rev_2
      

      取自:http://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html

      类似的符号 r1...r2 被称为 r1 和 r2 的对称差和 被定义为 r1 r2 --not $(git 合并基础 --all r1 r2)。这是一套 可访问的提交 r1 或 r2 之一,但不是来自 两者都有。

      来自 git diff 帮助:

      git diff [--options] <commit>...<commit> [--] [<path>...]
         This form is to view the changes on the branch containing and up to the second <commit>, starting at a
         common ancestor of both <commit>. "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B".
         You can omit any one of <commit>, which has the same effect as using HEAD instead.
      

      这对你有用吗?

      【讨论】:

      • 我认为这不是 OP 想要的。看看它相当于什么 - 它实际上与 A 上的更改没有任何关系;它只是将其用作查找差异起点的一种方式。
      • 这确实不是我需要的。这回答了如何比较两个提交(或修订)之间项目内容的差异。我想知道一个(或多个)提交如何更改内容(=changeset)并将其与一个(或多个)其他提交的更改集进行比较。
      猜你喜欢
      • 2011-01-15
      • 1970-01-01
      • 2011-05-02
      • 2012-10-08
      • 2020-10-18
      • 2013-07-25
      • 2016-07-11
      • 2013-01-11
      • 1970-01-01
      相关资源
      最近更新 更多