Git
英文 ▾ 主題 ▾ 最新版本 ▾ git-diff-files 最後更新於 2.46.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> 行上下文的差異,而不是通常的三行。表示 --patch

--output=<file>

輸出到特定檔案,而不是標準輸出。

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

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

--raw

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

--patch-with-raw

-p --raw 的同義詞。

--indent-heuristic

啟用啟發式演算法,將差異塊邊界移位,以使修補程式更容易閱讀。這是預設值。

--no-indent-heuristic

停用縮排啟發式演算法。

--minimal

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

--patience

使用「耐心差異」演算法產生差異。

--histogram

使用「直方圖差異」演算法產生差異。

--anchored=<text>

使用「錨定差異」演算法產生差異。

可以多次指定此選項。

如果一行同時存在於來源和目標中,僅存在一次,且以這個文字開頭,則此演算法會嘗試防止它在輸出中顯示為刪除或新增。它在內部使用「耐心差異」演算法。

--diff-algorithm={patience|minimal|histogram|myers}

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

default, myers

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

minimal

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

patience

產生修補程式時使用「耐心差異」演算法。

histogram

此演算法將耐心演算法擴展為「支援低頻率的通用元素」。

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

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

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

這些參數也可以使用 --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[<param1,param2,…​>]
--dirstat[=<param1,param2,…​>]

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

changes

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

lines

透過執行常規的基於行的差異分析並將移除/新增的行數相加來計算 dirstat 數字。(對於二進位檔案,則計算 64 位元組的區塊,因為二進位檔案沒有自然行的概念)。這是一種比 changes 行為更昂貴的 --dirstat 行為,但它確實像其他變更一樣計算檔案中重新排列的行。產生的輸出與您從其他 --*stat 選項中獲得的輸出一致。

files

透過計算變更的檔案數量來計算目錄統計(dirstat)數字。每個變更的檔案在目錄統計分析中都計為相同權重。這是計算成本最低的 --dirstat 行為,因為它完全不需要查看檔案內容。

cumulative

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

<limit>

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

範例:以下命令將計算變更的檔案,同時忽略變更檔案總數低於 10% 的目錄,並將子目錄計數累加到父目錄中:--dirstat=files,10,cumulative

--cumulative

--dirstat=cumulative 的同義詞

--dirstat-by-file[=<param1,param2>…​]

--dirstat=files,<param1>,<param2>…​ 的同義詞

--summary

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

--patch-with-stat

-p --stat 的同義詞。

-z

當給定 --raw--numstat--name-only--name-status 時,不要竄改路徑名稱,並使用 NUL 作為輸出欄位終止符。

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

--name-only

僅顯示後映像樹中每個變更檔案的名稱。檔案名稱通常以 UTF-8 編碼。如需更多資訊,請參閱 git-log[1] 手冊頁中關於編碼的討論。

--name-status

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

--submodule[=<format>]

指定如何顯示子模組中的差異。當指定 --submodule=short 時,會使用*short* 格式。此格式僅顯示範圍開始和結束時的 commit 名稱。當指定 --submodule--submodule=log 時,會使用 *log* 格式。此格式會像 git-submodule[1] summary 一樣列出範圍內的 commit。當指定 --submodule=diff 時,會使用 *diff* 格式。此格式會顯示 commit 範圍之間子模組內容變更的內嵌差異。預設為 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=<modes>

此選項設定在對 --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>]

顯示單字差異,使用 <mode> 來分隔變更的單字。預設情況下,單字由空白分隔;請參閱下方的 --word-diff-regex。<mode> 預設為 *plain*,且必須是下列其中之一

color

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

plain

將單字顯示為 [-removed-]{+added+}。如果分隔符號出現在輸入中,則不嘗試逸出分隔符號,因此輸出可能不明確。

porcelain

使用專為指令碼耗用而設計的特殊行式格式。已新增/已移除/未變更的執行會以通常的統一差異格式列印,行的開頭使用 +/-/` ` 字元,並延伸至行尾。輸入中的換行符號會由單獨一行上的波浪號 ~ 表示。

none

再次停用單字差異。

請注意,儘管第一個模式的名稱如此,但如果啟用,則會使用顏色來突顯所有模式中的變更部分。

--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

關閉重新命名偵測,即使配置檔案預設會執行此操作。

--[no-]rename-empty

是否使用空的 Blob 作為重新命名來源。

--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

在產生修補程式格式輸出時,不要顯示前映像和後映像 Blob 物件名稱的前幾個字元,而是在「索引」行上顯示完整的前映像和後映像 Blob 物件名稱。

--binary

除了 --full-index 之外,還會輸出可以使用 git-apply 套用的二進位差異。隱含 --patch

--abbrev[=<n>]

在 diff-raw 格式的輸出和 diff-tree 的標頭行中,不顯示完整的 40 位元組十六進位物件名稱,而是顯示長度至少為 <n> 位數且能唯一識別物件的最短前綴。在 diff-patch 輸出格式中,--full-index 具有較高的優先權,也就是說,如果指定了 --full-index,則無論是否使用 --abbrev,都會顯示完整的 blob 名稱。可以使用 --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>

尋找變更檔案中指定字串出現次數差異 (即新增/刪除) 的變更。適用於腳本編寫者使用。

當您尋找確切的程式碼區塊 (例如結構),並且想知道該區塊自第一次出現以來的歷史記錄時,它非常有用:迭代使用此功能,將預映像中感興趣的區塊回饋到 -S 中,然後持續執行直到您取得該區塊的最早版本。

也會搜尋二進位檔案。

-G<regex>

尋找其修補程式文字包含符合 <regex> 的新增/刪除行的差異。

若要說明 -S<regex> --pickaxe-regex-G<regex> 之間的差異,請考慮在同一個檔案中包含以下差異的 commit:

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

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

除非提供了 --text,否則將會忽略沒有 textconv 篩選器的二進位檔案修補程式。

如需詳細資訊,請參閱 gitdiffcore[7] 中的 pickaxe 項目。

--find-object=<object-id>

尋找變更指定物件出現次數差異的變更。與 -S 類似,只是參數不同,它不會搜尋特定字串,而是搜尋特定物件 ID。

該物件可以是 blob 或子模組 commit。它會隱含 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 樣式的順序決定。會先輸出路徑名稱符合第一個樣式的檔案,接著輸出路徑名稱符合第二個樣式 (但不是第一個) 的檔案,依此類推。最後會輸出路徑名稱不符合任何樣式的檔案,就像檔案結尾有一個隱含的全部比對樣式一樣。如果多個路徑名稱具有相同的等級 (它們符合相同的樣式但沒有較早的樣式),則它們彼此之間的輸出順序為正常順序。

<orderfile> 的剖析方式如下:

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

  • 會忽略以井號 ("#") 開頭的行,因此它們可以用於註解。如果樣式以井號開頭,請在樣式開頭新增反斜線 ("\")。

  • 每一行都包含單一樣式。

樣式的語法和語意與用於 fnmatch(3) 的樣式相同,但不包括 FNM_PATHNAME 標記,除非移除任意數量的最終路徑名稱元件符合該樣式,否則路徑名稱也會符合樣式。例如,樣式 "foo*bar" 符合 "fooasdfbar" 和 "foo/bar/baz/asdf",但不符合 "foobarx"。

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

捨棄輸出中指定 <file> 之前的檔案 (即跳過到),或將它們移至輸出結尾 (即旋轉到)。這些選項主要是為 git difftool 命令而發明的,否則可能沒有太多用處。

-R

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

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

當從專案的子目錄執行時,可以使用此選項來排除目錄外的變更,並顯示相對於該目錄的路徑名稱。當您不在子目錄中(例如,在裸儲存庫中),您可以透過給定一個 <path> 作為參數,來指定輸出的相對子目錄。--no-relative 可以用來反制 diff.relative 設定選項和先前的 --relative

-a
--text

將所有檔案視為文字。

--ignore-cr-at-eol

在比較時忽略行尾的回車符。

--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=<lines>

顯示差異區塊之間的上下文,最多為指定的行數,從而融合彼此接近的區塊。預設值為 diff.interHunkContext,如果未設定組態選項,則預設值為 0。

-W
--function-context

顯示整個函數作為每個變更的上下文行。函數名稱的確定方式與 git diff 計算 patch hunk 標頭的方式相同(請參閱 gitattributes[5] 中的「定義自訂 hunk 標頭」)。

--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]。由於 textconv 篩選器通常是單向轉換,因此產生的差異適合人類使用,但無法套用。因此,textconv 篩選器預設僅針對 git-diff[1]git-log[1] 啟用,但不適用於 git-format-patch[1] 或差異管道命令。

--ignore-submodules[=<when>]

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

--src-prefix=<prefix>

顯示給定的來源前綴,而不是 "a/"。

--dst-prefix=<prefix>

顯示給定的目標前綴,而不是 "b/"。

--no-prefix

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

--default-prefix

使用預設的來源和目標前綴("a/" 和 "b/")。這會覆寫組態變數,例如 diff.noprefixdiff.srcPrefixdiff.dstPrefixdiff.mnemonicPrefix(請參閱 git-config(1))。

--line-prefix=<prefix>

在輸出的每一行前面加上額外的前綴。

--ita-invisible-in-index

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

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

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

分別比對 "base" 版本、"我們的分支" 或 "他們的分支"。使用這些選項,不會顯示合併項目的差異。

預設值是與我們的分支 (-2) 和乾淨解析的路徑進行比對。可以給定選項 -0 來省略未合併項目的差異輸出,而只顯示 "Unmerged"。

-c
--cc

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

-q

即使是不存在的檔案也保持靜默

原始輸出格式

"git-diff-index"、"git-diff-tree"、"git-diff-files" 和 "git diff --raw" 的原始輸出格式非常相似。

這些命令都會比較兩組事物;比較的內容有所不同

git-diff-index <tree-ish>

比較 <tree-ish> 和檔案系統上的檔案。

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

比較 <tree-ish> 和索引。

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

比較兩個參數命名的樹。

git-diff-files [<pattern>…​]

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

"git-diff-tree" 命令會先印出正在比較的雜湊值來開始其輸出。之後,所有命令都會為每個變更的檔案印出一行輸出。

輸出行的格式如下

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. "src" 的模式;如果為建立或未合併,則為 000000。

  3. 一個空格。

  4. "dst" 的模式;如果為刪除或未合併,則為 000000。

  5. 一個空格。

  6. "src" 的 sha1;如果為建立或未合併,則為 0{40}。

  7. 一個空格。

  8. "dst" 的 sha1;如果為刪除、未合併或「工作樹與索引不同步」,則為 0{40}。

  9. 一個空格。

  10. 狀態,後跟可選的「分數」數字。

  11. 當使用 -z 選項時,為 tab 或 NUL。

  12. "src" 的路徑

  13. 當使用 -z 選項時,為 tab 或 NUL;僅適用於 C 或 R。

  14. "dst" 的路徑;僅適用於 C 或 R。

  15. 當使用 -z 選項時,為 LF 或 NUL,以終止記錄。

可能的狀態字母為

  • A:新增檔案

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

  • D:刪除檔案

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

  • R:重新命名檔案

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

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

  • X:「未知」變更類型(很可能是錯誤,請回報)

狀態字母 C 和 R 後面總是跟著一個分數(表示移動或複製的來源和目標之間的相似百分比)。狀態字母 M 後面可能會跟著一個分數(表示檔案重寫的差異百分比)。

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

範例

:100644 100644 5be4a4a 0000000 M file.c

如果沒有 -z 選項,具有「不常見」字元的路徑名稱會被引起來,如組態變數 core.quotePath 所述(請參閱 git-config[1])。使用 -z 時,會逐字輸出檔案名稱,並以 NUL 位元組終止該行。

合併的差異格式

"git-diff-tree"、"git-diff-files" 和 "git-diff --raw" 可以使用 -c--cc 選項來產生合併提交的差異輸出。輸出與上述格式的不同之處在於:

  1. 每個父項都有一個冒號

  2. 有更多 "src" 模式和 "src" 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

--combined-all-paths 新增至 -c--cc 時的範例

::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

請注意,*合併差異*僅列出從所有父項修改的檔案。

使用 -p 產生 patch 文字

使用 -p 選項執行 git-diff[1]git-log[1]git-show[1]git-diff-index[1]git-diff-tree[1]git-diff-files[1] 會產生 patch 文字。您可以使用 GIT_EXTERNAL_DIFFGIT_DIFF_OPTS 環境變數(請參閱 git[1])以及 diff 屬性(請參閱 gitattributes[5])來自訂 patch 文字的建立。

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

  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>

    檔案模式以 6 位數八進制數字印出,包括檔案類型和檔案權限位元。

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

    相似度索引是未變更行的百分比,而相異度索引是已變更行的百分比。它是一個向下捨入的整數,後面跟著百分比符號。因此,100% 的相似度索引值保留給兩個相同的檔案,而 100% 的相異度表示舊檔案中沒有任何一行進入新檔案。

    索引行包含變更前後的 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 標頭會提及 Hunk 套用的函式名稱。有關如何針對特定語言調整此設定的詳細資訊,請參閱 gitattributes[5] 中的「定義自訂 Hunk 標頭」。

合併差異格式

任何產生差異的命令都可以使用 -c--cc 選項,在顯示合併時產生合併差異。當使用 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. 接著是一個兩行的來源檔案/目標檔案標頭:

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

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

    但是,如果提供了 --combined-all-paths 選項,則您將會取得一個 N+1 行的來源檔案/目標檔案標頭,而不是兩行的來源檔案/目標檔案,其中 N 是合併提交中的父系數量。

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

    如果重新命名或複製偵測處於啟用狀態,則這種擴展格式會很有用,可讓您查看不同父系中檔案的原始名稱。

  4. Chunk 標頭格式已修改,以防止人們意外將其饋送至 patch -p1。合併差異格式是為檢閱合併提交變更而建立的,並非用於套用。此變更類似於擴展索引標頭中的變更。

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

    合併差異格式的 Chunk 標頭中有 (父系數量 + 1) 個 @ 字元。

與傳統統一差異格式不同,後者使用單一欄顯示兩個檔案 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 是階段 2 又名「我們的版本」,file2 是階段 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. 定位字元;

  3. 刪除的行數;

  4. 定位字元;

  5. 路徑名稱 (可能包含重新命名/複製資訊);

  6. 換行符號。

-z 輸出選項生效時,輸出會以此方式格式化:

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

也就是說:

  1. 新增的行數;

  2. 定位字元;

  3. 刪除的行數;

  4. 定位字元;

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

  6. 前像中的路徑名稱;

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

  8. 後像中的路徑名稱 (僅在重新命名/複製時存在);

  9. 一個 NUL。

重新命名案例中,前像路徑之前的額外 NUL,是為了讓讀取輸出的指令碼可以判斷目前正在讀取的記錄是單一路徑記錄還是重新命名/複製記錄,而無需提前讀取。讀取新增和刪除的行之後,讀取到 NUL 將會產生路徑名稱,但如果它是 NUL,則記錄將會顯示兩個路徑。

GIT

屬於 git[1] 套件的一部分

scroll-to-top