【问题标题】:How to git diff diverged branch如何 git diff 分歧分支
【发布时间】:2021-05-18 07:52:55
【问题描述】:

我在我的分支上重写了一些提交历史,所以我的分支与远程分支不同:

Switched to branch 'dev'
Your branch and 'origin/dev' have diverged,
and have 3 and 3 different commits each, respectively.

在不同的版本(即我的本地分支和远程分支)之间有git diff 的简单方法吗?

我知道我可以使用 git diff commit1..commit2 来区分 2 个提交,但在这种情况下,我想区分我分支上的三个本地提交和三个远程提交。

【问题讨论】:

    标签: git diff git-branch git-diff


    【解决方案1】:

    使用git fetch获取后使用

    git diff <mainbranch_path> <remotebranch_path>
    

    例如git diff develop origin/develop

    【讨论】:

      【解决方案2】:

      TL;DR

      使用git range-diff——在本例中为git range-diff origin/dev...dev(注意此处的三个点)。

      长(ish)

      首先,让我们绘制设置。以下是两组提交,如您自己的存储库中所示:

                F'-G'-H'  <-- dev
               /
      ...--D--E
               \
                F--G--H   <-- origin/dev
      

      提交FGH——这里的字母代表真正的哈希ID,它们太大太丑了——是你工作之前的原始三个;它们新的和改进的替代品分别是 F-prime、G-prime 和 H-prime。

      通过仅比较这两个提交来比较最终结果非常容易:git diff dev origin/devgit diff origin/dev dev 将比较提交 HH'dev 选择 H' , origin/dev 选择 H)。但这不是你想要的,不是真的:

      • 您想先比较FF';那么
      • 您想比较GG';最后
      • 您想比较 HH'

      单个git diff 命令只能生成这三个命令中的最后一个。

      蛮力解决方案是自己运行三个git diffs,一次一个。要命名提交F',可以写dev~2;要命名 commit G',你可以写成 dev~1(或 dev~dev^——所有这些都有效;有关更多信息,请参阅 the gitrevisions documentation)。要将提交命名为F,请使用origin/dev~2,依此类推。

      不过,从 Git 2.19 开始,就有一个新命令可以为您执行此操作。如上面的 TL;DR 中所述,这是 git range-diff

      range-diff 命令需要知道要比较的两个范围。您可以明确地将它们提供给它:

      git range-diff origin/dev~3..origin/dev dev~3..dev
      

      我们在这里使用~3,而不是~2,因为用两点.. 表示法表示的范围在数学上是半开区间:它们包括最终提交,但不包括开始提交。 (在心理上,你可以认为这需要在结果中提交三个提交,因此 X~3..X。这是 (X~3 .. X] 的事实当然很重要,因为 [X~3 .. X ) 将忽略范围的错误结束,但无论哪种方式,半开间隔都会补偿通常的 fencepost error。)再次,请参阅 gitrevisions

      不过,在这种情况下更简单的是,我们可以使用 三个-点表示法,git range-diff 会稍微特别处理它。如gitrevisions 文档中所述,三点符号表示集合论方面的对称差分操作,因此:

      git range-diff origin/dev...dev
      

      暗示该命令应该检查可通过或者origin/dev 访问的提交——即,在后面提交H—— dev,即,提交@987654368 @ 背面;但应该检查可从两个名称访问的提交,即提交E 和更早的时间。所以这会准确选择所需的两组提交:F-G-HF'-G'-H'

      范围的乐趣

      那么,剩下的问题是:

      1. 这是如何工作的? 为什么我们不必在任何地方提及X~3,对于某些X

      2. 这些顺序是否正确?如果不是,您将获得一个范围差异,描述从您的新提交和改进提交(可能是由 rebase 产生)到旧的和糟糕的。

      让我们先解决问题 1,然后解决问题 2。我们实际上已经回答了问题 1,但只是求助于集合论,这对某些人来说可能并不熟悉。

      Symmetric difference 是根据集合定义的:它是并集减去交集。给定两个集合 AB,对称差 A⊖BAΔB 可以计算为A∖B (读作“A 排除 B”)和 B∖A 的并集(或等效地,作为从 中减去交集的结果 em> 工会,这是我自己通常的想法,并在此先声明)。

      在上面,我们写道:dev 可到达的所有提交的集合,不包括从dev~3 可到达的所有提交的集合。那是我们的dev~3..dev。这是从E 开始的每个提交并向后工作 H' 开始的每个提交并向后工作的非常精确的方法 .但毕竟我们不必那么精确。我们可以偷懒,说:H' 开始的每个提交并向后工作,剥离从H 开始的每个提交并向后工作。F-G-H 不在 那个集合,要求把它们从那个集合中剥离出来是无害的:A∖B 不需要 B 中的东西在 A 首先。

      因此,我们可以使用origin/dev..dev 来代替dev~3..dev,从E 向后删除提交。当然origin/dev 需要输入十个字符,而dev~3 只有五个字符,所以我们在这里并没有什么收获。

      问题是,出于同样的原因,我们可以写 dev..origin/dev 以从向后提交的 H 中排除 E 的 commits-backwards-from。这一次它确实节省了一些输入,而且——更好的是——如果我们有某种符号让我们只需输入 AB 在这里,我们只需键入每个名称一次。 这是我们的对称差分符号,因此我们可以只输入origin/dev...dev(三个点)或dev...origin/dev(仍然是三个点)。

      现在让我们解决问题 2,获得正确的顺序。我们现在咨询the git range-diff documentation,上面写着:

      &lt;rev1&gt;...&lt;rev2&gt;
      相当于通过&lt;rev2&gt;..&lt;rev1&gt;&lt;rev1&gt;..&lt;rev2&gt;

      现在,我最初建议:

      git range-diff origin/dev~3..origin/dev dev~3..dev
      

      也就是说,我们将 old 范围的提交放在第一位,new 范围的提交放在第二位。如果我们运行:

      git range-diff origin/dev...dev
      

      那么&lt;rev2&gt;就是dev,所以“等价于”部分就变成了:

      git range-diff dev..origin/dev origin/dev..dev
      

      这使用了第 1 项中的技巧来制作两个单独的范围表达式,并确保 second 范围表达式——它确定哪些提交是“新的”——以指定的 秒结束rev,即dev。所以origin/dev...dev 是正确的顺序。

      【讨论】:

        猜你喜欢
        • 2013-03-27
        • 1970-01-01
        • 1970-01-01
        • 2019-11-24
        • 2022-01-08
        • 2020-09-16
        • 2012-06-10
        • 1970-01-01
        • 2012-09-20
        相关资源
        最近更新 更多