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

就像git blame,但git blame会显示触及特定行的LAST commit。

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


当前回答

请参见Git:发现哪些提交曾经接触过一系列行。


从Git 1.8.4开始,Git log有-L来查看行范围的演变。

例如,假设您查看git blame的输出。这里- l150,+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表示“跟踪文件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)

其他回答

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

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”修改为行号,将“/to/file”修改为文件路径。

简化@matt的回答-

get - l14,15——<file_path>

这里你会看到第14行到第15行。

因为-L选项需要Range作为参数,我们不能使用-L选项获得单行的责备。

参考

这将调用git blame为每一个有意义的修订显示line $ line文件$ file:

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

像往常一样,责备在每行开头显示修订号。你可以添加

| sort | uniq -c

要获得聚合结果,可以使用更改这一行的提交列表之类的东西。(不完全是,如果代码只是被移动了,这可能会对行中不同的内容显示相同的提交ID两次。为了进行更详细的分析,您必须对相邻提交的git blame结果进行滞后比较。有人知道吗?)

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

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.3上,它不支持“git blame -L”中的正则表达式。 (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>"

当然,这可以被做成一个脚本或一个函数。