簡體中文 ▾ 主題 ▾ 最新版本 ▾ git-range-diff 上次更新於 2.48.0

名稱

git-range-diff - 比較兩個提交範圍(例如同一分支的兩個版本)

概要

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] 中的 SPECIFYING RANGES

  • <rev1>...<rev2>。這等同於 <rev2>..<rev1> <rev1>..<rev2>

  • <base> <rev1> <rev2>:這等同於 <base>..<rev1> <base>..<rev2>

選項

--no-dual-color

當提交差異不同時,git range-diff 會重新建立原始差異的著色,並新增帶有紅色/綠色背景的外部 -/+ 差異標記,以便更容易看出例如所新增的具體行發生了哪些變化。

此外,僅在第一個提交範圍中存在的提交差異行會顯示為“模糊”(這可以使用 color.diff.<slot> 配置設定覆蓋,其中 <slot>contextDimmedoldDimmednewDimmed 之一),僅在第二個提交範圍中存在的提交差異行會以粗體顯示(這可以使用配置設定 color.diff.<slot> 覆蓋,其中 <slot>contextBoldoldBoldnewBold 之一)。

這在 range-diff 中被稱為“雙色著色”。使用 --no-dual-color 可恢復根據外部差異標記對所有行進行著色(並完全忽略內部差異的著色)。

--creation-factor=<percent>

將建立/刪除成本調整係數設定為 <percent>。預設為 60。如果 git range-diff 錯誤地將一個大改動視為完全重寫(刪除一個提交併新增另一個),則嘗試一個較大的值;反之則嘗試一個較小的值。有關需要這樣做的原因的解釋,請參閱下面的“演算法”部分。

--left-only

抑制第一個指定範圍(或使用 <rev1>...<rev2> 格式時的“左側範圍”)中缺失的提交。

--right-only

抑制第二個指定範圍(或使用 <rev1>...<rev2> 格式時的“右側範圍”)中缺失的提交。

--diff-merges=<format>

不忽略合併提交,而是使用 git-log[1] 相應的 --diff-merges=<format> 選項為它們生成差異,並將其包含在比較中。

注意:在常見情況下,remerge 模式將是最自然的用法,因為它只顯示在 Git 合併機制會產生的結果之上所做的差異。換句話說,如果合併提交是無衝突 git merge 的結果,remerge 模式將用空差異表示它。

--remerge-diff

便捷選項,等同於 --diff-merges=remerge

--[no-]notes[=<ref>]

此標誌被傳遞給生成補丁的 git log 程式(參見 git-log[1])。

<range1> <range2>

比較由兩個範圍指定的提交,其中 <range1> 被認為是 <range2> 的舊版本。

<rev1>…​<rev2>

等同於傳遞 <rev2>..<rev1><rev1>..<rev2>

<base> <rev1> <rev2>

等同於傳遞 <base>..<rev1><base>..<rev2>。注意 <base> 不必是分支的精確分支點。示例:在 rebase 一個分支 my-topic 後,git range-diff my-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 是第二版。假設 A2 的 cherry-pick,而 C1 的 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 的成本是免費的。調整係數是必要的,因為即使 1C 之間沒有任何共同點,它們可能仍然共享一些空行等,這可能使賦值 1--Co--o 略低於 1--oo--C,即使 1C 沒有共同點。有了調整係數,我們需要一個更大的共同部分才能將補丁視為對應。

計算此演算法所需的總時間是計算 n+m 個提交差異以及 n*m 個補丁差異所需的時間,再加上計算 n 和 m 個差異之間最小成本分配所需的時間。Git 使用 Jonker-Volgenant 演算法的實現來解決分配問題,該演算法具有立方時間複雜度。在這種情況下找到的匹配將如下所示

    1 ----.      A
	  |    /
    2 ----+---'  B
       .--+-----'
    o -'  `----- C
	  c>0
    o ---------- o

    o ---------- o

另請參閱

GIT

Git[1] 套件的一部分

scroll-to-top