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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8435343/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 12:27:11  来源:igfitidea点击:

Retrieve the commit log for a specific line in a file?

git

提问by jrochkind

Is there any way to get git to give you a commit log for just commits that touched a particular linein a file?

有什么方法可以让 git 为您提供一个提交日志,仅用于触及文件中特定的提交?

Like git blame, but git blamewill show you the LAST commit that touched a particular line.

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

I'd really like to get a similar log of, not the list of commits to anywhere in the file, but just the commits that touched a particular line.

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

回答by Matt McClure

See also Git: discover which commits ever touched a range of lines.

另请参阅Git:发现哪些提交触及了一系列行



Since Git 1.8.4, git loghas -Lto view the evolution of a range of lines.

自 Git 1.8.4 以来git log必须-L查看一系列行的演变。

For example, suppose you look at git blame's output. Here -L 150,+11means "only look at the lines 150 to 150+11":

例如,假设您查看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 "$@" &

And you want to know the history of what is now line 155.

你想知道现在第 155 行的历史。

Then, use git log. Here, -L 155,155:git-web--browse.shmeans "trace the evolution of lines 155 to 155 in the file named git-web--browse.sh".

然后,使用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 <[email protected]>

    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 <[email protected]>

    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 <[email protected]>

    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)

回答by Adam Dymitruk

You can get a set of commits by using pick-axe.

您可以使用pick-axe 获取一组提交。

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

This will give you all of the commits that affected that text in that file. If the file was renamed at some point, you can add --follow-parent.

这将为您提供影响该文件中该文本的所有提交。如果文件在某个时候被重命名,您可以添加 --follow-parent。

If you would like to inspect the commits at each of these edits, you can pipe that result to git show:

如果您想在每次编辑时检查提交,您可以将该结果通过管道传输到 git show:

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

回答by jitendrapurohit

Try using below command implemented in Git 1.8.4.

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

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

So, in your case upperLimit& lowerLimitis the touched line_number

所以,在你的情况下upperLimit&lowerLimit是被感动的line_number

More info - https://www.techpurohit.com/list-some-useful-git-commands

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

回答by Cory Klein

An extremely easy way to do this is by using vim-fugitive. Just open the file in vim, select the line(s) you're interested in using V, then enter

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

:Glog

Now you can use :cnextand :cprevto see all the revisions of the file where that line is modified. At any point, enter :Gblameto see the sha, author, and date info.

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

回答by Swaps

Simplifying @matt's answer -

简化@matt 的回答 -

git blame -L14,15 -- <file_path>

git blame -L14,15 -- <file_path>

Here you will get a blame for a lines 14 to 15.

在这里,您将因台词而受到责备14 to 15

Since -Loption expects Rangeas a param we can't get a Blamefor a single line using the -Loption`.

由于-Loption 需要Range作为参数,我们无法Blame使用-Loption`获得单行的a

Reference

参考

回答by Cascabel

I don't believe there's anything built-in for this. It's made tricky by the fact that it's rare for a single line to change several times without the rest of the file changing substantially too, so you'll tend to end up with the line numbers changing a lot.

我不相信有任何内置的东西。由于很少有一行更改多次而文件的其余部分也没有实质性更改,因此您往往会最终导致行号发生很大变化,因此这很棘手。

If you're lucky enough that the line always has someidentifying characteristic, e.g. an assignment to a variable whose name never changed, you could use the regex choice for git blame -L. For example:

如果您足够幸运,该行始终具有某些识别特征,例如分配给名称从未改变的变量,您可以使用正则表达式选择git blame -L. 例如:

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

But this only finds the firstmatch for that regex, so if you don't have a good way of matching the line, it's not too helpful.

但这只能找到该正则表达式的第一个匹配项,因此如果您没有匹配该行的好方法,它就没有太大帮助。

You could hack something up, I suppose. I don't have time to write out code just now, but... something along these lines. Run git blame -n -L $n,$n $file. The first field is the previous commit touched, and the second field is the line number in thatcommit, since it could've changed. Grab those, and run git blame -n $n,$n $commit^ $file, i.e. the same thing starting from the commit before the last time the file was changed.

你可以破解一些东西,我想。我现在没有时间写出代码,但是......一些类似的东西。运行git blame -n -L $n,$n $file。第一场是上一次提交感动,第二场是行号提交,因为它可能已经改变。抓住这些,然后运行git blame -n $n,$n $commit^ $file,即从上次更改文件之前的提交开始的相同内容。

(Note that this will fail you if the last commit that changed the line was a merge commit. The primary way this could happen if the line was changed as part of a merge conflict resolution.)

(请注意,如果更改该行的最后一次提交是合并提交,则这将使您失败。如果该行作为合并冲突解决方案的一部分更改,则可能发生这种情况的主要方式。)

Edit: I happened across this mailing list postfrom March 2011 today, which mentions that tigand git guihave a feature that will help you do this. It looks like the feature has been considered, but not finished, for git itself.

编辑:我从 2011 年 3 月今天偶然发现了这个邮件列表帖子,其中提到了这一点,tig并且git gui有一个功能可以帮助你做到这一点。对于 git 本身,似乎已经考虑了该功能,但尚未完成。

回答by krlmlr

This will call git blamefor everymeaningful revision to show line $LINEof file $FILE:

这将调用git blame每一个有意义的修订秀行$LINE的文件$FILE

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

As usual, the blame shows the revision number in the beginning of each line. You can append

像往常一样,blame 在每一行的开头显示修订号。你可以附加

| sort | uniq -c

to get aggregated results, something like a list of commits that changed this line. (Not quite, if code only has been moved around, this might show the same commit ID twice for different contents of the line. For a more detailed analysis you'd have to do a lagged comparison of the git blameresults for adjacent commits. Anyone?)

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

回答by Lucas Cimon

Here is a solution that defines a git alias, so you will be able use it like that :

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

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

Output example :

输出示例:

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

You can define the alias in your .gitconfigor simply run the following command

您可以在.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

This is an ugly one-liner, so here is a de-obfuscated equivalent bash function :

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

The pickaxe solution ( git log --pickaxe-regex -S'REGEX') will only give you line additions/deletions, not the other alterations of the line containing the regular expression.

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

A limitation of this solution is that git blameonly returns the 1st REGEX match, so if multiple matches exist the recursion may "jump" to follow another line. Be sure to check the full history output to spot those "jumps" and then fix your REGEX to ignore the parasite lines.

此解决方案的一个限制是git blame仅返回第一个 REGEX 匹配项,因此如果存在多个匹配项,则递归可能会“跳转”以跟随另一行。请务必检查完整的历史输出以发现那些“跳跃”,然后修复您的 REGEX 以忽略寄生线。

Finally, here is an alternate version that run git showon each commit to get the full diff :

最后,这是一个替代版本,它在每次提交时运行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

回答by cserpell

You can mix git blameand git logcommands to retrieve the summary of each commit in the git blame command and append them. Something like the following bash + awk script. It appends the commit summary as code comment inline.

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

git blame FILE_NAME | awk -F" " \
'{
   commit = substr(
git blame FILE_NAME | awk -F" " '{ commit = substr(
myfile=haproxy.cfg
git rev-list HEAD -- $myfile | while read i
do
    git diff -U0 ${i}^ $i $myfile | sed "s/^/$i /"
done | grep "<sometext>"
, 0, 8); if (!a[commit]) { query = "git log --oneline -n 1 " commit " --"; (query | getline a[commit]); } print
myfile=<myfile> ; git rev-list HEAD -- $myfile | while read i; do     git diff -U0 ${i}^ $i $myfile | sed "s/^/$i /"; done | grep "<sometext>"
" // " substr(a[commit], 9); }'
, 0, 8); if (!a[commit]) { query = "git log --oneline -n 1 " commit " --"; (query | getline a[commit]); } print ##代码## " // " substr(a[commit], 9); }'

In one line:

在一行中:

##代码##

回答by sastorsl

In my case the line number had changed a lot over time. I was also on git 1.8.3 which does not support regex in "git blame -L". (RHEL7 still has 1.8.3)

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

##代码##

Oneliner:

单线:

##代码##

This can of course be made into a script or a function.

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