设置和配置
获取和创建项目
基本快照
分支与合并
共享和更新项目
检查和比较
打补丁
调试
电子邮件
外部系统
服务器管理
指南
管理
底层命令
- 2.48.1 → 2.50.1 无更改
-
2.48.0
2025-01-10
- 2.43.1 → 2.47.3 无更改
-
2.43.0
2023-11-20
- 2.38.1 → 2.42.4 无更改
-
2.38.0
2022-10-02
- 2.31.1 → 2.37.7 无更改
-
2.31.0
2021-03-15
- 2.25.1 → 2.30.9 无更改
-
2.25.0
2020-01-13
- 2.20.1 → 2.24.4 无更改
-
2.20.0
2018-12-09
- 2.19.1 → 2.19.6 无更改
-
2.19.0
2018-09-10
概要
git range-diff [--color=[<when>]] [--no-color] [<diff-options>] [--no-dual-color] [--creation-factor=<factor>] [--left-only | --right-only] [--diff-merges=<format>] [--remerge-diff] ( <range1> <range2> | <rev1>…<rev2> | <base> <rev1> <rev2> ) [[--] <path>…]
描述
此命令显示补丁系列或更广义上说,两个提交范围(忽略合并提交)的两个版本之间的差异。
当存在 <path> 参数时,这些提交范围会相应地受到限制。
为此,它首先从两个提交范围中找到相互对应的提交对。如果两个提交的补丁(即作者信息、提交消息和提交差异)之间的差异相对于补丁的大小来说足够小,则称它们相互对应。有关详细信息,请参阅下面的“算法”部分。
最后,按照第二个提交范围的顺序显示匹配提交列表,不匹配的提交在其所有祖先都显示后插入。
指定提交范围有三种方式
-
<range1> <range2>:任一提交范围可以是 <base>
..<rev>、<rev>^!或 <rev>^-<n> 的形式。有关详细信息,请参阅 gitrevisions[7] 中的SPECIFYINGRANGES。 -
<rev1>
...<rev2>。这等同于 <rev2>..<rev1> <rev1>..<rev2>。 -
<base> <rev1> <rev2>:这等同于 <base>
..<rev1> <base>..<rev2>。
选项
- --no-dual-color
-
当提交差异不同时,
gitrange-diff会重新创建原始差异的着色,并添加带有红色/绿色背景的外部 -/+ 差异标记,以便更容易看出例如所添加的具体行发生了哪些变化。此外,仅在第一个提交范围中存在的提交差异行会显示为“模糊”(这可以使用
color.diff.<slot> 配置设置覆盖,其中 <slot> 是contextDimmed、oldDimmed和newDimmed之一),仅在第二个提交范围中存在的提交差异行会以粗体显示(这可以使用配置设置color.diff.<slot> 覆盖,其中 <slot> 是contextBold、oldBold或newBold之一)。这在
range-diff中被称为“双色着色”。使用--no-dual-color可恢复根据外部差异标记对所有行进行着色(并完全忽略内部差异的着色)。 - --creation-factor=<percent>
-
将创建/删除成本调整系数设置为 <percent>。默认为 60。如果
gitrange-diff错误地将一个大改动视为完全重写(删除一个提交并添加另一个),则尝试一个较大的值;反之则尝试一个较小的值。有关需要这样做的原因的解释,请参阅下面的“算法”部分。 - --left-only
-
抑制第一个指定范围(或使用 <rev1>
...<rev2> 格式时的“左侧范围”)中缺失的提交。 - --right-only
-
抑制第二个指定范围(或使用 <rev1>
...<rev2> 格式时的“右侧范围”)中缺失的提交。 - --diff-merges=<format>
-
不忽略合并提交,而是使用 git-log[1] 相应的
--diff-merges=<format> 选项为它们生成差异,并将其包含在比较中。注意:在常见情况下,
remerge模式将是最自然的用法,因为它只显示在 Git 合并机制会产生的结果之上所做的差异。换句话说,如果合并提交是无冲突gitmerge的结果,remerge模式将用空差异表示它。 - --remerge-diff
-
便捷选项,等同于
--diff-merges=remerge。 - --[no-]notes[=<ref>]
-
此标志被传递给生成补丁的
gitlog程序(参见 git-log[1])。 - <range1> <range2>
-
比较由两个范围指定的提交,其中 <range1> 被认为是 <range2> 的旧版本。
- <rev1>…<rev2>
-
等同于传递 <rev2>
..<rev1> 和 <rev1>..<rev2>。 - <base> <rev1> <rev2>
-
等同于传递 <base>
..<rev1> 和 <base>..<rev2>。注意 <base> 不必是分支的精确分支点。示例:在 rebase 一个分支my-topic后,gitrange-diffmy-topic@{u}my-topic@{1}my-topic将显示 rebase 引入的差异。
git range-diff 也接受常规的 diff 选项(参见 git-diff[1]),最值得注意的是 --color=[<when>] 和 --no-color 选项。这些选项用于生成“补丁之间的差异”,即比较相应新旧提交的作者、提交消息和差异。目前没有办法调整传递给 git log 的大部分 diff 选项来生成这些补丁。
输出稳定性
range-diff 命令的输出可能会发生变化。它旨在作为人类可读的门面输出,而不是可以跨 Git 版本获得文本稳定 range-diff 的内容(与 git-patch-id[1] 的 --stable 选项相反)。range-diff 也没有 git-apply[1] 的等效项,输出并非旨在机器可读。
当传递 diff 选项时尤其如此。目前,某些选项(如 --stat)可能会作为一种附带效果,产生在 range-diff 上下文中相当无用的输出。未来的 range-diff 版本可能会学习以特定于 range-diff 的方式解释此类选项(例如,对于 --stat 生成总结 diffstat 如何变化的人类可读输出)。
配置
此命令使用 diff.color.* 和 pager.range-diff 设置(后者默认为开启)。参见 git-config[1]。
示例
当 rebase 需要解决合并冲突时,之后直接使用以下命令比较 rebase 引入的更改
$ git range-diff @{u} @{1} @
git range-diff 的典型输出可能如下所示
-: ------- > 1: 0ddba11 Prepare for the inevitable!
1: c0debee = 2: cab005e Add a helpful message at the start
2: f00dbal ! 3: decafe1 Describe a bug
@@ -1,3 +1,3 @@
Author: A U Thor <author@example.com>
-TODO: Describe a bug
+Describe a bug
@@ -324,5 +324,6
This is expected.
-+What is unexpected is that it will also crash.
++Unexpectedly, it also crashes. This is a bug, and the jury is
++still out there how to fix it best. See ticket #314 for details.
Contact
3: bedead < -: ------- TO-UNDO
在此示例中,有 3 个旧提交和 3 个新提交,其中开发者删除了第 3 个,在前两个之前添加了一个新提交,并修改了第 2 个提交的提交消息及其差异。
当输出到终端时,它默认是颜色编码的,就像常规 git diff 的输出一样。此外,第一行(添加提交)是绿色,最后一行(删除提交)是红色,第二行(完美匹配)是黄色,就像 git show 输出的提交头一样,第三行将旧提交着色为红色,新提交着色为绿色,其余部分则像 git show 的提交头一样。
然而,对差异的差异进行简单的颜色编码实际上有点难以阅读,因为它会将整行着色为红色或绿色。例如,旧提交中添加“What is unexpected”的行是完全红色的,即使旧提交的意图是添加某些内容。
为了解决这个问题,range 默认使用 --dual-color 模式。在此模式下,差异的差异将保留原始差异颜色,并在行前加上背景为红色或绿色的 -/+ 标记,以使其更明显地表明它们描述了差异本身如何变化。
算法
一般思路是:我们计算两个提交范围中的提交之间的成本矩阵,然后解决最小成本分配问题。
成本矩阵的填充方式如下:对于每对提交,生成两个差异,然后生成“差异的差异”,带有 3 行上下文,然后将该差异中的行数用作成本。
为了避免误报(例如,当一个补丁被删除,并且在同一个补丁系列的两次迭代之间添加了一个不相关的补丁时),成本矩阵会进行扩展以允许这种情况发生,方法是为批量删除/添加添加固定成本条目。
示例:假设提交 1--2 是一个补丁系列的第一版,而 A--C 是第二版。假设 A 是 2 的 cherry-pick,而 C 是 1 的 cherry-pick 但稍有修改(例如,修正了一个错字)。将提交可视化为二分图
1 A
2 B
C
我们正在寻找对新系列相对于旧系列“最佳”的解释。我们可以将“解释”表示为图中的一条边
1 A
/
2 --------' B
C
这种解释是“免费的”,因为没有变化。类似地,C 可以用 1 来解释,但这会因为修改而产生一些成本 c > 0
1 ----. A
| /
2 ----+---' B
|
`----- C
c>0
在数学术语中,我们正在寻找某种最小成本二分匹配;1 以某种成本与 C 匹配,等等。底层图实际上是一个完全二分图;我们与每条边关联的成本是两个提交的补丁之间的差异大小。为了也解释新提交,我们在两侧引入了虚拟节点
1 ----. A
| /
2 ----+---' B
|
o `----- C
c>0
o o
o o
边 o--C 的成本是 C 的差异大小,并通过一个应小于 100% 的调整系数进行修改。边 o--o 的成本是免费的。调整系数是必要的,因为即使 1 和 C 之间没有任何共同点,它们可能仍然共享一些空行等,这可能使赋值 1--C、o--o 略低于 1--o、o--C,即使 1 和 C 没有共同点。有了调整系数,我们需要一个更大的共同部分才能将补丁视为对应。
计算此算法所需的总时间是计算 n+m 个提交差异以及 n*m 个补丁差异所需的时间,再加上计算 n 和 m 个差异之间最小成本分配所需的时间。Git 使用 Jonker-Volgenant 算法的实现来解决分配问题,该算法具有立方时间复杂度。在这种情况下找到的匹配将如下所示
1 ----. A
| /
2 ----+---' B
.--+-----'
o -' `----- C
c>0
o ---------- o
o ---------- o