如何获得这两个git提交之间的interdiff?

时间:2013-07-22 16:30:02

标签: git

我正在尝试查看git中同一提交的两个修订版之间的区别。差异的差异,基本上。从我到目前为止所读到的,这被称为“interdiff”。我已经阅读了几个关于如何创建git补丁的interdiffs的教程,但是我无法让这些方法在我的特定情况下工作。

所以这是设置。我有两个不同的分支,每个分支略有不同:

* 29e734f - (origin/feature_branch, new_commits) New commit 3 (69 minutes ago) <Ajedi32>
* b22ebea - New commit 2 (89 minutes ago) <Ajedi32>
* 09d42c2 - New commit 1 (2 hours ago) <Ajedi32>
| * 467e08f - (old_commits) Old commit 3 (4 weeks ago) <Ajedi32>
| * f2bf1cb - Old commit 2 (4 weeks ago) <Ajedi32>
| * 34a2187 - Old commit 1 (4 weeks ago) <Ajedi32>
|/  
*   1b05a4a - (origin/base, base) Base commit (5 weeks ago) <Ajedi32>

在这个例子中,我想找到“旧提交3”和“新提交3”之间的interdiff。我尝试从这两个提交中创建一个补丁文件并通过interdiff实用程序运行它们,但我得到的只是:

1 out of 2 hunks FAILED -- saving rejects to file /tmp/interdiff-1.Kgwx8u.rej
interdiff: Error applying patch1 to reconstructed file

我不太确定这意味着什么,所以我现在有点困惑了。我从哪里开始?

注意:我在这里寻找git diff old_commits new_commits。我不希望输出中包含提交1和2的修订版。

5 个答案:

答案 0 :(得分:3)

Git 2.19引入了一个新命令git range-diff,它执行以下操作:

  

git-range-diff-比较两个提交范围(例如分支的两个版本)

git range-diff [--color=[<when>]] [--no-color] [<diff-options>] [--no-dual-color]
               [--creation-factor=<factor>]\
               ( <range1> <range2> | <rev1>...<rev2> | <base> <rev1> <rev2> )
     

说明

     

此命令显示补丁的两个版本之间的差异   系列,或更一般地说,是两个提交范围(忽略合并提交)。

     

为此,它首先从两个提交范围中查找成对的提交   彼此对应。据说有两个提交对应   当他们的补丁之间的差异(即作者信息,   与以下内容相比,commit消息和commit diff)相对较小   补丁的大小。有关详细信息,请参见下面的Algorithm

     

最后,匹配提交列表按以下顺序显示:   第二个提交范围,在之后插入不匹配的提交   他们所有的祖先都被显示了。

所以,就您而言:

git range-diff base old_commits new_commits

会自动将old_commits分支中的提交与new_commits分支中的提交进行匹配,并显示每次提交之间差异的摘要。

或者,如果您只想从每个分支的最后一次提交中进行更改,则可以运行:

git range-diff old_commits~..old_commits new_commits~..new_commits

有关范围差异的更多信息,请参见the official documentation

答案 1 :(得分:2)

也许是这样的:

git log -p -1 new_commits > patch.new
git log -p -1 old_commits > patch.old
diff patch.old patch.new

或简洁的单行(bash):

diff <(git log -p -1 old_commits) <(git log -p -1 new_commits)

答案 2 :(得分:1)

如果两次提交之间的差异很小,则比较删除的行和添加的行(即只有以+或 - 开头的行)是有效的。它消除了以@@开头的hunks边界引入的噪声或者不重要的提交消息体:

diff -u --ignore-matching-lines '^[^+-]' \
    <(git show 1d9e4ac) <(git show 7b8e5c9)

样本外出是:

--- /dev/fd/63  2015-02-13 13:27:08.612683558 +0100
+++ /dev/fd/62  2015-02-13 13:27:08.616683527 +0100
@@ -62,13 +57,24 @@
  }

 diff --git a/src/crush/CrushWrapper.h b/src/crush/CrushWrapper.h
-index 0113662..282cbeb 100644
+index 3b2e6e6..0a633a5 100644
 --- a/src/crush/CrushWrapper.h
 +++ b/src/crush/CrushWrapper.h
-@@ -874,6 +874,25 @@ public:
-     return false;
+@@ -863,6 +863,36 @@ public:
+     if (!crush) return -1;
+     return crush_find_rule(crush, ruleset, type, size);
    }
- 
++
++  bool ruleset_exists(int const ruleset) const {
++    for (size_t i = 0; i < crush->max_rules; ++i) {
++     if (crush->rules[i]->mask.ruleset == ruleset) {
++       return true;
++     }
++    }
++
++    return false;
++  }
++
 +  /**
 +   * Return the lowest numbered ruleset of type `type`
 +   *

答案 3 :(得分:0)

也许这会给你一些你想要的东西。但如果提交1-2-3非常依赖,它将失败。

$ git checkout 'old commit 2'
$ git cherry-pick -n 'new commit 3'
$ git diff 'old commit 3'

$ git checkout 'new commit 2'
$ git cherry-pick -n 'old commit 3'
$ git diff 'new commit 3'

答案 4 :(得分:0)

您的2个补丁上的GNU interdiff失败,因为它们没有直接的公共基数/父代。

尽管git range-diff会产生一个外部差异diff(通常很难阅读;对先前提交中已消耗的/合并的更改不知道/不一致;不适用补丁格式),但您可以获得很好的效果通过将一个提交的副本合并到另一个(最好是较新的)提交的父级上,将一个提交的副本合并为基准,从而实现可读的interdiff。有几种方法。

在您的示例中,比较方便的做法是将<New commit 1><Old commit 1>进行比较,因为它们已经具有直接共同的父母

diff NC1 OC1

进一步远离公共基础,根据您的实际问题,我们得到这样的示例:

# move to the parent of NC3 - entering detached HEAD state
git checkout NC3~1
# merge-rebase the single patch <Old-commit-3> onto here
git cherry-pick OC3
# show the diff or reverse diff (or diff in gitk GUI)
git diff -R NC3
# back to feature_branch
git checkout feature_branch

当然,这里可能会出现合并冲突-然后由于缺乏真正的直接共同母体,(有必要)暴露与“虚拟共同体”互不兼容的更改。

可以创建一个(临时)标记或分支来保存此基于重新定义的比较提交(或提交范围),例如与其他用户进行讨论和合作。否则,临时未引用的悬挂提交将很快被自动回收。