中文 (简体) ▾ 主题 ▾ 最新版本 ▾ 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>_ 可以采用以下形式之一

  • number

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

  • /regex/

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

  • +offset or -offset

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

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

-l

显示长 rev(默认:关闭)。

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

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

-C[<num>]

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

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

--ignore-rev <rev>

在分配 blame 时忽略修订版本所做的更改,就好像该更改从未发生过一样。被忽略的提交更改或添加的行将被 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")。

实际行的内容在上面的标头之后输出,并以 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