Git
英语 ▾ 主题 ▾ 版本 2.44.0 ▾ 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 或下文中简要提到的“十字镐”界面之类的工具。

除了支持文件注释之外,Git 还支持搜索开发历史,以查找代码片段在更改中出现的时间。这使得跟踪代码片段何时添加到文件、在文件之间移动或复制,以及最终删除或替换成为可能。它的工作原理是在 diff 中搜索文本字符串。搜索 blame_usage 的十字镐界面的一个小示例

$ 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

在责备输出的末尾包含其他统计信息。

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

仅注释由 <start>,<end> 给出的行范围,或由函数名称正则表达式 <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,其中要责备的路径存在于 START 中。为方便起见,git blame --reverse START 被视为 git blame --reverse START..HEAD

--first-parent

在看到合并提交时仅关注第一个父提交。此选项可用于确定某行何时引入到特定集成分支,而不是何时引入到整个历史记录中。

-p
--porcelain

以适合机器消费的格式显示。

--line-porcelain

显示瓷器格式,但输出每次提交的提交信息,而不仅仅是首次引用提交。暗示 --porcelain。

--incremental

以适合机器消费的格式逐步显示结果。

--encoding=<encoding>

指定用于输出作者姓名和提交摘要的编码。将其设置为 none 会使责备输出未转换的数据。有关更多信息,请参阅 git-log[1] 手册页中关于编码的讨论。

--contents <file>

使用指定文件中的内容进行注释,从 <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)归咎于父级,并将向下移动的行(即 A)归咎于子提交。使用此选项,通过运行额外的检查,将两组行都归咎于父级。

<num> 是可选的,但它是 Git 必须检测为文件内移动/复制的字母数字字符数的下限,以便将这些行与父提交相关联。默认值为 20。

-C[<num>]

除了 -M,检测从在同一提交中修改的其他文件中移动或复制的行。当您重新组织程序并在文件间移动代码时,这很有用。当此选项给出两次时,该命令还将查找创建文件的提交中其他文件中的副本。当此选项给出三次时,该命令还将查找任何提交中其他文件中的副本。

<num> 是可选的,但它是 Git 必须检测为文件间移动/复制的字母数字字符数的下限,以便将这些行与父提交相关联。默认值为 40。如果给出了多个 -C 选项,则最后一个 -C 的 <num> 参数将生效。

--ignore-rev <rev>

在分配责任时忽略修订所做的更改,就好像更改从未发生过一样。被忽略的提交更改或添加的行将被归咎于更改该行或附近行的上一个提交。此选项可以指定多次以忽略多个修订。如果设置了 blame.markIgnoredLines 配置选项,则被忽略的提交更改并归因于另一个提交的行将在责备输出中标记为 ?。如果设置了 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;

  • 原始文件中行的行号;

  • 最终文件中行的行号;

  • 在一行开始一组来自与前一个不同的提交的行时,此组中的行数。在后续行中,此字段不存在。

此标题行后至少为每个提交跟随以下信息一次

  • 作者姓名(“作者”)、电子邮件(“作者邮件”)、时间(“作者时间”)和时区(“作者时区”);提交者类似。

  • 行所归属的提交中的文件名。

  • 提交日志消息的第一行(“摘要”)。

实际行的内容在上述标题后输出,前面加上一个 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 选项调用时,该命令在构建时输出结果。输出通常会首先讨论最近提交中涉及的行(即,行将按无序方式注释),并且旨在供交互式查看器使用。

输出格式类似于 Porcelain 格式,但它不包含正在注释的文件的实际行。

  1. 每个责备条目始终以一行开头

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

    行号从 1 开始计数。

  2. 提交首次出现在流中时,它会打印有关它的其他各种信息,每行开头都有一个单词标签,描述额外的提交信息(作者、电子邮件、提交者、日期、摘要等)。

  3. 与 Porcelain 格式不同,始终给出文件名信息并终止条目

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

    因此,对于某些面向行和单词的解析器(这对于大多数脚本语言来说应该是很自然的)来说,解析起来非常容易。

    注意
    对于执行解析的人员:为了使其更健壮,只需忽略第一个和最后一个(“<sha1>”和“文件名”行)之间的任何行,其中你无法识别“扩展信息”行开头的标签词(或不关心该特定词)。这样,如果将来添加信息(如提交编码或扩展提交注释),责备查看器将不会在意。

映射作者

请参阅 gitmailmap[5]

配置

本节中此行以下的所有内容均有选择地包含在 git-config[1] 文档中。内容与在那里找到的内容相同

blame.blankBoundary

git-blame[1] 中为边界提交显示空白提交对象名称。此选项默认为 false。

blame.coloring

这决定了应用于责备输出的着色方案。它可以是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