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

时间:2011-12-08 17:51:48

标签: git

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

git blame类似,但git blame会向您显示触及特定行的最后一次提交。

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

11 个答案:

答案 0 :(得分:530)

另见Git: discover which commits ever touched a range of lines


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

例如,假设您查看git blame的输出。这里-L 150,+11表示"只看150到150 + 11"

$ git blame -L 150,+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表示&#34;跟踪名为git-web--browse.sh&#34;的文件中第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)

答案 1 :(得分:61)

您可以使用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

答案 2 :(得分:35)

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

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

所以,在你的情况下upperLimit&amp; lowerLimit是受到感动的line_number

更多信息 - https://www.techpurohit.com/list-some-useful-git-commands

答案 3 :(得分:13)

一种非常简单的方法是使用vim-fugitive。只需在vim中打开文件,选择您对V感兴趣的行,然后输入

:Glog

现在,您可以使用:cnext:cprev查看修改该行的文件的所有修订版。在任何时候,请输入:Gblame以查看sha,作者和日期信息。

答案 4 :(得分:9)

我不相信这有任何内置的东西。由于在没有文件的其余部分发生重大变化的情况下,单行更改几次很少见,所以你很容易因为行号变化而变得很多。

如果你足够幸运,该行总是具有某些识别特征,例如:对名称从未更改的变量的赋值,您可以使用git blame -L的正则表达式选项。例如:

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

但是这只能找到该正则表达式的第一个匹配,所以如果你没有一个很好的匹配线的方法,那就不太有用了。

我想你可以解决一些问题。我现在没有时间写出代码,但......就这些问题做了些什么。运行git blame -n -L $n,$n $file。第一个字段是先前提交的提交,第二个字段是提交的行号,因为它可能已更改。抓住这些,然后运行git blame -n $n,$n $commit^ $file,即从最后一次更改文件之前的提交开始。

(请注意,如果最后一次更改行的提交是合并提交,则会失败。如果在合并冲突解决方案中更改了行,则可能会发生这种情况。)

编辑:我今天从2011年3月开始this mailing list post发生了tig,其中提到git gui和{{1}}有一项功能可以帮助您完成此任务。看起来git本身已经考虑了这个功能,但还没有完成。

答案 5 :(得分:9)

简化@ matt的回答 -

git blame -L14,15 -- <file_path>

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

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

Reference

答案 6 :(得分:6)

这会调用git blame 每个有意义的修订,以显示文件$LINE的第$FILE行:

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

与往常一样,责备显示每行开头的修订号。你可以追加

| sort | uniq -c

获取聚合结果,类似于更改此行的提交列表。 (不完全是,如果代码只是被移动了,这可能会为该行的不同内容显示两次相同的提交ID。对于更详细的分析,您必须对git blame结果进行滞后比较。相邻提交。任何人?)

答案 7 :(得分:6)

这是一个定义git别名的解决方案,因此您可以像这样使用它:

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

这是一个丑陋的单行,所以这里是一个去混淆的等效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
}

pickaxe解决方案( git log --pickaxe-regex -S'REGEX' )只会为您提供行添加/删除,而不是该行的其他更改包含正则表达式。

此解决方案的限制是 git blame 仅返回第一个REGEX匹配,因此如果存在多个匹配,则递归可以“跳转”以跟随另一行。请务必检查完整的历史记录输出以发现这些“跳转”,然后修复您的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

答案 8 :(得分:2)

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

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

Oneliner:

{{1}}

当然可以将其制作成脚本或函数。

答案 9 :(得分:1)

您可以混合使用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); }'

答案 10 :(得分:0)

如果行的位置(行号)在文件的历史记录中保持不变,则会在每次提交时向您显示行的内容:

git log --follow --pretty=format:"%h" -- 'path/to/file' | while read -r hash; do echo $hash && git show $hash:'path/to/file' | head -n 544 | tail -n1; done

544更改为行号,将path/to/file更改为文件路径。