Git
English ▾ 主題 ▾ 最新版本 ▾ git-blame 最後更新於 2.44.0

名稱

git-blame - 顯示檔案中每一行最後修改的修訂版本和作者

概要

git blame [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-e] [-p] [-w] [--incremental]
	    [-L <range>] [-S <revs-file>] [-M] [-C] [-C] [-C] [--since=<date>]
	    [--ignore-rev <rev>] [--ignore-revs-file <file>]
	    [--color-lines] [--color-by-age] [--progress] [--abbrev=<n>]
	    [ --contents <file> ] [<rev> | --reverse <rev>..<rev>] [--] <file>

描述

使用最後修改該行的修訂版本的資訊註解指定檔案中的每一行。可選地,從指定的修訂版本開始註解。

當指定一次或多次時,-L 會將註解限制為請求的行。

行的來源會自動追蹤整個檔案的重新命名(目前沒有關閉追蹤重新命名的選項)。要追蹤從一個檔案移動到另一個檔案的行,或追蹤從另一個檔案複製貼上的行,等等,請參閱 -C-M 選項。

該報告不會告訴您任何關於已刪除或取代的行的資訊;您需要使用諸如 *git diff* 之類的工具,或是在下面段落中簡要提及的「pickaxe」介面。

除了支援檔案註解外,Git 還支援搜尋開發歷史,以了解程式碼片段何時出現在變更中。這使得追蹤程式碼片段何時新增至檔案、在檔案之間移動或複製,以及最終刪除或取代成為可能。它的運作方式是在差異中搜尋文字字串。以下是一個搜尋 blame_usage 的 pickaxe 介面的小範例

$ git log --pretty=oneline -S'blame_usage'
5040f17eba15504bad66b14a645bddd9b015ebb7 blame -S <ancestry-file>
ea4c7f9bf69e781dd0cd88d2bccb2bf5cc15c9a7 git-blame: Make the output

選項

-b

顯示邊界提交的空白 SHA-1。這也可以透過 blame.blankBoundary 配置選項控制。

--root

不要將根提交視為邊界。這也可以透過 blame.showRoot 配置選項控制。

--show-stats

在 blame 輸出結尾包含額外的統計資訊。

-L <start>,<end>
-L :<funcname>

僅註解由 *<start>,<end>* 或函數名稱 regex *<funcname>* 給定的行範圍。可以多次指定。允許重疊範圍。

*<start>* 和 *<end>* 是可選的。-L <start>-L <start>, 從 *<start>* 延伸到檔案結尾。-L ,<end> 從檔案開頭延伸到 *<end>*。

*<start>* 和 *<end>* 可以採用以下形式之一

  • 數字

    如果 *<start>* 或 *<end>* 是數字,則它指定絕對行號(行數從 1 開始)。

  • /regex/

    此形式將使用第一個符合給定 POSIX regex 的行。如果 *<start>* 是 regex,它將從上一個 -L 範圍的結尾開始搜尋,如果沒有,則從檔案的開頭開始搜尋。如果 *<start>* 是 ^/regex/,它將從檔案的開頭開始搜尋。如果 *<end>* 是 regex,它將從 *<start>* 給定的行開始搜尋。

  • +offset 或 -offset

    這僅對 *<end>* 有效,並將指定 *<start>* 給定的行之前或之後的行數。

如果以 :<funcname> 取代 *<start>* 和 *<end>*,則它是表示從第一個符合 *<funcname>* 的 funcname 行到下一個 funcname 行的範圍的正規表示式。:<funcname> 從上一個 -L 範圍的結尾開始搜尋,如果沒有,則從檔案的開頭開始搜尋。^:<funcname> 從檔案的開頭開始搜尋。函數名稱的決定方式與 git diff 計算出修補程式區塊標頭的方式相同(請參閱 gitattributes[5] 中的 *定義自訂區塊標頭*)。

-l

顯示長修訂版本 (預設值:關閉)。

-t

顯示原始時間戳記 (預設值:關閉)。

-S <revs-file>

使用來自 revs-file 的修訂版本,而不是呼叫 git-rev-list[1]

--reverse <rev>..<rev>

向前而不是向後瀏覽歷史。不是顯示一行出現的修訂版本,而是顯示一行存在的最後修訂版本。這需要像 START..END 這樣的修訂版本範圍,其中要 blame 的路徑存在於 START 中。為了方便起見,git blame --reverse START 會被視為 git blame --reverse START..HEAD

--first-parent

在看到合併提交時,僅追蹤第一個父提交。此選項可用於判斷某行何時引入到特定整合分支,而不是何時引入到整體歷史中。

-p
--porcelain

以設計用於機器消費的格式顯示。

--line-porcelain

顯示 porcelain 格式,但為每行輸出提交資訊,而不僅僅是第一次引用提交時。隱含 --porcelain。

--incremental

以設計用於機器消費的格式增量顯示結果。

--encoding=<encoding>

指定用於輸出作者名稱和提交摘要的編碼。將其設定為 none 會使 blame 輸出未轉換的資料。有關更多資訊,請參閱 git-log[1] 手冊頁中關於編碼的討論。

--contents <file>

從指定的檔案內容開始註解,如果指定了 <rev>,則從 <rev> 開始,否則從 HEAD 開始。您可以指定 *-* 以使命令從標準輸入讀取檔案內容。

--date <format>

指定用於輸出日期的格式。如果未提供 --date,則會使用 blame.date 配置變數的值。如果也未設定 blame.date 配置變數,則會使用 iso 格式。有關支援的值,請參閱 git-log[1] 中 --date 選項的討論。

--[no-]progress

預設情況下,當進度狀態連接到終端時,會在標準錯誤流上報告。即使未連接到終端,此標誌也會啟用進度報告。不能將 --progress--porcelain--incremental 一起使用。

-M[<num>]

偵測檔案內移動或複製的行。當提交移動或複製程式碼區塊時(例如,原始檔案具有 A 和 B,然後提交將其變更為 B 然後 A),傳統的 *blame* 演算法僅會注意到一半的移動,並且通常會將向上移動的行(即 B) blame 到父系,並將向下移動的行(即 A) blame 到子提交。透過此選項,可以透過執行額外的檢查遍歷,將兩組程式碼行 blame 到父系。

<num> 是可選的,但它是 Git 必須偵測為在檔案內移動/複製以將這些程式碼行與父提交關聯的字母數字字元的下限。預設值為 20。

-C[<num>]

除了 -M 之外,還會偵測在同一提交中修改的其他檔案中移動或複製的程式碼行。當您重新組織程式並在檔案之間移動程式碼時,這非常有用。當此選項給定兩次時,該命令還會尋找提交中其他檔案的複本,該提交會建立檔案。當此選項給定三次時,該命令還會尋找任何提交中其他檔案的複本。

<num> 是可選的,但它是在 Git 偵測到檔案之間有移動/複製時,必須視為與父提交相關聯的字母數字字元數量的下限。預設值為 40。如果給定多個 -C 選項,則最後一個 -C<num> 參數將生效。

--ignore-rev <rev>

在指派責任時,忽略修訂版本所做的變更,就好像變更從未發生過一樣。由忽略的提交所變更或新增的行,將會歸咎於前一個變更該行或附近行的提交。此選項可以指定多次,以忽略多個修訂版本。如果設定了 blame.markIgnoredLines 組態選項,則由忽略的提交變更並歸因於另一個提交的行,將在 blame 輸出中標記為 ?。如果設定了 blame.markUnblamableLines 組態選項,則由忽略的提交觸及的、且我們無法歸因於其他修訂版本的行,將標記為 *

--ignore-revs-file <file>

忽略在 file 中列出的修訂版本,其格式必須與 fsck.skipList 相同。此選項可以重複使用,並且這些檔案將在任何使用 blame.ignoreRevsFile 組態選項指定的檔案之後處理。一個空的檔案名稱 "" 將清除先前處理過的檔案中的修訂版本列表。

--color-lines

如果行註解與前一行來自同一個提交,則以不同的顏色顯示預設格式的行註解。這使得區分不同提交引入的程式碼區塊更容易。顏色預設為青色,可以使用 color.blame.repeatedLines 組態選項進行調整。

--color-by-age

根據預設格式中行的存在時間來對行註解進行著色。color.blame.highlightRecent 組態選項控制每個存在時間範圍所使用的顏色。

-h

顯示說明訊息。

-c

使用與 git-annotate[1] 相同的輸出模式 (預設:關閉)。

--score-debug

包含與檔案之間的行移動 (請參閱 -C) 和檔案內移動的行 (請參閱 -M) 相關的偵錯資訊。列出的第一個數字是分數。這是偵測到在檔案之間或檔案內移動的字母數字字元的數量。此數量必須高於特定閾值,git blame 才會將這些程式碼行視為已移動。

-f
--show-name

顯示原始提交中的檔案名稱。預設情況下,如果存在任何來自不同名稱的檔案的行,則會顯示檔案名稱,這是由於重新命名偵測所致。

-n
--show-number

顯示原始提交中的行號 (預設:關閉)。

-s

從輸出中隱藏作者姓名和時間戳記。

-e
--show-email

顯示作者電子郵件,而不是作者姓名 (預設:關閉)。這也可以通過 blame.showEmail 組態選項進行控制。

-w

在比較父版本和子版本以找出行的來源時,忽略空白字元。

--abbrev=<n>

不使用預設的 7+1 個十六進制數字作為縮寫物件名稱,而是使用 <m>+1 個數字,其中 <m> 至少為 <n>,但確保提交物件名稱是唯一的。請注意,1 個欄位用於插入符號,以標記邊界提交。

預設格式

當未指定 --porcelain--incremental 選項時,git blame 將會為每一行輸出註解,包含

  • 行來自的提交的縮寫物件名稱;

  • 作者識別資訊 (預設為作者姓名和日期,除非指定了 -s-e);以及

  • 行號

在行內容之前。

瓷器格式

在此格式中,每一行在標頭之後輸出;標頭至少有第一行,其中包含

  • 該行歸屬的提交的 40 位元組 SHA-1;

  • 原始檔案中行的行號;

  • 最終檔案中行的行號;

  • 在開始一組行來自不同於前一個提交的行的行上,此組中的行數。在後續的行上,此欄位將不存在。

此標頭行之後,至少會為每個提交顯示一次以下資訊

  • 作者姓名 ("author")、電子郵件 ("author-mail")、時間 ("author-time") 和時區 ("author-tz");提交者也類似。

  • 該行歸屬的提交中的檔案名稱。

  • 提交記錄訊息的第一行 ("summary")。

實際行的內容會接在上述標頭之後輸出,並以 TAB 作為前綴。這是為了允許稍後新增更多標頭元素。

瓷器格式通常會隱藏已看到的提交資訊。例如,歸咎於相同提交的兩行都將顯示,但該提交的詳細資訊只會顯示一次。這更有效率,但可能需要讀取器保留更多狀態。可以使用 --line-porcelain 選項為每一行輸出完整的提交資訊,允許更簡單 (但效率較低) 的用法,例如

# count the number of lines attributed to each author
git blame --line-porcelain file |
sed -n 's/^author //p' |
sort | uniq -c | sort -rn

指定範圍

與較舊版本的 git 中的 git blamegit annotate 不同,註解的範圍可以限制為行範圍和修訂版本範圍。可以多次指定 -L 選項,該選項將註解限制在某個行範圍內。

當您有興趣找到檔案 foo 的 40-60 行的來源時,您可以使用 -L 選項,如下所示 (它們表示相同的含義 - 兩者都要求從第 40 行開始的 21 行)

git blame -L 40,60 foo
git blame -L 40,+21 foo

您也可以使用正則表達式來指定行範圍

git blame -L '/^sub hello {/,/^}$/' foo

這將註解限制在 hello 子例程的主體中。

當您對版本 v2.6.18 之前的變更或 3 週之前的變更不感興趣時,您可以使用類似於 git rev-list 的修訂版本範圍指定符

git blame v2.6.18.. -- foo
git blame --since=3.weeks -- foo

當使用修訂版本範圍指定符來限制註解時,自範圍邊界以來未變更的行 (在上面的例子中,無論是提交 v2.6.18 還是最近一次超過 3 週的提交),都會將該範圍邊界提交歸咎於該行。

一種特別有用的方法是查看新增的檔案是否具有從現有檔案複製貼上的行。有時,這表示開發人員很草率,沒有正確地重構程式碼。您可以首先使用以下命令找到引入檔案的提交

git log --diff-filter=A --pretty=short -- foo

然後使用 commit^! 表示法,在提交及其父提交之間註解變更

git blame -C -C -f $commit^! -- foo

增量輸出

當使用 --incremental 選項呼叫時,命令會在建立結果時輸出結果。輸出通常會先提到最近提交所觸及的行 (也就是說,行會以無序的方式進行註解),並旨在供互動式檢視器使用。

輸出格式與瓷器格式類似,但不包含正在註解的檔案中的實際行。

  1. 每個 blame 條目都始終以一行開始

    <40-byte-hex-sha1> <sourceline> <resultline> <num-lines>

    行號從 1 開始計數。

  2. 提交在資料流中第一次出現時,會印出關於它的各種其他資訊,每行的開頭都會有一個描述額外提交資訊的單字標籤 (作者、電子郵件、提交者、日期、摘要等等)。

  3. 與瓷器格式不同,永遠會給出檔案名稱資訊,並終止條目

    "filename" <whitespace-quoted-filename-goes-here>

    因此,對於某些面向行和單字的剖析器來說,剖析它真的相當容易 (對於大多數腳本語言來說,這應該是很自然的)。

    注意
    對於進行剖析的人員:為了使其更加穩健,只需忽略第一個和最後一個 ("<sha1>" 和 "filename" 行) 之間,您不認識標籤單字 (或關心特定單字) 的任何行。這樣一來,如果新增了任何資訊 (例如提交編碼或擴展提交評論),blame 檢視器就不會介意。

對應作者

請參閱 gitmailmap[5]

組態

此節中此行以下的所有內容都從 git-config[1] 文件中有選擇地包含。內容與該處找到的內容相同

blame.blankBoundary

git-blame[1] 中顯示邊界提交的空白提交物件名稱。此選項預設為 false。

blame.coloring

這決定套用至 blame 輸出的著色配置。它可以是 repeatedLineshighlightRecentnone,這是預設值。

blame.date

指定用於在 git-blame[1] 中輸出日期的格式。如果未設定,則使用 iso 格式。有關支援的值,請參閱 git-log[1]--date 選項的討論。

blame.showEmail

git-blame[1] 中顯示作者電子郵件,而不是作者姓名。此選項預設為 false。

blame.showRoot

git-blame[1] 中,不要將根提交視為邊界。此選項預設為 false。

blame.ignoreRevsFile

忽略檔案中列出的修訂版本,每行一個未縮寫的物件名稱,請參考 git-blame[1]。空白字元和以 # 開頭的註解將被忽略。此選項可以重複多次使用。空的檔案名稱將重置忽略的修訂版本清單。此選項將在命令行選項 --ignore-revs-file 之前處理。

blame.markUnblamableLines

git-blame[1] 的輸出中,將無法歸因於其他提交的、由忽略的修訂版本所變更的行標記為 *

blame.markIgnoredLines

git-blame[1] 的輸出中,將歸因於其他提交的、由忽略的修訂版本所變更的行標記為 ?

另請參閱

GIT

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

scroll-to-top