检索文件中特定行的提交日志?

有没有办法让git给你一个提交日志只是提交,触及文件中的一个特定的

git blame ,但git blame会告诉你最后的承诺,触及一个特定的行。

我真的想得到一个类似的日志,而不是提交到文件中的任何地方的列表,而只是触及特定行的提交。

另请参阅Git:了解哪些提交触及了一系列的行 。


由于Git 1.8.4 , git log-L来查看一系列行的演变。

例如,假设你看看git blame的输出。 这里-L150,+11意思是“只看150到150 + 11行”:

 $ git blame -L150,+11 -- git-web--browse.sh a180055a git-web--browse.sh (Giuseppe Bilotta 2010-12-03 17:47:36 +0100 150) die "The browser $browser is not a180055a git-web--browse.sh (Giuseppe Bilotta 2010-12-03 17:47:36 +0100 151) fi 5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 152) fi 5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 153) 5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 154) case "$browser" in 81f42f11 git-web--browse.sh (Giuseppe Bilotta 2010-12-03 17:47:38 +0100 155) firefox|iceweasel|seamonkey|iceape) 5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 156) # Check version because firefox < 2.0 do 5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 157) vers=$(expr "$($browser_path -version)" 5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 158) NEWTAB='-new-tab' 5d6491c7 git-browse-help.sh (Christian Couder 2007-12-02 06:07:55 +0100 159) test "$vers" -lt 2 && NEWTAB='' a0685a4f git-web--browse.sh (Dmitry Potapov 2008-02-09 23:22:22 -0800 160) "$browser_path" $NEWTAB "$@" & 

而且你想知道现在155线的历史。

然后,使用git log 。 这里, -L 155,155:git-web--browse.sh意思是“在名为git-web--browse.sh的文件中跟踪155行到155行的演变”。

 $ git log --pretty=short -u -L 155,155:git-web--browse.sh commit 81f42f11496b9117273939c98d270af273c8a463 Author: Giuseppe Bilotta <giuseppe.bilotta@gmail.com> web--browse: support opera, seamonkey and elinks diff --git a/git-web--browse.sh b/git-web--browse.sh --- a/git-web--browse.sh +++ b/git-web--browse.sh @@ -143,1 +143,1 @@ -firefox|iceweasel) +firefox|iceweasel|seamonkey|iceape) commit a180055a47c6793eaaba6289f623cff32644215b Author: Giuseppe Bilotta <giuseppe.bilotta@gmail.com> web--browse: coding style diff --git a/git-web--browse.sh b/git-web--browse.sh --- a/git-web--browse.sh +++ b/git-web--browse.sh @@ -142,1 +142,1 @@ - firefox|iceweasel) +firefox|iceweasel) commit 5884f1fe96b33d9666a78e660042b1e3e5f9f4d9 Author: Christian Couder <chriscool@tuxfamily.org> Rename 'git-help--browse.sh' to 'git-web--browse.sh'. diff --git a/git-web--browse.sh b/git-web--browse.sh --- /dev/null +++ b/git-web--browse.sh @@ -0,0 +127,1 @@ + firefox|iceweasel) 

你可以通过使用pick-ax来获得一组提交。

 git log -S'the line from your file' -- path/to/your/file.txt 

这会给你所有影响该文件中的文本的提交。 如果文件在某个时候被重命名,则可以添加 – follow-parent。

如果您想在每个编辑中检查提交,可以将结果传送给git show:

 git log ... | xargs -n 1 git show 

尝试使用在Git 1.8.4中实现的以下命令。

 git log --pretty=short -u -L <upperLimit>,<lowerLimit>:<path_to_filename> 

所以,在你的情况lowerLimitlowerLimit是触及的line_number

我不相信这有什么内置的。 由于事实上很less有一条线改变几次,而文件的其余部分实际上并没有太大的改变,所以你会倾向于最后的行号改变很多。

如果你足够幸运的话,那么这个行总是有一些识别特征,例如一个名字从未改变过的variables的赋值,你可以使用git blame -L的正则expression式。 例如:

 git blame -L '/variable_name *= */',+1 

但是这只能find该正则expression式的第一个匹配项,所以如果你没有一个好的方法来匹配这个行,那么这个方法不是很有帮助。

我想,你可以把事情搞砸了。 我现在没有时间写出代码,但是……沿着这些方向。 运行git blame -n -L $n,$n $file 。 第一个字段是之前提交的提交,第二个字段是该提交中的行号,因为它可能已经更改。 抓住这些,然后运行git blame -n $n,$n $commit^ $file ,也就是从最后一次文件更改前的提交开始。

(请注意,如果最后一次提交改变行是一个合并提交,这将会失败。如果该行作为合并冲突解决scheme的一部分进行更改,则会发生这种情况。

编辑:我从2011年3月发生在这个邮件列表post ,提到tiggit gui有一个function,将帮助你做到这一点。 它看起来像function已经考虑,但没有完成,git本身。

一个非常简单的方法来做到这一点是通过使用vim-逃亡 。 只需在vim中打开文件,使用Vselect你感兴趣的行,然后input

 :Glog 

现在可以使用:cnext:cprev来查看修改了该行的文件的所有修订版本。 在任何时候,input:Gblame查看sha,作者和date信息。

这将调用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结果的滞后比较。任何人?)

这是一个定义git别名的解决scheme,所以你可以像这样使用它:

 git rblame -M -n -L '/REGEX/,+1' FILE 

输出示例:

 00000000 18 (Not Committed Yet 2013-08-19 13:04:52 +0000 728) fooREGEXbar 15227b97 18 (User1 2013-07-11 18:51:26 +0000 728) fooREGEX 1748695d 23 (User2 2013-03-19 21:09:09 +0000 741) REGEXbar 

您可以在.gitconfig中定义别名,或者只需运行以下命令

 git config alias.rblame !sh -c 'while line=$(git blame "$@" $commit 2>/dev/null); do commit=${line:0:8}^; [ 00000000^ == $commit ] && commit=$(git rev-parse HEAD); echo $line; done' dumb_param 

这是一个丑陋的单线程,所以这里是一个de-obfuscated等价的bash函数:

 git-rblame () { local commit line while line=$(git blame "$@" $commit 2>/dev/null); do commit="${line:0:8}^" if [ "00000000^" == "$commit" ]; then commit=$(git rev-parse HEAD) fi echo $line done } 

镐解决scheme( git log –pickaxe-regex -S'REGEX )只会给你添加/删除行,而不是包含正则expression式的行的其他更改。

这个解决scheme的限制是git blame只返回第一个REGEX匹配,所以如果存在多个匹配,recursion可能会“跳转”到另一行。 一定要检查完整的历史输出,以发现这些“跳跃”,然后修复您的REGEX忽略寄生虫线。

最后,这是一个替代版本,在每次提交时运行git show以获得完整的差异:

 git config alias.rblameshow !sh -c 'while line=$(git blame "$@" $commit 2>/dev/null); do commit=${line:0:8}^; [ 00000000^ == $commit ] && commit=$(git rev-parse HEAD); git show $commit; done' dumb_param 

在我的情况下,行号随着时间的推移已经发生了很大的变化 我也在git 1.8.3上,它不支持“git blame -L”中的正则expression式。 (RHEL7还有1.8.3)

 myfile=haproxy.cfg git rev-list HEAD -- $myfile | while read i do git diff -U0 ${i}^ $i $myfile | sed "s/^/$i /" done | grep "<sometext>" 

Oneliner:

 myfile=<myfile> ; git rev-list HEAD -- $myfile | while read i; do git diff -U0 ${i}^ $i $myfile | sed "s/^/$i /"; done | grep "<sometext>" 

这当然可以做成一个脚本或一个function。

您可以混合使用git blamegit log命令来检索git blame命令中的每个提交的摘要并追加它们。 像下面的bash + awk脚本。 它将提交摘要作为代码注释内联。

 git blame FILE_NAME | awk -F" " \ '{ commit = substr($0, 0, 8); if (!a[commit]) { query = "git log --oneline -n 1 " commit " --"; (query | getline a[commit]); } print $0 " // " substr(a[commit], 9); }' 

在一行中:

 git blame FILE_NAME | awk -F" " '{ commit = substr($0, 0, 8); if (!a[commit]) { query = "git log --oneline -n 1 " commit " --"; (query | getline a[commit]); } print $0 " // " substr(a[commit], 9); }' 

简化@马特的答案 –

git blame -L14,15 -- <file_path>

在这里你会得到一个14 to 15行的责备。

由于-L选项需要Range作为参数,因此我们无法使用-L选项获取单行的责备

参考