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

在历史追溯输出的结尾处包括额外的统计数据。


-L <start>,<end>

-L :<funcname>

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

<start> 和 <end> 是可选的 -L <start> 或 -L <start>, 范围从 <start> 到文件末尾。 -L ,<end> 从文件开始到 <end>.


-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 会使历史追溯输出未转换的数据。


–contents <file>

使用指定文件中的内容进行注释,如果指定了 <rev>,则从 <rev> 开始,否则从 HEAD 开始。你可以指定 - 来使命令从标准输入中读取文件内容。


–date <格式>

指定用于输出日期的格式。如果没有提供 –date,则使用 blame.date 配置变量的值。如果 blame.date 配置变量也没有设置,则使用 iso 格式。


–[no-]progress

当它连接到一个终端时,默认情况下进度状态会在标准错误流中报告。这个标志可以使进度报告即使没有连接到终端。–porcelain或--incremental 不能与 –progress 一起使用。


-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 中列出的修订,其格式必须与 fsck.skipList 相同。 这个选项可以重复使用,这些文件将在任何用 blame.ignoreRevsFile 配置选项指定的文件之后被处理。 一个空的文件名,““,将清除以前处理的文件的 Revs 列表。


–color-lines

在默认格式下,如果行注释与前一行来自同一提交,则颜色不同。这可以让我们更容易区分不同提交的代码块。颜色默认为青色,可以使用 color. blame.repeatedLines 配置选项进行调整。


–color-by-age

根据默认格式的行的阶段,给行的注释着色。 color.blue.highlightRecent 配置选项控制每个阶段范围使用什么颜色。


-h

显示帮助信息。


-c

使用与git - annotate相同的输出模式(默认: off ) 。


–score-debug

包括与文件之间行的移动(见 -C)和文件内行的移动(见 -M)有关的调试信息。 列出的第一个数字是分数。 这是检测到的在文件间或文件内移动的字母数字字符的数量。 这个数字必须超过一定的阈值,git blame 才会认为这些代码行被移动了。


-f

–show-name

显示原始提交中的文件名。 默认情况下,如果有任何一行来自不同名字的文件,由于重名检测,文件名会显示出来。


-n

–show-number

显示原始提交中的行号(默认:off)。


-s

抑制输出中的作者姓名和时间戳。


-e

–show-email

显示作者的电子邮件地址,而不是作者的名字(默认:关闭) 。这也可以通过blame . showEmail配置选项来控制。


-w

在比较父本和子本的版本时,忽略空白,以找到行的来源。


–abbrev=<n>

不要使用默认的7+1个十六进制数字作为对象的缩写,而是使用 <m>+1 个数字,其中 <m> 至少是 <n>,但确保提交对象的名称是唯一的。 请注意,有1列是用来标记边界提交的关健词。


THE DEFAULT FORMAT

当既没有指定--porcelain 也没有指定--incremental 选项时,git blame 将为每一行输出注释:

  • 该行来自的提交的缩写对象名称;
  • 作者标识(默认为作者姓名和日期,除非指定了- s或- e );
  • 行号

在该行内容之前。


上层命令格式

在这种格式中,每一行都是在页眉之后输出的;页眉至少有第一行,它有:

  • 该行所归属的提交的 40 字节 SHA-1;
  • 原始文件中该行的行号;
  • 最后文件中该行的行号;
  • 在开始一组与前一次不同的提交的行上,该组的行数。 在随后的行中,这个字段是不存在的。


这个标题行后面是以下信息,每次提交至少有一次:

  • 作者姓名(“author”)、电子邮件(“author-mail”)、时间(“author-time”)和时区(“author-tz”);对提交者也是如此。
  • 该行归属的提交中的文件名。
  • 提交日志信息的第一行(“摘要”)。


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

上层命令格式通常会抑制已经看过的提交信息。例如,两行归咎于同一个提交的内容都会被显示出来,但该提交的细节只会被显示一次。这样做更有效率,但可能需要读者保存更多的状态:

# 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 blame” 和 “git 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 选项时,该命令在构建过程中输出结果。 一般来说,输出结果会先谈及最近提交的行(也就是说,这些行会被不按顺序的注释),并且是为了给交互式浏览者使用。


输出格式类似于上层命令格式,但它不包含被注释的文件的实际行数。


每个历史追溯条目总是以一行字开始:

<40-byte hex sha1> <sourceline> <resultline> <num_lines>

行数从 1 开始计算。


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


与上层命令格式不同,文件名信息总是给定的,并终止条目:

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

因此,对于一些面向行和字的解析器来说,它确实很容易解析(这对于大多数脚本语言来说应该是很自然的)。

Note

对于做解析的人来说:为了使它更健壮,只要忽略第一和最后一个(“<sha1>” 和 “filename” 行)之间的任何行,在 “扩展信息” 行的开头,你不认识标签词(或关心那个特定的)。这样一来,如果有一天增加了信息(比如提交编码或扩展的提交注释),历史追溯查看者就不会在意。