Git – 如何查看方法/函数的更改历史logging?

所以我发现如何查看一个文件的变化历史的问题,但是这个特定文件的变化历史是巨大的,我真的只对特定方法的变化感兴趣。 那么有可能只看到特定方法的变化历史?

我知道这将需要git来分析代码,并且分析对于不同的语言是不同的,但是方法/函数声明在大多数语言中看起来非常相似,所以我想也许有人实现了这个function。

我目前使用的语言是Objective-C,而我目前使用的SCM是git,但是我想知道这个function是否存在于任何SCM /语言中。

最近版本的git log学习了-L参数的特殊forms:

-L:<funcname>:<file>

跟踪<file>"<start>,<end>" (或函数名称regex <funcname> )给出的行范围的演变。 你不能给任何pathpec限制。 这目前仅限于从单一修订开始,也就是说,您可能只给出零个或一个正面的修订参数。 您可以多次指定此选项。

如果给出“:<funcname>”来代替<start><end> ,它是一个正则expression式,表示从匹配<funcname>第一个funcname行到下一个funcname行的范围。 “:<funcname>”从前一个-L范围的末尾进行search(如果有的话),否则从文件开头search。 “^:<funcname>”从文件开头search。

换句话说,如果您要求Git将git log -L :myfunction:path/to/myfile.cgit log -L :myfunction:path/to/myfile.c ,它现在可以愉快地打印该函数的更改历史logging。

使用git gui blame很难在脚本中使用,而当git log -Ggit log --pickaxe都可以在方法定义出现或消失时显示出来,我还没有find任何方法让它们列出所有的变化使你的方法的身体

但是,您可以使用gitattributestextconv属性来拼凑一个解决scheme。 尽pipe这些function最初是为了帮助您处理二进制文件,但它们在这里也能正常工作。

关键是在执行任何diff操作之前,让Git从文件中除去所有感兴趣的行。 然后, git loggit diff等将只能看到你感兴趣的区域。

以下是我用另一种语言做的事情的概要; 你可以根据自己的需要调整它。

  • 编写一个简短的shell脚本(或其他程序),它接受一个参数 – 一个源文件的名称 – 并只输出该文件的有趣部分(或者没有任何有趣的部分)。 例如,你可以使用sed如下:

     #!/bin/sh sed -n -e '/^int my_func(/,/^}/ p' "$1" 
  • 为您的新脚本定义一个Git textconvfilter。 (有关更多详细信息,请参阅gitattributes手册页。)filter的名称和命令的位置可以是任何您喜欢的。

     $ git config diff.my_filter.textconv /path/to/my_script 
  • 告诉Git在计算文件差异之前使用该filter。

     $ echo "my_file diff=my_filter" >> .gitattributes 
  • 现在,如果你使用-G. (注意. )列出所有在应用filter时产生可见变化的提交,你将会有那些你感兴趣的提交。任何其他使用Git的diff例程的选项,比如--patch ,也将得到这个受限的观点。

     $ git log -G. --patch my_file 
  • 瞧!

您可能想要做的一个有用的改进是让您的filter脚本将方法名称作为其第一个参数(并将文件作为其第二个参数)。 这让你只需调用git config指定一个感兴趣的新方法,而不必编辑你的脚本。 例如,你可能会说:

 $ git config diff.my_filter.textconv "/path/to/my_command other_func" 

当然,filter脚本可以做任何你喜欢的事情,拿出更多的参数,或者其他任何东西:除了我在这里展示的东西之外,还有很多的灵活性。

git log有一个选项'-G'可以用来查找所有的差异。

-G查找添加或删除的行与给定的<regex>匹配的区别。

只要给它一个你关心的函数名称的正确的正则expression式。 例如,

 $ 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 

你可以做的最接近的事情是确定你的函数在文件中的位置(例如说你的函数i_am_buggyfoo/bar.c ),然后运行一下以下内容:

 git log -p -L 200,300:foo/bar.c 

这将打开更less(或等效的寻呼机)。 现在你可以input/i_am_buggy (或者你的寻呼机等价物)并开始逐步完成这些变化。

这甚至可以工作,这取决于你的代码风格:

 git log -p -L /int i_am_buggy\(/,+30:foo/bar.c 

这将search从正则expression式(理想的是你的函数声明)的第一个命中限制到之后的三十行。 最后的参数也可以是一个正则expression式,虽然检测与正则expression式是一个更有说服力的命题。

git blame显示你最后一次更改文件的每一行; 您可以指定要检查的行,以避免在函数之外获取行的历史logging。