Git
英文 ▾ 主題 ▾ 最新版本 ▾ git-diff-index 最後更新於 2.46.0

名稱

git-diff-index - 比較樹狀結構與工作樹或索引

概要

git diff-index [-m] [--cached] [--merge-base] [<common-diff-options>] <tree-ish> [<path>…​]

說明

比較樹狀物件中找到的 blob 內容和模式,與工作樹中對應的追蹤檔案,或與索引中對應的路徑。當存在 <path> 引數時,僅比較符合這些模式的路徑。否則,將比較所有追蹤的檔案。

選項

-p
-u
--patch

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

-s
--no-patch

抑制 diff 機制的所有輸出。對於像 git show 這樣預設顯示修補程式的命令來說,這很有用,可以抑制它們的輸出,或者取消別名中較早的 --patch--stat 等選項的效果。

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

產生具有 <n> 行上下文的差異,而不是通常的三行。表示 --patch

--output=<file>

輸出到特定的檔案,而不是 stdout。

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

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

defaultmyers

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

minimal

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

patience

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

histogram

此演算法擴展了耐心演算法以「支援低頻率常見元素」。

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

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

產生 diffstat。預設情況下,會將必要的空間用於檔案名稱部分,其餘空間用於圖表部分。最大寬度預設為終端機寬度,如果未連接到終端機,則預設為 80 個欄位,並且可以被 <width> 覆蓋。檔案名稱部分的寬度可以通過在逗號後給出另一個寬度 <name-width> 或設定 diff.statNameWidth=<width> 來限制。圖表部分的寬度可以使用 --stat-graph-width=<width> 或設定 diff.statGraphWidth=<width> 來限制。使用 --stat--stat-graph-width 會影響產生 stat 圖表的所有命令,而設定 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

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

files

透過計算已變更的檔案數量來計算 dirstat 數字。每個已變更的檔案在 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* 格式。此格式只會顯示範圍開頭和結尾的提交名稱。當指定 --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* 將用於在 diff 中其他地方新增的已移除行。此模式會挑出任何移動的行,但在檢查以判斷程式碼區塊是否在沒有排列的情況下移動時,它並不是很有用。

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

將單字顯示為 [-已移除-]{+已新增+}。如果分隔符號出現在輸入中,則不會嘗試跳脫分隔符號,因此輸出可能不明確。

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>

在 diff 的 contextoldnew 行中,強調顯示空白錯誤。多個值以逗號分隔,none 重置先前的值,default 將列表重置為 new,而 allold,new,context 的縮寫。如果未提供此選項,且未設定組態變數 diff.wsErrorHighlight,則只會強調顯示 new 行中的空白錯誤。空白錯誤會以 color.diff.whitespace 著色。

--full-index

在產生 patch 格式輸出時,不要顯示前幾個字元,而是顯示「index」行上完整的 pre- 和 post-image blob 物件名稱。

--binary

除了 --full-index 之外,輸出可使用 git-apply 套用的二進位 diff。暗示 --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 認為這是完全重寫(也就是說,否則產生的 patch 將是一系列刪除和插入與上下文行混合在一起)。

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

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

偵測重新命名。如果指定了 n,則它是相似性索引的臨界值(即與檔案大小相比,新增/刪除的數量)。例如,-M90% 表示如果檔案的變更比例超過 90%,則 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

省略刪除的 preimage,也就是說,僅列印標頭,而不列印 preimage 和 /dev/null 之間的差異。產生的 patch 並不打算使用 patchgit apply 應用;這僅適用於只想專注於檢閱變更後文字的使用者。此外,輸出顯然缺少足夠的資訊來反向套用此類 patch,即使是手動套用也是如此,因此選項名稱如此。

-B 一起使用時,也會省略刪除/建立配對刪除部分的 preimage。

-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 會排除新增和刪除的路徑。

請注意,並非所有 diff 都具有所有類型。例如,如果已停用這些類型的偵測,則無法顯示複製和重新命名的項目。

-S<string>

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

當您正在尋找一個精確的程式碼區塊(例如結構)時,並且想要了解該區塊自首次出現以來的歷程記錄時,這非常有用:以迭代方式使用此功能,將 preimage 中的有趣區塊回傳到 -S 中,然後繼續直到取得該區塊的第一個版本。

也會搜尋二進位檔案。

-G<regex>

尋找其 patch 文字包含符合 <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 篩選器的二進位檔案 patch。

如需更多資訊,請參閱 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 輔助程式的執行,這些輔助程式的結束程式碼不可信任,即其各自的組態選項 diff.trustExitCodediff.<driver>.trustExitCode 或環境變數 GIT_EXTERNAL_DIFF_TRUST_EXIT_CODE 為 false。

--ext-diff

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

--no-ext-diff

不允許外部 diff 驅動程式。

--textconv
--no-textconv

允許(或不允許)在比較二進位檔案時執行外部文字轉換篩選器。有關詳細資訊,請參閱 gitattributes[5]。由於 textconv 篩選器通常是單向轉換,因此產生的 diff 適合人為閱讀,但無法套用。因此,textconv 篩選器預設僅針對 git-diff[1]git-log[1] 啟用,而不會針對 git-format-patch[1] 或 diff plumbing 命令啟用。

--ignore-submodules[=<when>]

忽略在 diff 產生中對子模組的變更。 <when> 可以是 "none"、"untracked"、"dirty" 或 "all",預設值為 "all"。使用 "none" 時,如果子模組包含未追蹤或已修改的檔案,或其 HEAD 與超級專案中記錄的 commit 不同,則會將子模組視為已修改,並且可以用於覆寫 git-config[1]gitmodules[5] 中 *ignore* 選項的任何設定。當使用 "untracked" 時,如果子模組僅包含未追蹤的內容,則不會將子模組視為 dirty(但仍會掃描已修改的內容)。使用 "dirty" 會忽略對子模組工作樹的所有變更,僅顯示對儲存在超級專案中的 commit 的變更(這是 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]

<tree-ish>

要比較的樹狀物件的 ID。

--cached

完全不考慮磁碟上的檔案。

--merge-base

不直接比較 <tree-ish>,而是改為使用 <tree-ish> 和 HEAD 之間的合併基礎。 <tree-ish> 必須是 commit。

-m

預設情況下,索引中記錄但未簽出的檔案會報告為已刪除。此標誌會使 git diff-index 說所有未簽出的檔案都是最新的。

原始輸出格式

"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. 一個 Tab 鍵或當使用 -z 選項時為一個 NUL。

  12. "src" 的路徑

  13. 一個 Tab 鍵或當使用 -z 選項時為一個 NUL;僅適用於 C 或 R。

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

  15. 一個 LF 或當使用 -z 選項時為一個 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 位元組終止。

合併的 diff 格式

"git-diff-tree"、"git-diff-files" 和 "git-diff --raw" 可以採用 -c--cc 選項來產生合併 commit 的 diff 輸出。輸出與上述格式的不同之處在於以下方面

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

  2. 有更多的「src」模式和「src」sha1

  3. 狀態是每個父項串連的狀態字元

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

  5. 檔案的 Tab 分隔路徑名稱

對於 -c--cc,即使檔案在歷史記錄的任何一側被重新命名,也僅會顯示目標或最終路徑。使用 --combined-all-paths,則會顯示每個父項中的路徑名稱,後面接著合併 commit 中的路徑名稱。

不使用 --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 產生補丁文字

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

    檔案模式以 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. 後面接著一個雙行 from-file/to-file 標頭

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

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

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

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

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

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

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

    合併差異格式的區塊標頭中有 (父節點數 + 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,則記錄會顯示兩個路徑。

運作模式

您可以選擇是否要完全信任索引檔 (使用 --cached 旗標),或要求差異邏輯顯示任何與統計狀態不符的檔案為「暫定變更」。 這兩種操作都非常有用。

已快取模式

如果指定了 --cached,則可讓您要求

show me the differences between HEAD and the current index
contents (the ones I'd write using 'git write-tree')

例如,假設您已在工作目錄中工作,更新了索引中的一些檔案,並準備好提交。 您想要查看您將要提交的確切內容,而不必寫入新的樹狀結構物件並以該方式進行比較,若要執行此操作,您只需執行

git diff-index --cached HEAD

範例:假設我已將 commit.c 重新命名為 git-commit.c,並且我已執行 update-index 以使其在索引檔案中生效。 git diff-files 不會顯示任何內容,因為索引檔案與我的工作目錄相符。 但是執行 _git diff-index_ 會顯示

torvalds@ppc970:~/git> git diff-index --cached HEAD
:100644 000000 4161aecc6700a2eb579e842af0b7f22b98443f74 0000000000000000000000000000000000000000 D	commit.c
:000000 100644 0000000000000000000000000000000000000000 4161aecc6700a2eb579e842af0b7f22b98443f74 A	git-commit.c

您可以很容易地看到以上是一個重新命名。

事實上,git diff-index --cached 應該始終完全等同於實際執行 _git write-tree_ 並進行比較。 只是對於您只想檢查目前狀況的情況,這種方式更好。

因此,當您在問自己「我已標記要提交的內容有哪些,以及與先前的樹狀結構有何差異」時,執行 git diff-index --cached 基本上非常有用。

未快取模式

「未快取」模式採用不同的方法,而且可能在兩種模式中更有用,因為它執行的動作無法使用 _git write-tree_ + _git diff-tree_ 來模擬。 因此,這是預設模式。 未快取版本會詢問以下問題

show me the differences between HEAD and the currently checked out
tree - index contents _and_ files that aren't up to date

這顯然也是一個非常有用的問題,因為這會告訴您您可以提交的內容。 同樣地,輸出會與 _git diff-tree -r_ 輸出完全一致,但有一個轉折。

關鍵在於,如果某些檔案與索引不匹配,我們就沒有對應的後備儲存機制,我們會使用特殊的「全零」SHA1值來表示。假設您編輯了 kernel/sched.c,但尚未對其執行 git update-index - 這樣新狀態沒有關聯的「物件」,您會得到以下結果:

torvalds@ppc970:~/v2.6/linux> git diff-index --abbrev HEAD
:100644 100644 7476bb5ba 000000000 M	kernel/sched.c

也就是說,它顯示樹狀結構已變更,且 kernel/sched.c 不是最新的,可能包含新的內容。全零 SHA1 值表示,若要取得實際的差異,您需要直接查看工作目錄中的物件,而不是進行物件到物件的差異比較。

注意
如同此類型的其他命令,git diff-index 實際上並不會查看檔案的內容。因此,也許 kernel/sched.c 實際上並未變更,而只是您碰觸了它。無論如何,這都表示您需要執行 git update-index 來讓索引同步。
注意
您可能會同時看到某些檔案顯示為「已更新」和「在工作目錄中仍為髒的」。您可以隨時判斷哪個檔案處於哪種狀態,因為「已更新」的檔案會顯示有效的 SHA1 值,而「與索引不同步」的檔案則始終會顯示特殊的全零 SHA1 值。

GIT

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

scroll-to-top