Git
英语 ▾ 主题 ▾ 最新版本 ▾ 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 还支持在开发历史中搜索代码片段出现的时刻。这使得能够追踪代码片段何时添加到文件、在文件之间移动或复制,以及最终删除或替换。它的工作原理是在 diff 中搜索文本字符串。一个使用 pickaxe 界面搜索 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

在 blame 输出的末尾包含额外的统计信息。

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

仅注释由 <start>,<end> 给出的行范围,或由函数名正则表达式 <funcname> 给出的行范围。可以指定多次。允许重叠范围。

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

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

  • 数字

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

  • /正则表达式/

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

  • +偏移量或-偏移量

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

如果在 <start><end> 的位置给出 :<funcname>,它是一个正则表达式,表示从匹配 <funcname> 的第一个 funcname 行开始到下一个 funcname 行结束的范围。:<funcname> 从上一个 -L 范围的末尾开始搜索,如果没有上一个范围,则从文件开头开始搜索。^:<funcname> 从文件开头开始搜索。函数名是以 git diff 确定补丁 hunk 头的方式确定的(参见 gitattributes[5] 中的 定义自定义 hunk 头)。

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

--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)归咎于父提交,并将向下移动的代码行(即 A)归咎于子提交。使用此选项,通过运行额外的检查传递,两组代码行都将归咎于父提交。

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

-C[<num>]

除了 -M 之外,还可以检测从同一提交中修改的其他文件中移动或复制的代码行。当你在程序中进行重构并将代码移动到不同的文件中时,这很有用。当此选项给出两次时,该命令还会查找来自创建该文件的提交中的其他文件的副本。当此选项给出三次时,该命令还会查找来自任何提交中的其他文件的副本。

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

--ignore-rev <rev>

在分配 blame 时忽略该版本所做的更改,就好像更改从未发生一样。由忽略的提交更改或添加的代码行将归咎于之前更改该行或附近代码行的提交。此选项可以指定多次,以忽略多个版本。如果设置了 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”)。

实际行的内容在上述标题之后输出,以制表符为前缀。这是为了允许以后添加更多标题元素。

瓷器格式通常会抑制已经看到的提交信息。例如,归属到同一个提交的两行都将显示出来,但该提交的详细信息只显示一次。这更加有效,但可能需要读者维护更多状态。可以使用--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