因此,我发现了一个有关如何查看文件更改历史记录的问题,但是此特定文件的更改历史记录非常庞大,我实际上只对特定方法的更改感兴趣。那么是否有可能仅查看该特定方法的更改历史记录?
我知道这将需要git来分析代码,并且对于不同的语言,分析也会有所不同,但是在大多数语言中,方法/函数的声明看起来非常相似,所以我认为也许有人实现了此功能。
我目前使用的语言是Objective-C,而我目前使用的SCM是git,但是我想知道此功能是否适用于任何SCM /语言。
因此,我发现了一个有关如何查看文件更改历史记录的问题,但是此特定文件的更改历史记录非常庞大,我实际上只对特定方法的更改感兴趣。那么是否有可能仅查看该特定方法的更改历史记录?
我知道这将需要git来分析代码,并且对于不同的语言,分析也会有所不同,但是在大多数语言中,方法/函数的声明看起来非常相似,所以我认为也许有人实现了此功能。
我目前使用的语言是Objective-C,而我目前使用的SCM是git,但是我想知道此功能是否适用于任何SCM /语言。
Answers:
最新版本git log
学习了-L
参数的特殊形式:
-L:<函数名>:<文件>
追踪内
"<start>,<end>"
(或函式名称regex<funcname>
)所指定行范围的演变<file>
。您不得提供任何pathspec限制器。当前,这仅限于从单个修订版开始的遍历,即,您只能给出零个或一个正修订版参数。您可以多次指定此选项。
...
如果“:<funcname>”
代替<start>
和给出<end>
,则它是一个正则表达式,表示从匹配的第一个funcname行<funcname>
到下一个funcname行的范围。“:<funcname>”
从上一个-L
范围的末尾(如果有)搜索,否则从文件的开头搜索。“^:<funcname>”
从文件开头搜索。
换句话说:如果您要求Git to git log -L :myfunction:path/to/myfile.c
,它将立即愉快地打印该功能的更改历史记录。
使用git gui blame
难以利用的脚本,并同时git log -G
和git log --pickaxe
可以各自显示您何时该方法的定义出现或消失,我还没有找到任何办法使它们列出来所做的所有更改身体的方法。
但是,您可以使用gitattributes
和textconv
属性组合实现此目的的解决方案。尽管这些功能最初是为了帮助您使用二进制文件,但它们在这里同样适用。
关键是让Git从文件中删除所有您感兴趣的行,然后再执行任何diff操作。然后git log
,,git diff
等只会看到您感兴趣的区域。
这是我用另一种语言所做的工作的概述;您可以根据自己的需要进行调整。
编写一个简短的shell脚本(或其他程序),该脚本带有一个参数(源文件的名称),并且仅输出该文件的有趣部分(如果没有有趣的部分,则不输出)。例如,您可以使用sed
以下方式:
#!/bin/sh
sed -n -e '/^int my_func(/,/^}/ p' "$1"
textconv
为新脚本定义一个Git 过滤器。(有关gitattributes
更多详细信息,请参见手册页。)过滤器的名称和命令的位置可以是您喜欢的任何内容。
$ git config diff.my_filter.textconv /path/to/my_script
告诉Git在计算有问题的文件的差异之前使用该过滤器。
$ echo "my_file diff=my_filter" >> .gitattributes
现在,如果您使用-G.
(请注意.
)列出所有在应用过滤器时会产生可见变化的提交,那么您将拥有您感兴趣的那些提交。其他使用Git diff例程的其他选项,例如--patch
,将也得到这个受限的视图。
$ git log -G. --patch my_file
瞧!
您可能想做的一个有用的改进是让过滤器脚本将方法名称作为第一个参数(将文件作为第二个参数)。这样,您只需调用即可指定一种新的感兴趣的方法git config
,而不必编辑脚本。例如,您可能会说:
$ git config diff.my_filter.textconv "/path/to/my_command other_func"
当然,筛选器脚本可以执行您喜欢的任何操作,接受更多参数或执行其他操作:除了我在此处显示的内容以外,还有很多灵活性。
git log有一个选项-G可以用来找到所有差异。
-G查找添加或删除的行与给定的匹配的差异
<regex>
。
只需为其提供您所关心的函数名称的正则表达式即可。例如,
$ git log --oneline -G'^int commit_tree'
40d52ff make commit_tree a library function
81b50f3 Move 'builtin-*' into a 'builtin/' subdirectory
7b9c0a6 git-commit-tree: make it usable from other builtins
--oneline
为-p
您可以做的最接近的事情是确定函数在文件中的位置(例如,说您的函数i_am_buggy
在的第241-263行foo/bar.c
),然后执行以下操作:
git log -p -L 200,300:foo/bar.c
这将打开较少(或等效的寻呼机)。现在,您可以输入/i_am_buggy
(或与您的寻呼机等效)并开始逐步进行更改。
这甚至可能有效,具体取决于您的代码样式:
git log -p -L /int i_am_buggy\(/,+30:foo/bar.c
这将搜索从该正则表达式的第一次匹配(最好是您的函数声明)搜索到其后的三十行。结束参数也可以是一个正则表达式,尽管检测的是与正则表达式的是iffier命题。
-L ":int myfunc:foo/bar.c"
并限制使用该名称的函数即可。这太棒了-感谢您的指导!现在,如果仅功能检测更加可靠...
正确的方法是git log -L :function:path/to/file
按照eckes答案中的说明使用。
但是此外,如果您的函数很长,那么对于每个可能仅涉及这些行之一的提交,您可能只想查看各种提交所引入的更改,而不是整个函数行(包括未修改的)。像平常一样diff
。
通常git log
可以查看与的差异-p
,但这不适用于-L
。因此,您grep
git log -L
只需要显示涉及的行和commits / files标头即可将它们上下文化。这里的窍门是只匹配终端彩色线,并--color
使用正则表达式添加开关。最后:
git log -L :function:path/to/file --color | grep --color=never -E -e "^(^[\[[0-9;]*[a-zA-Z])+" -3
请注意,它^[
应该是实际的,字面的^[
。您可以通过按bash中的^ V ^ [来键入它们,即Ctrl+ V,Ctrl+ [。参考这里。
也是最后一个-3
开关,允许在每条匹配的行之前和之后打印3行输出上下文。您可能需要对其进行调整。
显示函数历史与git log -L :<funcname>:<file>
作为表现出eckes的回答和git的文档
如果未显示任何内容,请参阅定义自定义的粗体标题,*.java diff=java
以在.gitattributes
文件中添加类似内容以支持您的语言。
显示提交之间的函数历史 git log commit1..commit2 -L :functionName:filePath
显示重载的函数历史记录(可能有许多具有相同名称但具有不同参数的函数) git log -L :sum\(double:filepath