Setup and Config
Getting and Creating Projects
Basic Snapshotting
Branching and Merging
Sharing and Updating Projects
Inspection and Comparison
Patching
Debugging
External Systems
Server Admin
Guides
- gitattributes
- Command-line interface conventions
- Everyday Git
- Frequently Asked Questions (FAQ)
- Glossary
- Hooks
- gitignore
- gitmodules
- Revisions
- Submodules
- Tutorial
- Workflows
- All guides...
Administration
Plumbing Commands
- 2.43.1 → 2.47.0 no changes
- 2.43.0 11/20/23
- 2.38.1 → 2.42.3 no changes
- 2.38.0 10/02/22
- 2.31.1 → 2.37.7 no changes
- 2.31.0 03/15/21
- 2.25.1 → 2.30.9 no changes
- 2.25.0 01/13/20
- 2.20.1 → 2.24.4 no changes
- 2.20.0 12/09/18
- 2.19.1 → 2.19.6 no changes
- 2.19.0 09/10/18
概述
git range-diff [--color=[<何时>]] [--no-color] [<差异选项>] [--no-dual-color] [--creation-factor=<系数>] [--left-only | --right-only] ( <范围 1> <范围 2> | <修订 1>…<修订 2> | <基础> <修订 1> <修订 2> ) [[--] <path>…]
描述
该命令显示补丁系列的两个版本之间的差异,或者更笼统地说,两个提交范围之间的差异(忽略合并提交)。
如果存在 <path>
参数,这些提交范围将受到相应的限制。
为此,它首先从两个提交范围中找到相互对应的提交对。当两个补丁之间的差值(即作者信息、提交信息和提交差值)相对于补丁的大小相当小时,这两个提交就被认为是对应的。详见下面的 ``算法``。
最后,匹配的提交列表会按照第二个提交范围的顺序显示,未匹配的提交会在其所有祖先提交显示之后插入。
指定提交范围有三种方法 :
-
<range1> <range2>
: 提交范围可以是<base>...<rev>
、<rev>^!
或<rev>^-<n>
。详见 gitrevisions[7] 中的指定范围
。 -
<rev1>...<rev2>
。这等同于<rev2>...<rev1> <rev1>...<rev2>
. -
<base> <rev1> <rev2>
: 等同于<base>..<rev1> <base>..<rev2>
.
选项
- --no-dual-color
-
当提交的差异不同时,`git range-diff`会重现原始差异的颜色,并添加外层的 -/+ 差异标记,背景 为红/绿色,以便于查看,例如,当具体添加了哪些行时。
此外,只出现在第一个提交范围内的提交差异行会显示为 "dimmed"(这可以使用
color.diff. <slot>
配置设置,其中<slot>
是`contextDimmed`、oldDimmed
和newDimmed
中的一个),而仅出现在第二个提交范围内的提交差异行以粗体显示(这可以通过配置设置color.diff.<slot>
来覆盖,其中<slot>
是contextBold
、oldBold
和newBold
中的一个)。这在
range-diff
中被称为 "双重着色"。使用--no-dual-color
可以还原为根据外部差异标记对所有线条着色(在着色时完全忽略内部差异)。 - --creation-factor=<百分比>
-
将创建/删除成本误差因子设置为
<百分比>
。 默认为 60。如果git range-diff
错误地认为一个大的改动是完全重写 (删除一个提交,增加另一个提交),可以使用较大的值,反之则使用较小的值。 请参阅下面的 ``算法`` 部分以了解为什么需要这个值。 - --left-only
-
忽略第一个指定范围(或使用
<rev1>...<rev2>
格式时的 "左侧范围")中丢失的提交。 - --right-only
-
忽略第二个指定范围(或使用
<rev1>...<rev2>
格式时的 "右侧范围")中丢失的提交。 - --[no-]notes[=<引用>]
-
这个标志将传递给生成补丁的
git log
程序(参见 git-log[1])。 - <范围1> <范围2>
-
比较两个范围指定的提交,其中
<range1>
被认为是<range2>
的旧版本。 - <修订 1>..<修订 2>
-
相当于传递
<rev2>...<rev1>
和<rev1>...<rev2>
。 - <基础> <修订 1> <修订 2>
-
等同于传递
<base>...<rev1>
和<base>...<rev2>
。 注意<base>
不需要是分支的确切分支点。例如: 在重定向分支my-topic
之后,git range-diff my-topic@{u} my-topic@{1} my-topic
将显示重定向带来的差异。
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]。
实例
当重置需要解决合并冲突时,直接比较重置后引入的更改,使用 :
$ 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: 描述一个错误 +描述一个错误 @@ -324,5 +324,6 这是意料之中的。 -+出乎意料的是,它也会崩溃。 ++出乎意料的是,它也会崩溃。这是一个bug,陪审团还在讨论如何最好地修复它。 ++如何最好地修复它,还没有定论。详见 #314 号记录。 Contact 3: bedead < -: ------- TO-UNDO
在这个例子中,有 3 个旧提交和 3 个新提交,开发人员删除了第 3 个提交,在前两个提交之前添加了一个新提交,并修改了第 2 个提交的提交信息及其差异。
当输出到终端时,默认是用颜色编码的,就像普通的 git diff
输出一样。此外,第一行(添加提交)是绿色的,最后一行(删除提交)是红色的,第二行(完全匹配)是黄色的,就像 git show
输出的提交头一样,第三行旧提交是红色的,新提交是绿色的,其余的就像 git show
的提交头一样。
不过,用颜色编码的原 diff 实际上有点难读,因为它会把整行都染成红色或绿色。例如,在旧提交中添加了 "What is unexpected" 的那行就完全是红色的,即使旧提交的意图是添加一些东西。
为了解决这个问题,range
默认使用 --dual-color
模式。在这种模式下,diffs 的 diff 将保留原始的 diff 颜色,并在行的前缀加上 -/+ 标记,其 背景 为红色或绿色,以便更明显地描述 diff 本身是如何改变的。
算法
总体思路是这样的:我们在两个提交范围内的提交之间生成一个成本矩阵,然后求解最小成本分配。
成本矩阵是这样填充的:对于每一对提交,生成两个差异,并生成 “差异的差异”,其中包含 3 行上下文,然后将差异中的行数作为成本。
为了避免假阳性(例如,当一个补丁被删除,而在同一补丁系列的两次迭代之间又添加了一个不相关的补丁),成本矩阵通过为整体删除/添加添加固定成本条目进行扩展,以考虑到这一点。
示例: 假设 1--2
是补丁系列的第一次迭代,A--C`是第二次迭代。假设 `A`是从 `2
中挑选出来的,而 C
是从 1
中挑选出来的,但做了一点修改(比如,一个固定的错别字)。将提交可视化为一个二元图:
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
GIT
属于 git[1] 文档