Git - 如何查看方法/函数的更改历史记录?

Eri*_*k B 81 git methods history function objective-c

所以我找到了关于如何查看文件的更改历史记录的问题,但是这个特定文件的更改历史记录很大,我真的只对特定方法的更改感兴趣.那么就可以看到该特定方法的变更历史吗?

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

我目前使用的语言是Objective-C,我目前使用的SCM是git,但我很想知道这个功能是否适用于任何SCM /语言.

eck*_*kes 78

最近版本git log学习了一个特殊形式的-L参数:

-L:<funcname>:<file>

跟踪由"<start>,<end>"(或函数名称正则表达式<funcname>)给出的行范围的演变<file>.你可能不会给任何pathpec限制器.目前这仅限于从单个修订开始的步行,即,您可能只提供零个或一个正修订参数.您可以多次指定此选项.
...
如果“:<funcname>”代替<start><end>,则它是一个正则表达式,表示从匹配的第一个funcname行<funcname>到下一个funcname行的范围.“:<funcname>”从上一个-L范围的末尾搜索(如果有的话),否则从文件的开头搜索.“^:<funcname>”从文件的开头搜索.

换句话说:如果你问Git git log -L :myfunction:path/to/myfile.c,它现在可以愉快地打印该函数的更改历史记录.

  • 这可能适用于Objective-c开箱即用,但如果您正在为其他语言(例如Python,Ruby等)执行此操作,则可能需要在.gitattributes文件中添加适当的配置,以便git识别函数/方法用这种语言的声明.对于python使用*.py diff = python,对于ruby使用*.rb diff = ruby (11认同)
  • git 如何追踪函数? (3认同)
  • @nn0p 我假设拥有多种语言的语法知识,从而知道如何隔离函数并跟踪她的更改。 (2认同)
  • 扩展@samaspin的注释,对于其他语言,您可以在此处参考文档:https://git-scm.com/docs/gitattributes#_generating_diff_text (2认同)

Pau*_*ker 16

使用git gui blame很难在脚本中使用,虽然git log -G并且git log --pickaxe每个都可以在方法定义出现或消失时向您显示,但我没有找到任何方法使它们列出对方法主体所做的所有更改.

但是,您可以使用gitattributestextconv属性拼凑一个解决方案.虽然这些功能最初旨在帮助您使用二进制文件,但它们在这里也可以正常工作.

关键是在执行任何差异操作之前让Git从文件中除去你感兴趣的所有行.然后git log,git diff等等只会看到您感兴趣的区域.

这是我用另一种语言做的概述; 你可以根据自己的需要调整它.

  • 编写一个简短的shell脚本(或其他程序),它接受一个参数 - 源文件的名称 - 并仅输出该文件的有趣部分(如果没有任何有趣的话,则不输出任何内容).例如,您可以使用sed如下:

    #!/bin/sh
    sed -n -e '/^int my_func(/,/^}/ p' "$1"
    
    Run Code Online (Sandbox Code Playgroud)
  • textconv为新脚本定义Git 过滤器.(有关gitattributes详细信息,请参见手册页.)过滤器的名称和命令的位置可以是您喜欢的任何内容.

    $ git config diff.my_filter.textconv /path/to/my_script
    
    Run Code Online (Sandbox Code Playgroud)
  • 在计算相关文件的差异之前,告诉Git使用该过滤器.

    $ echo "my_file diff=my_filter" >> .gitattributes
    
    Run Code Online (Sandbox Code Playgroud)
  • 现在,如果您使用-G.(注意.)列出在应用过滤器时产生可见更改的所有提交,您将拥有您感兴趣的那些提交.使用Git的diff例程的任何其他选项,例如--patch,也得到这种限制的观点.

    $ git log -G. --patch my_file
    
    Run Code Online (Sandbox Code Playgroud)
  • 瞧!

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

$ git config diff.my_filter.textconv "/path/to/my_command other_func"
Run Code Online (Sandbox Code Playgroud)

当然,过滤器脚本可以做任何你喜欢的事情,采取更多的参数,或者其他:除了我在这里展示的内容之外,还有很多灵活性.


lht*_*lht 11

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
Run Code Online (Sandbox Code Playgroud)

  • 我没有运行命令,但看起来像这个命令只会显示触及匹配正则表达式的行的提交,这不是整个方法/函数. (5认同)
  • 但是,如果对方法进行了20行修改怎么办? (3认同)

bad*_*adp 10

你可以做的最接近的事情是确定函数在文件中的位置(例如,假设你的函数i_am_buggy在第241-263行foo/bar.c),然后运行一些效果:

git log -p -L 200,300:foo/bar.c
Run Code Online (Sandbox Code Playgroud)

这将打开更少(或相当的寻呼机).现在您可以输入/i_am_buggy(或等效的寻呼机)并开始逐步完成更改.

这甚至可能有效,具体取决于您的代码样式:

git log -p -L /int i_am_buggy\(/,+30:foo/bar.c
Run Code Online (Sandbox Code Playgroud)

这限制了搜索从该正则表达式的第一次命中(理想情况下是您的函数声明)到此后的三十行.结束参数也可以是正则表达式,尽管使用正则表达式检测是一个更有效的命题.


Kri*_*ofe 7

  1. 显示函数历史记录,如eckes 的答案git docgit log -L :<funcname>:<file>中所示

    如果它没有显示任何内容,请参阅定义自定义 hunk-header*.java diff=java以向文件中添加类似内容.gitattributes 以支持您的语言。

  2. 显示提交之间的函数历史记录git log commit1..commit2 -L :functionName:filePath

  3. 显示重载函数历史记录(可能有许多函数具有相同的名称,但具有不同的参数)git log -L :sum\(double:filepath


Haz*_*d17 6

正确的方法是git log -L :function:path/to/file按照eckes answer 中的说明使用。

但是此外,如果您的函数很长,您可能只想查看各种提交引入的更改,而不是整个函数行,包括未修改的,对于每个可能只涉及这些行之一的提交。像正常人diff一样。

通常git log可以查看与 的差异-p,但这不适用于-L。因此,您必须grep git log -L仅显示涉及的行和提交/文件标题以将它们上下文化。这里的技巧是只匹配终端彩色线,添加--color开关,与正则表达式。最后:

git log -L :function:path/to/file --color | grep --color=never -E -e "^(^[\[[0-9;]*[a-zA-Z])+" -3
Run Code Online (Sandbox Code Playgroud)

请注意,^[应该是实际的,文字的^[。您可以通过在 bash 中按 ^V^[ 来输入它们,即Ctrl+ V, Ctrl+ [。参考这里

最后一个-3开关,允许在每个匹配行之前和之后打印 3 行输出上下文。您可能需要根据自己的需要进行调整。


Wil*_*ill 2

gitblame显示最后更改文件每一行的人;您可以指定要检查的行,以避免获取函数外部行的历史记录。

  • 使用“git guiblame”你可以浏览旧版本。 (4认同)