English ▾ 主題 ▾ 最新版本 ▾ git-diff-files 最後更新於 2.55.0

名稱

git-diff-files - 比較工作樹與索引中的檔案

概要

git diff-files [-q] [-0 | -1 | -2 | -3 | -c | --cc] [<common-diff-options>] [<path>…​]

描述

比較工作樹與索引中的檔案。當指定路徑時,僅比較這些命名的路徑。否則,將比較索引中的所有條目。輸出格式與 git diff-indexgit diff-tree 相同。

選項

-p
-u
--patch

產生修補檔(請參見 使用 -p 產生修補檔文字)。

-s
--no-patch

隱藏差異機制的所有輸出。對於像 git show 這樣預設顯示修補檔的指令,可以用來壓制其輸出,或者取消指令列中先前在別名中定義的 --patch--stat 等選項的效果。

-U<n>
--unified=<n>

產生具有 <n> 行上下文的差異。上下文行數預設為 diff.context,如果未設定該組態變數則預設為 3。(由於歷史因素,不帶 <n>-U 會被默認為 -p 的別名)。隱含 --patch

--output=<file>

輸出到指定檔案而非標準輸出 (stdout)。

--output-indicator-new=<char>
--output-indicator-old=<char>
--output-indicator-context=<char>

指定在產生的修補檔中,用於指示新行、舊行或上下文行的字元。通常分別為 +- 和 ' '。

--raw

以原始格式產生差異。這是預設值。

--patch-with-raw

-p --raw 的別名。

--indent-heuristic

啟用偏移差異區塊 (hunk) 邊界的啟發式演算法,使修補檔更易於閱讀。這是預設值。

--no-indent-heuristic

停用縮排啟發式演算法。

--minimal

花費額外時間以確保產生最小可能的差異。

--patience

使用 "patience diff" 演算法產生差異。

--histogram

使用 "histogram diff" 演算法產生差異。

--anchored=<text>

使用 "anchored diff" 演算法產生差異。

此選項可以指定多次。

如果一行同時存在於來源和目的地,且僅出現一次,並以 <text> 開頭,此演算法會嘗試防止它在輸出中顯示為刪除或新增。它在內部使用 "patience diff" 演算法。

--diff-algorithm=(patience|minimal|histogram|myers)

選擇差異演算法。變體如下:

default
myers

基本的貪婪差異演算法。目前這是預設值。

minimal

花費額外時間以確保產生最小可能的差異。

patience

在產生修補檔時使用 "patience diff" 演算法。

histogram

此演算法擴展了 patience 演算法以「支援低出現率的共同元素」。

例如,如果您將 diff.algorithm 變數配置為非預設值,但想使用預設值,則必須使用 --diff-algorithm=default 選項。

--stat[=<width>[,<name-width>[,<count>]]]

產生 diffstat。預設情況下,檔名部分將盡可能使用所需的空間,其餘部分用於圖表部分。最大寬度預設為終端寬度,如果未連接到終端,則為 80 個字元,並可由 <寬度> 覆蓋。檔名部分的寬度可以透過在逗號後提供另一個寬度 <名稱寬度> 或透過設定 diff.statNameWidth=<名稱寬度> 來限制。圖表部分的寬度可以透過使用 --stat-graph-width=<圖表寬度> 或透過設定 diff.statGraphWidth=<圖表寬度> 來限制。使用 --stat--stat-graph-width 會影響所有產生統計圖表的指令,而設定 diff.statNameWidthdiff.statGraphWidth 不會影響 git format-patch。透過提供第三個參數 <計數>,您可以將輸出限制為前 <計數> 行,如果還有更多行,則後面跟著 ...

這些參數也可以單獨使用 --stat-width=<width>--stat-name-width=<name-width>--stat-count=<count> 來設定。

--compact-summary

在 diffstat 中輸出擴展標頭資訊的簡要摘要,例如檔案建立或刪除("new" 或 "gone",如果是符號連結則可選擇 +l)和模式更改(分別使用 +x-x 表示新增或移除可執行位元)。資訊放在檔案名稱部分和圖形部分之間。隱含 --stat

--numstat

類似於 --stat,但以十進位表示法顯示新增和刪除的行數,並顯示不含縮寫的路徑名稱,使其對機器更友善。對於二進位檔案,輸出兩個 - 而非顯示 0 0

--shortstat

僅輸出 --stat 格式的最後一行,包含修改後的檔案總數,以及新增和刪除的行數。

-X [<param>,...]
--dirstat[=<param>,...]

輸出每個子目錄相對變更量的分佈。透過傳遞逗號分隔的參數清單,可以自訂 --dirstat 的行為。預設值由 diff.dirstat 配置變數控制(參見 git-config[1])。下列參數可用:

changes

透過計算從來源移除或新增到目的地的行數來計算 dirstat 數值。這會忽略檔案內純粹的程式碼移動。換句話說,重新排列檔案中的行不像其他變更那樣被大量計算。這是未提供參數時的預設行為。

lines

透過執行一般的基於行的差異分析來計算 dirstat 數值,並加總移除/新增的行數。(對於二進位檔案,則計算 64 位元組的區塊,因為二進位檔案沒有自然的「行」概念)。這比 changes 行為更耗費資源,但它會將檔案內重新排列的行視為與其他變更一樣重要。產生的輸出與您從其他 --*stat 選項獲得的結果一致。

files

透過計算更改的檔案數量來計算 dirstat 數值。每個更改的檔案在 dirstat 分析中的權重相等。這是計算上最便宜的 --dirstat 行為,因為它根本不需要查看檔案內容。

cumulative

同時計算子目錄中對父目錄的變更。請注意,使用 cumulative 時,報告的百分比總和可能會超過 100%。預設(非累進)行為可以使用 noncumulative 參數指定。

<limit>

整數參數指定截斷百分比(預設為 3%)。變更佔比低於此百分比的目錄不會顯示在輸出中。

範例:下列指令將計算更改的檔案,同時忽略變更佔比低於總量 10% 的目錄,並在父目錄中累加子目錄的計數:--dirstat=files,10,cumulative

--cumulative

--dirstat=cumulative 的別名。

--dirstat-by-file[=<param>,...]

--dirstat=files,<param>,... 的別名。

--summary

輸出擴展標頭資訊的簡要摘要,例如建立、重新命名和模式更改。

--patch-with-stat

-p --stat 的別名。

-z

當指定了 --raw--numstat--name-only--name-status 時,不要對路徑名稱進行轉義,並使用 NUL 作為輸出欄位終止符。

若不使用此選項,具有「不尋常」字元的路徑名稱將按照配置變數 core.quotePath 的說明進行引用(參見 git-config[1])。

--name-only

僅顯示後映像 (post-image) 樹中每個更改檔案的名稱。檔案名稱通常以 UTF-8 編碼。更多資訊請參見 git-log[1] 手冊頁中有關編碼的討論。

--name-status

僅顯示每個更改檔案的名稱和狀態。有關狀態字母的含義,請參閱 --diff-filter 選項的說明。與 --name-only 一樣,檔案名稱通常以 UTF-8 編碼。

--submodule[=<format>]

指定如何顯示子模組中的差異。當指定 --submodule=short 時,使用 short 格式。此格式僅顯示範圍開頭和結尾的提交名稱。當指定 --submodule--submodule=log 時,使用 log 格式。此格式列出範圍內的提交,如同 git-submodule[1]summary 所做的那樣。當指定 --submodule=diff 時,使用 diff 格式。此格式顯示提交範圍之間子模組內容變更的內聯差異。預設為 diff.submodule,如果未設定該配置選項,則為 short 格式。

--color[=<when>]

顯示有顏色的差異。--color(即不含 =<when>)與 --color=always 相同。<when> 可以是 alwaysneverauto 之一。

--no-color

關閉彩色差異。這與 --color=never 相同。

--color-moved[=<mode>]

移動的程式碼行會以不同的顏色顯示。如果不提供該選項,<mode> 預設為 no;如果提供不帶模式的選項,則預設為 zebra。模式必須是下列之一:

no

移動的行不突出顯示。

default

zebra 的別名。這在未來可能會改為更合理的模式。

plain

在一個位置新增且在另一個位置移除的任何行將以 color.diff.newMoved 著色。類似地,color.diff.oldMoved 將用於在差異中其他位置新增的移除行。此模式會識別任何移動的行,但在檢閱中對於確定程式碼區塊是否在沒有置換的情況下移動並非很有用。

blocks

貪婪地偵測至少 20 個英數字元的移動文字區塊。偵測到的區塊使用 color.diff.(old|new)Moved 顏色繪製。相鄰區塊無法區分。

zebra

如同 blocks 模式偵測移動文字區塊。區塊使用 color.diff.(old|new)Moved 顏色或 color.diff.(old|new)MovedAlternative 顏色繪製。兩種顏色之間的切換表示偵測到了新區塊。

dimmed-zebra

類似於 zebra,但會對移動程式碼中不感興趣的部分進行額外變暗處理。兩個相鄰區塊的邊界行被認為是有趣的,其餘部分是不感興趣的。dimmed_zebra 是已棄用的別名。

--no-color-moved

關閉移動偵測。這可用於覆蓋組態設定。這與 --color-moved=no 相同。

--color-moved-ws=<mode>,...

這配置了執行 --color-moved 的移動偵測時如何忽略空白。這些模式可以作為逗號分隔的清單提供:

no

執行移動偵測時不要忽略空白。

ignore-space-at-eol

忽略行尾 (EOL) 的空白變更。

ignore-space-change

忽略空白數量的變更。這會忽略行尾的空白,並將所有其他一個或多個空白字元的序列視為等效。

ignore-all-space

比較行時忽略空白。即使一行有空白而另一行沒有,這也會忽略差異。

allow-indentation-change

最初在移動偵測中忽略任何空白,然後僅當每行的空白變更相同時,才將移動的程式碼區塊分組為一個區塊。這與其他模式不相容。

--no-color-moved-ws

執行移動偵測時不要忽略空白。這可用於覆蓋組態設定。這與 --color-moved-ws=no 相同。

--word-diff[=<mode>]

預設情況下,單字由空白分隔;請參見下文的 --word-diff-regex<mode> 預設為 plain,且必須是下列之一:

color

僅使用顏色突出顯示更改的單字。隱含 --color

plain

將單字顯示為 [-removed-]{added}。不會嘗試對輸入中出現的分隔符進行轉義,因此輸出可能會有歧義。

porcelain

使用專門為腳本處理設計的特殊基於行的格式。新增/移除/未更改的內容以通常的統一差異格式列印,以行首的 +/-/` ` 字元開始並延伸到行尾。輸入中的換行符在獨立的一行上由波浪號 ~ 表示。

none

再次停用單字差異。

請注意,儘管第一種模式有名稱,但如果啟用了顏色,則在所有模式下都會使用顏色來突出顯示更改的部分。

--word-diff 選項的操作方式是採用不加該選項時所產生的逐行差異,並計算每個區塊內的逐字變更。這可能會產生比專用逐字差異工具更大的差異。如果 Git 將來採用了不同的實作,輸出可能會改變。請注意,這類似於 --diff-algorithm 選項,該選項也可能會改變輸出。

--word-diff-regex=<regex>

使用 <regex> 來決定什麼是一個單字,而不是將非空白序列視為單字。除非已經啟用,否則也隱含 --word-diff

<regex> 的每個非重疊匹配項都被視為一個單字。這些匹配項之間的任何內容都被視為空白,並且在尋找差異時會被忽略(!)。您可能希望在正規表示式中附加 |[^[:space:]],以確保它匹配所有非空白字元。包含換行符的匹配項會在換行符處靜默截斷(!)。

例如,--word-diff-regex=. 將每個字元視為一個單字,並相應地逐字元顯示差異。

正規表示式也可以透過差異驅動程式或配置選項設定,參見 gitattributes[5]git-config[1]。顯式指定它會覆蓋任何差異驅動程式或配置設定。差異驅動程式會覆蓋組態設定。

--color-words[=<regex>]

相當於 --word-diff=color 加上(如果指定了正規表示式)--word-diff-regex=<regex>

--no-renames

關閉重新命名偵測,即使配置檔案預設為開啟。

--rename-empty
--no-rename-empty

是否使用空白內容物件作為重新命名來源。

--check

如果變更引入了衝突標記或空白錯誤,則發出警告。什麼被視為空白錯誤由 core.whitespace 配置控制。預設情況下,尾隨空白(包括僅由空白組成的行)和在行初始縮排內緊隨製表符 (tab) 之後的空格字元被視為空白錯誤。如果發現問題,則以非零狀態碼退出。與 --exit-code 不相容。

--ws-error-highlight=<kind>

在差異的 contextoldnew 行中突出顯示空白錯誤。多個值由逗號分隔,none 重設先前的值,default 將清單重設為 new,而 allold,new,context 的簡寫。當未提供此選項,且配置變數 diff.wsErrorHighlight 未設定時,僅突出顯示 new 行中的空白錯誤。空白錯誤使用 color.diff.whitespace 著色。

--full-index

在產生修補檔格式輸出時,在 "index" 行顯示完整的前映像和後映像內容物件名稱,而非僅顯示前幾個字元。

--binary

除了 --full-index 之外,還產生一個可以使用 git-apply 套用的二進位差異。隱含 --patch

--abbrev[=<n>]

在 diff-raw 格式輸出和 diff-tree 標頭行中,不顯示完整的 40 位元組十六進位物件名稱,而是顯示唯一引用該物件的長度至少為 <n> 個十六進位位元的縮寫。在 diff-patch 輸出格式中,--full-index 優先權較高,即如果指定了 --full-index,則無論是否指定 --abbrev,都會顯示完整的內容物件名稱。非預設的位元數可以使用 --abbrev=<n> 指定。

-B[<n>][/<m>]
--break-rewrites[=[<n>][/<m>]]

將完全重寫的變更拆分為刪除和建立對。這有兩個目的:

它影響變更的方式,將檔案的完全重寫不視為一系列刪除和插入混合在一起(其中只有極少數行恰好在文字上匹配作為上下文),而是視為單次刪除所有舊內容,後接單次插入所有新內容。數字 <m> 控制 -B 選項的這一方面(預設為 60%)。-B/70% 指定結果中應保留少於 30% 的原始內容,Git 才會將其視為完全重寫(否則產生的修補檔將是一系列混合了上下文行的刪除和插入)。

當與 -M 一起使用時,完全重寫的檔案也被視為重新命名的來源(通常 -M 僅將消失的檔案視為重新命名的來源),數字 <n> 控制 -B 選項的這一方面(預設為 50%)。-B20% 指定與檔案大小的 20% 或更多相比具有新增和刪除的變更有資格被選為可能的重新命名到另一個檔案的來源。

-M[<n>]
--find-renames[=<n>]

偵測重新命名。如果指定了 <n>,它是相似性指數的閾值(即與檔案大小相比的新增/刪除量)。例如,-M90% 表示如果檔案變更內容少於 10%,則 Git 應將刪除/新增對視為重新命名。不帶 % 符號時,該數字應讀取為分數,前面帶有小數點。即 -M5 變為 0.5,因此與 -M50% 相同。同樣地,-M05-M5% 相同。若要將偵測限制為完全匹配的重新命名,請使用 -M100%。預設相似性指數為 50%。

-C[<n>]
--find-copies[=<n>]

偵測複製以及重新命名。另請參見 --find-copies-harder。如果指定了 <n>,其含義與 -M<n> 相同。

--find-copies-harder

出於效能原因,預設情況下,僅當複製的原始檔案在同一個變更集中被修改時,-C 選項才會尋找複製。此旗標使指令檢查未修改的檔案作為複製來源的候選者。對於大型專案來說,這是一項非常耗資源的操作,請謹慎使用。提供多個 -C 選項具有相同的效果。

-D
--irreversible-delete

省略刪除的前映像,即僅列印標頭,而不列印前映像與 /dev/null 之間的差異。產生的修補檔不打算使用 patchgit apply 套用;這僅適用於只想專注於檢閱變更後文字的人員。此外,輸出顯然缺乏足夠的資訊來反向套用此類修補檔,即使是手動套用也是如此,這就是該選項名稱的由來。

-B 一起使用時,也會省略刪除/建立對中刪除部分的前映像。

-l<num>

-M-C 選項涉及一些初步步驟,可以廉價地偵測重新命名/複製的子集,然後是一個詳盡的後備部分,將所有剩餘的未配對目的地與所有相關來源進行比較。(對於重新命名,僅剩餘的未配對來源是相關的;對於複製,所有原始來源都是相關的。)對於 N 個來源和目的地,此詳盡檢查的複雜度為 O(N^2)。如果涉及的來源/目的地檔案數量超過指定數量,此選項可防止執行重新命名/複製偵測的詳盡部分。預設為 diff.renameLimit。請注意,值 0 被視為無限制。

--diff-filter=[(A|C|D|M|R|T|U|X|B)...[*]]

僅選擇已新增 (A)、已複製 (C)、已刪除 (D)、已修改 (M)、已重新命名 (R)、類型(即一般檔案、符號連結、子模組等)已變更 (T)、未合併 (U)、未知 (X) 或配對已斷開 (B) 的檔案。可以使用過濾字元的任何組合(包括無)。當組合中加入 * (全選或不選) 時,如果比較中有任何檔案符合其他標準,則選擇所有路徑;如果沒有檔案符合其他標準,則不選擇任何內容。

此外,這些大寫字母可以改為小寫以排除。例如,--diff-filter=ad 排除新增和刪除的路徑。

請注意,並非所有差異都能具備所有類型。例如,如果停用了對這些類型的偵測,則無法出現複製和重新命名的項目。

-S<string>

尋找更改檔案中指定 <string> 出現次數(即新增/刪除)的差異。供腳本編寫者使用。

當您正在尋找特定的程式碼區塊(如結構體)並想知道該區塊自最初產生以來的歷史記錄時,這非常有用:反覆使用此功能將前映像中有趣的區塊饋送回 -S,並一直繼續下去,直到獲得該區塊的最早版本。

也會搜尋二進位檔案。

-G<regex>

尋找修補檔文字中包含符合 <regex> 的新增/移除行的差異。

為了說明 -S<regex> --pickaxe-regex-G<regex> 之間的區別,請考慮同一個檔案中具有以下差異的提交:

+    return frotz(nitfol, two->ptr, 1, 0);
...
-    hit = frotz(nitfol, mf2.ptr, 1, 0);

雖然 git log -G"frotz\(nitfol" 會顯示此提交,但 git log -S"frotz\(nitfol" --pickaxe-regex 則不會(因為該字串的出現次數沒有改變)。

除非提供 --text,否則沒有 textconv 過濾器的二進位檔案修補檔將被忽略。

更多資訊請參閱 gitdiffcore[7] 中的 pickaxe 條目。

--find-object=<object-id>

尋找更改指定物件出現次數的差異。類似於 -S,只是參數不同,它不是搜尋特定字串,而是搜尋特定的物件識別碼 (ID)。

該物件可以是內容物件 (blob) 或子模組提交。它在 git-log 中隱含 -t 選項以同時尋找樹狀物件。

--pickaxe-all

-S-G 找到變更時,顯示該變更集中的所有變更,而不僅僅是包含 <string> 變更的檔案。

--pickaxe-regex

將提供給 -S<string> 視為擴展的 POSIX 正規表示式進行匹配。

-O<orderfile>

控制檔案在輸出中顯示的順序。這會覆蓋 diff.orderFile 配置變數(參見 git-config[1])。要取消 diff.orderFile,請使用 -O/dev/null

輸出順序由 <orderfile> 中的通配符模式 (glob pattern) 順序決定。所有路徑名稱符合第一個模式的檔案先輸出,所有路徑名稱符合第二個模式(但不符合第一個)的檔案接著輸出,依此類推。所有路徑名稱不符合任何模式的檔案最後輸出,就像檔案末尾有一個隱含的全部匹配模式一樣。如果多個路徑名稱具有相同的層級(它們符合相同的模式,但不符合先前的任何模式),則它們彼此之間的相對輸出順序為正常順序。

<orderfile> 的解析方式如下:

  • 空行將被忽略,因此它們可用作分隔符號以提高可讀性。

  • 以井字號 ("#") 開頭的行將被忽略,因此可用於注釋。如果模式以井字號開頭,請在模式開頭添加反斜線 ("\")。

  • 其他每一行都包含一個模式。

模式的語法和語意與不帶 FNM_PATHNAME 旗標的 fnmatch(3) 所使用的模式相同,但如果移除任意數量的最後路徑組件後路徑名稱符合模式,則路徑名稱也符合模式。例如,模式 "foo*bar" 符合 "fooasdfbar" 和 "foo/bar/baz/asdf",但不符合 "foobarx"。

--skip-to=<file>
--rotate-to=<file>

從輸出中丟棄指定 <file> 之前的檔案(即 跳至 (skip to)),或將它們移動到輸出的末尾(即 旋轉至 (rotate to))。這些選項主要是為了 git difftool 指令發明的,在其他情況下可能不太有用。

-R

交換兩個輸入;也就是說,顯示從索引或磁碟檔案到樹內容的差異。

--relative[=<path>]
--no-relative

當從專案的子目錄執行時,可以使用此選項告訴它排除該目錄之外的更改,並顯示相對於該目錄的路徑名稱。當您不在子目錄中(例如在赤裸儲存庫中)時,可以透過提供 <path> 作為參數來命名使輸出相對於哪個子目錄。--no-relative 可用於抵消 diff.relative 配置選項和先前的 --relative

-a
--text

將所有檔案視為文字。

--ignore-cr-at-eol

進行比較時忽略行尾的回車符 (carriage-return)。

--ignore-space-at-eol

忽略行尾 (EOL) 的空白變更。

-b
--ignore-space-change

忽略空白數量的變更。這會忽略行尾的空白,並將所有其他一個或多個空白字元的序列視為等效。

-w
--ignore-all-space

比較行時忽略空白。即使一行有空白而另一行沒有,這也會忽略差異。

--ignore-blank-lines

忽略行全是空白的變更。

-I<regex>
--ignore-matching-lines=<regex>

忽略所有行均符合 <regex> 的變更。此選項可以指定多次。

--inter-hunk-context=<number>

顯示差異修改塊之間的內容,最多到指定的 <n> 行,從而融合彼此接近的修改塊。預設為 diff.interHunkContext,如果未設定配置選項則為 0。

-W
--function-context

顯示整個函式作為每次變更的上下文行。函式名稱的確定方式與 git diff 算出修補檔區塊標頭的方式相同(參見 gitattributes[5] 中的「定義自訂區塊標頭」)。

--exit-code

讓程式以類似於 diff(1) 的代碼退出。也就是說,如果有差異則以 1 退出,0 表示無差異。

--quiet

停用程式的所有輸出。隱含 --exit-code。停用執行其退出代碼不可信的外部差異輔助程式,即其對應的配置選項 diff.trustExitCodediff.<driver>.trustExitCode 或環境變數 GIT_EXTERNAL_DIFF_TRUST_EXIT_CODE 為 false。

--ext-diff

允許執行外部差異輔助程式。如果您使用 gitattributes[5] 設定了外部差異驅動程式,則需要將此選項與 git-log[1] 及其相關指令一起使用。

--no-ext-diff

禁止外部差異驅動程式。

--textconv
--no-textconv

比較二進位檔案時允許(或禁止)執行外部文字轉換過濾器。詳細資訊請參見 gitattributes[5]。由於文字轉換過濾器通常是單向轉換,因此產生的差異適合人類閱讀,但無法套用。出於這個原因,文字轉換過濾器預設僅對 git-diff[1]git-log[1] 啟用,而不對 git-format-patch[1] 或差異底層 (plumbing) 指令啟用。

--ignore-submodules[=(none|untracked|dirty|all)]

在差異產生中忽略子模組的變更。all 是預設值。使用 none 會將包含未追蹤或已修改檔案的子模組視為已修改,或者當其 HEAD 與超級專案中記錄的提交不同時,也可用於覆蓋 git-config[1]gitmodules[5]ignore 選項的任何設定。當使用 untracked 時,如果子模組僅包含未追蹤的內容,則不會將其視為髒污(但仍會掃描其是否包含已修改的內容)。使用 dirty 會忽略對子模組工作樹的所有變更,僅顯示對儲存在超級專案中的提交的變更(這是 1.7.0 之前的行為)。使用 all 會隱藏對子模組的所有變更。

--src-prefix=<prefix>

顯示指定的來源 <prefix> 而非 "a/"。

--dst-prefix=<prefix>

顯示指定的目的地 <prefix> 而非 "b/"。

--no-prefix

不顯示任何來源或目的地前綴。

--default-prefix

使用預設的來源和目的地前綴("a/" 和 "b/")。這會覆蓋配置變數,例如 diff.noprefixdiff.srcPrefixdiff.dstPrefixdiff.mnemonicPrefix(參見 git-config[1])。

--line-prefix=<prefix>

在輸出的每一行前面附加一個額外的 <prefix>

--ita-invisible-in-index

預設情況下,由 git add -N 新增的項目在 git diff 中顯示為現有的空檔案,在 git diff --cached 中顯示為新檔案。此選項使該項目在 git diff 中顯示為新檔案,在 git diff --cached 中顯示為不存在。可以使用 --ita-visible-in-index 還原此選項。這兩個選項都是實驗性的,將來可能會被移除。

--max-depth=<depth>

對於指令列上提供的每個路徑規格 (pathspec),最多下降 <depth> 層目錄。值為 -1 表示無限制。不能與路徑規格中的通配符結合使用。給定一個包含 foo/bar/baz 的樹,下列清單顯示了每組選項產生的匹配項:

  • --max-depth=0 -- foo: foo

  • --max-depth=1 -- foo: foo/bar

  • --max-depth=1 -- foo/bar: foo/bar/baz

  • --max-depth=1 -- foo foo/bar: foo/bar/baz

  • --max-depth=2 -- foo: foo/bar/baz

如果未提供路徑規格,則測量深度的基準如同指定了所有頂級條目一樣。請注意,這與從根目錄測量不同,因為 --max-depth=0 仍會返回 foo。這允許您在請求頂級條目子集的同時限制深度。

請注意,此選項僅支援樹狀物件之間的差異,不支援針對索引或工作區的差異。

有關這些常用選項的更詳細說明,另請參閱 gitdiffcore[7]

-1 --base
-2 --ours
-3 --theirs
-0

分別與「基礎 (base)」版本、「我們的分支 (our branch)」或「他們的分支 (their branch)」進行比較。使用這些選項時,不會顯示合併條目的差異。

預設是與我們的分支 (-2) 以及乾淨解析的路徑進行比較。可以使用 -0 選項來省略未合併條目的差異輸出,僅顯示「未合併 (Unmerged)」。

-c
--cc

這會比較暫存區 2(我們的分支)、暫存區 3(他們的分支)以及工作樹檔案,並輸出合併後的差異,類似於 diff-tree 使用這些旗標顯示合併提交的方式。

-q

即使對於不存在的檔案也保持沉默

原始輸出格式

git-diff-indexgit-diff-treegit-diff-filesgit diff --raw 的原始輸出格式非常相似。

這些指令都比較兩組內容;具體比較什麼有所不同:

git-diff-index <tree-ish>

比較 <樹狀物件> 和檔案系統上的檔案。

git-diff-index --cached <tree-ish>

比較 <樹狀物件> 和索引。

git-diff-tree [-r] <tree-ish-1> <tree-ish-2> [<pattern>...]

比較兩個參數命名的樹狀物件。

git-diff-files [<pattern>...]

比較索引與檔案系統上的檔案。

所有指令都會為每個變更的檔案列印一行輸出,除了 git diff-files 在遇到未合併檔案的情況下,它會同時列印「未合併」和「原地編輯」行。

輸出的每一行格式如下

in-place edit  :100644 100644 bcd1234 0123456 M file0
copy-edit      :100644 100644 abcd123 1234567 C68 file1 file2
rename-edit    :100644 100644 abcd123 1234567 R86 file1 file3
create         :000000 100644 0000000 1234567 A file4
delete         :100644 000000 1234567 0000000 D file5
unmerged       :000000 000000 0000000 0000000 U file6

也就是說,從左到右為

  1. 一個冒號。

  2. 「來源」模式;如果是建立則為 000000,或者如果「來源」來自索引且未合併。

  3. 一個空格。

  4. 「目標」模式;如果是刪除則為 000000,或者如果「目標」來自索引且未合併。

  5. 一個空格。

  6. 「來源」的 sha1;如果是建立則為 0{40},或者如果「來源」來自索引且未合併。

  7. 一個空格。

  8. 「目標」的 sha1;如果是刪除則為 0{40},如果「目標」來自索引且未合併,或者如果「目標」來自工作樹且與索引不同步。

  9. 一個空格。

  10. 狀態,後接選用的「分數」數字。

  11. 一個 tab 字元,或者當使用 -z 選項時為一個 NUL。

  12. 「來源」的路徑

  13. 一個 tab 字元,或者當使用 -z 選項時為一個 NUL;僅在狀態為 C 或 R 時存在。

  14. 「目標」的路徑;僅在狀態為 C 或 R 時存在。

  15. 一個 LF 或一個 NUL(當使用 -z 選項時),用來結束該筆紀錄。

可能的狀態字母有

  • A:新增檔案

  • C:將檔案複製到新檔案

  • D:刪除檔案

  • M:修改檔案內容或模式

  • R:重新命名檔案

  • T:檔案類型變更(一般檔案、符號連結或子模組)

  • U:檔案未合併(您必須先完成合併才能提交)

  • X:「未知」的變更類型(這極有可能是 bug,請回報)

狀態字母 CR 後面總是接一個分數(表示移動或複製的來源與目標之間的相似百分比)。對於檔案重寫,狀態字母 M 後面可能接一個分數(表示不相似百分比)。

如果檔案系統上的檔案與索引不同步,則「目標」的 sha1 會顯示為全 0。

範例

:100644 100644 5be4a4a 0000000 M file.c

如果不使用 -z 選項,含有「不尋常」字元的路徑名會按照配置變數 core.quotePath 的說明加上引號(參見 git-config[1])。使用 -z 時,檔名會按原樣輸出,且該行會以 NUL 位元組結尾。

合併的差異格式

git-diff-treegit-diff-filesgit-diff --raw 可以接受 -c--cc 選項,為合併提交產生差異輸出。其輸出與上述格式的不同之處如下

  1. 每個父節點都有一個冒號

  2. 有多個「來源」模式和「來源」sha1

  3. 狀態是每個父節點狀態字元的串接

  4. 沒有選用的「分數」數字

  5. 以 tab 分隔的檔案路徑名

對於 -c--cc,即使檔案在歷史的任何一方被重新命名,也只會顯示目標路徑或最終路徑。使用 --combined-all-paths 時,會顯示每個父節點中的路徑名稱,後接合併提交中的路徑名稱。

不含 --combined-all-paths-c--cc 範例

::100644 100644 100644 fabadb8 cc95eb0 4866510 MM	desc.c
::100755 100755 100755 52b7a2d 6d1ac04 d2ac7d7 RM	bar.sh
::100644 100644 100644 e07d6c5 9042e82 ee91881 RR	phooey.c

-c--cc 中加入 --combined-all-paths 的範例

::100644 100644 100644 fabadb8 cc95eb0 4866510 MM	desc.c	desc.c	desc.c
::100755 100755 100755 52b7a2d 6d1ac04 d2ac7d7 RM	foo.sh	bar.sh	bar.sh
::100644 100644 100644 e07d6c5 9042e82 ee91881 RR	fooey.c	fuey.c	phooey.c

注意,組合差異 (combined diff) 僅列出與所有父節點相比皆有修改的檔案。

使用 -p 產生修補檔文字

執行帶有 -p 選項的 git-diff[1]git-log[1]git-show[1]git-diff-index[1]git-diff-tree[1]git-diff-files[1] 會產生修補檔文字。您可以透過 GIT_EXTERNAL_DIFFGIT_DIFF_OPTS 環境變數(參見 git[1])以及 diff 屬性(參見 gitattributes[5])來自訂修補檔文字的產生方式。

-p 選項產生的內容與傳統的 diff 格式略有不同

  1. 它前面有一個 "git diff" 標頭,看起來像這樣

    diff --git a/file1 b/file2

    除非涉及重新命名/複製,否則 a/b/ 檔名是相同的。特別是,即使是建立或刪除,也不會使用 /dev/null 來代替 a/b/ 檔名。

    當涉及重新命名/複製時,file1file2 分別顯示重新命名/複製的源檔案名稱和重新命名/複製產生的檔案名稱。

  2. 後面跟著一行或多行擴充標頭

    old mode <mode>
    new mode <mode>
    deleted file mode <mode>
    new file mode <mode>
    copy from <path>
    copy to <path>
    rename from <path>
    rename to <path>
    similarity index <number>
    dissimilarity index <number>
    index <hash>..<hash> <mode>

    檔案模式 <mode> 以 6 位八進位數字印出,包含檔案類型和檔案權限位元。

    擴充標頭中的路徑名不包含 a/b/ 前綴。

    相似度指數 (similarity index) 是未變更列數的百分比,而不相似度指數 (dissimilarity index) 是已變更列數的百分比。它是一個無條件捨去的整數,後接百分比符號。100% 的相似度指數值保留給兩個完全相同的檔案,而 100% 的不相似度則表示舊檔案中沒有任何一行進入新檔案。

    index 行包含變更前後的 blob 物件名稱。如果檔案模式沒有變更,則包含 <mode>;否則會用單獨的行指示舊模式和新模式。

  3. 含有「不尋常」字元的路徑名會按照配置變數 core.quotePath 的說明加上引號(參見 git-config[1])。

  4. 輸出中所有的 file1 檔案都是指提交前的檔案,而所有的 file2 檔案則是指提交後的檔案。按順序將每個變更套用到每個檔案是不正確的。例如,這個修補檔將會交換 a 和 b

    diff --git a/a b/b
    rename from a
    rename to b
    diff --git a/b b/a
    rename from b
    rename to a
  5. 區塊 (Hunk) 標頭會提到該區塊套用的函式名稱。有關如何針對特定語言調整此項目的詳細資訊,請參見 gitattributes[5] 中的「自訂區塊標頭 (Defining a custom hunk-header)」。

組合差異格式

任何產生差異的命令都可以接受 -c--cc 選項,在顯示合併時產生 組合差異 (combined diff)。這是使用 git-diff[1]git-show[1] 顯示合併時的預設格式。另外請注意,您可以給這些命令任何適合的 --diff-merges 選項,以強制以特定格式產生差異。

「組合差異」格式看起來像這樣

diff --combined describe.c
index fabadb8,cc95eb0..4866510
--- a/describe.c
+++ b/describe.c
@@@ -98,20 -98,12 +98,20 @@@
	return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
  }

- static void describe(char *arg)
 -static void describe(struct commit *cmit, int last_one)
++static void describe(char *arg, int last_one)
  {
 +	unsigned char sha1[20];
 +	struct commit *cmit;
	struct commit_list *list;
	static int initialized = 0;
	struct commit_name *n;

 +	if (get_sha1(arg, sha1) < 0)
 +		usage(describe_usage);
 +	cmit = lookup_commit_reference(sha1);
 +	if (!cmit)
 +		usage(describe_usage);
 +
	if (!initialized) {
		initialized = 1;
		for_each_ref(get_name);
  1. 它前面有一個 "git diff" 標頭,看起來像這樣(當使用 -c 選項時)

    diff --combined file

    或者像這樣(當使用 --cc 選項時)

    diff --cc file
  2. 後面跟著一行或多行擴充標頭(本例顯示與兩個父節點的合併)

    index <hash>,<hash>..<hash>
    mode <mode>,<mode>..<mode>
    new file mode <mode>
    deleted file mode <mode>,<mode>

    mode <mode>,<mode>..<mode> 行僅在至少有一個 <mode> 與其他模式不同時才會出現。帶有偵測到的內容移動(重新命名和複製偵測)資訊的擴充標頭旨在用於兩個 <tree-ish> 的差異,不被組合差異格式所使用。

  3. 後面跟著兩行的 from-file/to-file 標頭

    --- a/file
    +++ b/file

    與傳統 unified diff 格式的兩行標頭類似,/dev/null 用於表示建立或刪除的檔案。

    但是,如果提供了 --combined-all-paths 選項,您將得到 N+1 行的 from-file/to-file 標頭,而不是兩行,其中 N 是合併提交中父節點的數量

    --- a/file
    --- a/file
    --- a/file
    +++ b/file

    如果啟用了重新命名或複製偵測,這種擴充格式會非常有用,它能讓您看到檔案在不同父節點中的原始名稱。

  4. 區塊標頭格式經過修改,以防止人們意外地將其餵給 patch -p1。組合差異格式是為審查合併提交的變更而建立的,並非為了套用。此變更與擴充 index 標頭中的變更類似

    @@@ <from-file-range> <from-file-range> <to-file-range> @@@

    組合差異格式的區塊標頭中有 (父節點數量 + 1) 個 @ 字元。

傳統的 unified diff 格式顯示兩個檔案 A 和 B,並使用單一列,其前綴為 -(減號 — 出現在 A 中但在 B 中移除)、+(加號 — A 中缺失但在 B 中新增)或 " "(空格 — 未變更);與此不同,此格式將兩個或多個檔案 file1, file2,…​ 與一個檔案 X 進行比較,並顯示 X 與每個 fileN 的不同之處。每個 fileN 都有一列會加在輸出行的前面,以說明 X 的該行與其有何不同。

第 N 列中的 - 字元表示該行出現在 fileN 中,但不在結果中。第 N 列中的 + 字元表示該行出現在結果中,而 fileN 沒有該行(換句話說,從該父節點的角度來看,該行是被新增的)。

在上述範例輸出中,函式簽名從兩個檔案中都被變更了(因此從 file1 和 file2 中分別移除了一個 -,加上 ++ 表示新增的一行在 file1 或 file2 中都沒有出現)。此外,還有其他八行與 file1 相同,但未出現在 file2 中(因此前綴為 +)。

當由 git diff-tree -c 顯示時,它會將合併提交的父節點與合併結果進行比較(即 file1..fileN 是父節點)。當由 git diff-files -c 顯示時,它會將兩個未解決的合併父節點與工作區檔案進行比較(即 file1 是 stage 2,亦即「我們的版本」,file2 是 stage 3,亦即「他們的版本」)。

其他差異格式

--summary 選項描述了新增加、刪除、重新命名和複製的檔案。--stat 選項在輸出中加入 diffstat(1) 圖表。這些選項可以與其他選項(如 -p)結合使用,且適合人類閱讀。

在顯示涉及重新命名或複製的變更時,--stat 輸出會透過組合路徑名的共同前綴和後綴來精簡地格式化路徑名。例如,將 arch/i386/Makefile 移動到 arch/x86/Makefile 並修改 4 行的變更將顯示如下

arch/{i386 => x86}/Makefile    |   4 +--

--numstat 選項提供 diffstat(1) 資訊,但設計上是為了更方便機器處理。--numstat 輸出中的一筆項目看起來像這樣

1	2	README
3	1	arch/{i386 => x86}/Makefile

也就是說,從左到右為

  1. 新增的列數;

  2. 一個 tab 字元;

  3. 刪除的列數;

  4. 一個 tab 字元;

  5. 路徑名(可能帶有重新命名/複製資訊);

  6. 一個換行符號。

-z 輸出選項生效時,輸出格式如下

1	2	README NUL
3	1	NUL arch/i386/Makefile NUL arch/x86/Makefile NUL

也就是

  1. 新增的列數;

  2. 一個 tab 字元;

  3. 刪除的列數;

  4. 一個 tab 字元;

  5. 一個 NUL(僅在重新命名/複製時存在);

  6. 變更前 (preimage) 的路徑名;

  7. 一個 NUL(僅在重新命名/複製時存在);

  8. 變更後 (postimage) 的路徑名(僅在重新命名/複製時存在);

  9. 一個 NUL。

在重新命名的情況下,變更前路徑之前的額外 NUL 是為了讓讀取輸出的指令稿在不預讀的情況下,判斷目前讀取的紀錄是單一路徑紀錄還是重新命名/複製紀錄。讀取新增和刪除的行數後,讀取到 NUL 將會得到路徑名,但如果該路徑名是 NUL,則表示該紀錄將顯示兩個路徑。

GIT

git[1] 套件的一部分