列出GIT历史记录中给定行号的所有版本

24
在Git中,是否可以通过行号列出给定文件中所有先前版本的特定行?我觉得这个功能非常有用,以便根据日志堆栈跟踪报告更轻松地解决问题。
例如,我在给定文件的第100行记录了一个“未定义的方法异常”,该文件包含在许多提交中,导致给定行即使没有对其进行任何更改也可能在文件中向上或向下“移动”。
如何打印出最近x次提交中给定文件中第100行的内容?

请参见 查看代码行的git历史记录 - CharlesB
@MRT:在我的回答中,我已经描述了如何查看一行的最后更改之后的内容。 - David Pärsson
2
我已经在重复的问题上发布了一个新的答案。如果这个问题没有被关闭,我会在这里保留相同的答案作为备份。 - krlmlr
7个回答

11

这将调用 git blame 来显示文件 $FILE 的行 $LINE每个有意义的修订版本中的责任:

git log --format=format:%H $FILE | xargs -L 1 git blame $FILE -L $LINE,$LINE

通常,每行的开头会显示修改编号,您可以追加

| sort | uniq -c

为了获得汇总结果,例如更改此行的提交列表。(但如果代码只是移动了位置,可能会显示相同的提交ID两次,而对于更详细的分析,您需要对相邻提交的git blame结果进行滞后比较。有人知道怎么做吗?)


谢谢,看起来这个做得很好。只是在xargs选项中需要使用大写的Lgit log --format=format:%H $FILE | xargs -L1 git blame $FILE -L $LINE,$LINE - mrt
@MRT:没错,根据 POSIX 标准,xargs-l 开关已经被弃用了。虽然在我的系统上可以使用,但是 -L 更好。 - krlmlr
git blame 命令的 -L 参数可用于查找代码而不是行号。例如,这对于查找已移动但未重命名的函数非常有用。 - David Pärsson

7

虽然不是完全符合您的要求,但是通过使用git blame <file>命令,您可以看到最后修改每行代码的提交。

第一列显示的是提交ID

$ git blame my-file.txt
65126918 (David Pärsson 2013-07-22 12:53:02 +0200 1) Heading
c6e6d36d (David Pärsson 2013-07-22 12:53:10 +0200 2) =======
65126918 (David Pärsson 2013-07-22 12:53:02 +0200 3) 
13e293e3 (David Pärsson 2013-07-22 12:49:33 +0200 4) Text on first line
8b3d2e15 (David Pärsson 2013-07-22 12:49:49 +0200 5) Text on second line
13e293e3 (David Pärsson 2013-07-22 12:49:33 +0200 6) Text on third line

您可以通过提供修订版本来查看最后修改之后的内容,例如:
$ git blame 8b3d2e15 my-file.txt

您可以使用-L参数来选择特定的行,例如: 选择特定行数的命令如下:
$ git blame my-file.txt -L 4,+3
13e293e3 (David Pärsson 2013-07-22 12:49:33 +0200 4) Text on first line
8b3d2e15 (David Pärsson 2013-07-22 12:49:49 +0200 5) Text on second line
13e293e3 (David Pärsson 2013-07-22 12:49:33 +0200 6) Text on third line

更多细节和巧妙技巧可以在git-blame手册页面上找到。


1
你也可以指定修订版本,即不仅仅是修改了每行的最后一个提交。 - the.malkolm
3
不要忘记加上-L100,+10选项,可以从第100行开始往下10行进行追踪,或者使用-L/void foo/,+10选项,可以从函数foo被定义的位置往下10行进行追踪。 - sehe

3
请看这篇简短的教程:http://zsoltfabok.com/blog/2012/02/git-blame-line-history/
它基本上通过结合git blamegit show来查看哪些提交更改了特定行(如David Parsson的答案中已经建议的那样使用git blame),以及如何更改该行(git show <commit-id>)。所以,交替执行git blame <commit-id> git show <commit-id>将为您提供文件特定行的完整历史记录。
还要记得在怀疑某一行从其他文件复制而来时使用git blame -M。从https://www.kernel.org/pub/software/scm/git/docs/git-blame.html获取更多信息。

-M |num|
检测文件中已移动或已复制的行。当一个提交移动或者复制一段代码时(例如原始文件有A和B,而提交将其更改为B和A),传统的责怪算法只会注意到移动的一半并且通常会将被移动的行(即B)归咎于父提交,并将责任归咎于被移动的行(即A)是子提交。使用此选项,通过运行额外的检查步骤,父级对文件中这两组行都有责任。

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


2

实际上,Git带有一个精美的GUI界面,使得轻松地在时间线上前后跳转以查看特定行的变化成为可能。尝试使用:

git gui blame <file>

您可以点击链接旁边的修订版本来“穿越时光”。

2

git blame <file> -L <line>,<line>


1
我觉得你需要使用 git blame 命令,它可以告诉你每一行是哪个提交添加的。因此,请运行 git blame 包含该行的文件名.txt,并跳转到第100行,它会告诉你添加该行的提交(以及何时提交以及由谁提交)。

-2

使用git blame命令来实现

看看是否有效

NAME
       git-blame - Show what revision and author last modified each line of a file

SYNOPSIS
       git blame [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-e] [-p] [-w] [--incremental] [-L n,m]
                   [-S <revs-file>] [-M] [-C] [-C] [-C] [--since=<date>] [--abbrev=<n>]
                   [<rev> | --contents <file> | --reverse <rev>] [--] <file>

DESCRIPTION
       Annotates each line in the given file with information from the revision which last modified the line. Optionally, start annotating from the given revision.

已经建议了三次,这不是 OP 寻找的。 - krlmlr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接