简体中文 ▾ 主题 ▾ 最新版本 ▾ git-blame 上次更新于 2.52.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 还支持搜索开发历史以查找代码片段的出现。这使得跟踪代码片段何时被添加到文件、在文件之间移动或复制、以及最终被删除或替换成为可能。它通过在 diff 中搜索文本字符串来实现。一个搜索 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> 给出的行范围,或由函数名正则表达式 <funcname> 指定的范围。可以多次指定。允许重叠范围。

<start><end> 是可选的。-L <start>-L <start>,<start> 跨越到文件末尾。-L ,<end> 从文件开头跨越到 <end>

<start><end> 可以采用以下形式之一

  • <number>

    如果 <start><end> 是一个数字,它指定一个绝对行号(行从 1 开始计数)。

  • /<regex>/

    此形式将使用第一个匹配给定 POSIX <regex> 的行。如果 <start> 是一个正则表达式,它将从上一个 -L 范围的末尾(如果存在)开始搜索,否则从文件开头开始搜索。如果 <start>^/<regex>/,它将从文件开头开始搜索。如果 <end> 是一个正则表达式,它将从 <start> 给定的行开始搜索。

  • +<offset>-<offset>

    这仅对 <end> 有效,并将指定 <start> 给定行之前或之后的行数。

如果用 <start><end> 的位置给出了 :<funcname>,它是一个正则表达式,表示从第一个匹配 <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 格式显示,但输出每行的提交信息,而不仅仅是提交首次被引用的地方。隐含 --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 选项的讨论。

--progress
--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 时忽略由某个修订版本所做的更改,就好像该更改从未发生过一样。由被忽略的提交更改或添加的行将被归因于上一提交,该提交更改了该行或附近行。此选项可以多次指定以忽略多个修订版本。如果设置了 blame.markIgnoredLines 配置选项,则被忽略提交更改并归因于另一提交的行将在 blame 输出中标记为 ?。如果设置了 blame.markUnblamableLines 配置选项,则那些被忽略提交触摸但我们无法归因于另一修订版本的行将标记为 *。在 porcelain 模式下,我们分别在换行符上打印 ignoredunblamable

--ignore-revs-file <file>

忽略 file 中列出的修订版本,该文件必须与 fsck.skipList 格式相同。此选项可以重复,并且这些文件将在处理完任何通过 blame.ignoreRevsFile 配置选项指定的 file 后处理。空文件名 "" 将清除之前处理的文件中的修订列表。

--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);以及

  • 行号

在行内容之前。

Porcelain 格式

在此格式中,每行在头部信息之后输出;头部至少包含以下内容:

  • 行所属提交的 40 字节 SHA-1;

  • 行在原始文件中的行号;

  • 行在最终文件中的行号;

  • 在一个标志着一组行与前一组不同的行的起始行上,显示该组的行数。在后续行上,此字段不存在。

此头部行之后,至少一次会输出以下信息:

  • 作者姓名(“author”)、电子邮件(“author-mail”)、时间(“author-time”)和时区(“author-tz”);提交者信息类似。

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

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

实际行的内容在上述头部信息之后输出,并以 TAB 作为前缀。这是为了以后可以添加更多头部元素。

Porcelain 格式通常会抑制已经见过的提交信息。例如,被 blame 到同一个提交的两行都会显示,但该提交的详细信息只显示一次。特定于单个行的信息不会分组在一起,例如标记为 ignoredunblamable 的修订版本。这更有效率,但可能需要读取器保留更多状态。--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. 每个 blame 条目始终以一行开始:

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

    行号从 1 开始计数。

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

  3. 与 Porcelain 格式不同,文件名信息始终提供,并且以文件名行结束该条目

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

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

    注意
    对于进行解析的人员:为了使其更健壮,只需忽略第一个和最后一个行(“<sha1>”和“filename”行)之间的所有行,其中您不识别标签词(或不关心该特定标签词)在“扩展信息”行的开头。这样,如果将来添加了信息(例如提交编码或扩展提交评论),blame 查看器也不会受影响。

作者映射

请参阅 gitmailmap[5]

配置

本节中以下所有内容均从 git-config[1] 文档中选择性地包含。内容与彼处相同:

blame.blankBoundary

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

blame.coloring

这决定了应用于 blame 输出的着色方案。它可以是 repeatedLineshighlightRecentnone,其中 none 是默认值。

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] 套件的一部分