如何查看Git中一个函数的修改历史/删除记录?

5
我正在尝试寻找一些曾经被删除的函数。我尝试使用git log -L :<funcname>:<file>来定位被删除的函数。结果显示为fatal: -L parameter '<funcname>' starting at line 1: no match
例如,如果我要查找函数findMe
我输入git log -L :findMe:index.php index.php
 <?php
 class stuff {.....}
 class otherStuff{....}
 class moreStuff{
   public function test(){...}
   public function findMe() {....}
   public function test1() {....}
 }
?>

结果 fatal: -L参数'<funcname>'从第1行开始:没有匹配项

参考 git log:

-L :<funcname>:<file>

如果在<start><end>的位置上给出“:<funcname>”,则它是一个正则表达式,表示范围从第一行匹配<funcname>的funcname行到下一个funcname行。如果之前有-L范围,则“:<funcname>”将从该范围的结尾开始搜索,否则将从文件的开头开始搜索。“^:<funcname>”将从文件的开头开始搜索。

3个回答

1

-L 只能找到在当前显示的文件版本中存在的内容。

(你引用的错误信息表明你传递了字面字符串<funcname>给你的命令,而不是字符串findMe。然而,如果findMe在当前或指定版本的index.php中不存在,-L也无法找到它。)

要查找更改字符串或正则表达式出现次数或影响匹配字符串或正则表达式的行的提交,请使用git log -Sgit log -G。请注意,-S默认使用字符串,而-G始终使用正则表达式。要使-S搜索正则表达式而不是简单字符串,请添加--pickaxe-regex。您可以将此类搜索限制为特定路径(与-L相比,它可以搜索许多路径名,但必须只搜索一个文件)。

因此,如果findMe曾经存在于index.php中但现在不再存在于index.php中,则命令如下:
git log -S findMe --full-history -- index.php

将找到所有更改此内容的提交,因为它将从index.php中的一个或多个出现次数变为零。但请注意,添加路径名index.php会打开历史记录简化功能。使用--full-history禁用此简化,以便您可以找到删除它的所有提交,而不仅仅是一些提交(如果删除是通过合并实现的,则有时会失败)。

1
那应该更容易使用Git 2.30(2021年第一季度)。在此之前,“git blame -L :funcname -- path(man) 对于定义了用户差异驱动程序的路径无法正常工作。

请参见提交 3af31e8, 提交 88894aa, 提交 9466e38, 提交 180d641, 提交 0cce88f, 提交 a4514a4, 提交 fd5c74e, 提交 f9c8d8c (2020年11月1日) 由Philippe Blain (phil-blain)提交。
(由Junio C Hamano -- gitster --合并于提交 3f6dc9c, 2020年11月18日)

blame: 启用 userdiff 驱动程序的 funcname 责备

签名作者:Philippe Blain

In blame.c::cmd_blame, we send the 'path' field of the 'sb' 'struct blame_scoreboard' as the 'path' argument to 'line-range.c::parse_range_arg', but 'sb.path' is not set yet; it's set to the local variable 'path' a few lines later at line 1137.

This 'path' argument is only used in 'parse_range_arg' if we are blaming a funcname, i.e. git blame -L :<funcname> <path>(man), and in that case it is sent to 'parse_range_funcname', where it is used to determine if a userdiff driver should be used for said <path> to match the given funcname.

Since 'path' is yet unset, the userdiff driver is never used, so we fall back to the default funcname regex, which is usually not appropriate for paths that are set to use a specific userdiff driver, and thus either we match some unrelated lines, or we die with

fatal: -L parameter '<funcname>' starting at line 1: no match  

This has been the case ever since git blame(man) learned to blame a funcname in 13b8f68c1f ("log -L: :pattern:file syntax to find by funcname", 2013-03-28, Git v1.8.4-rc0 -- merge).

Enable funcname blaming for paths using specific userdiff drivers by initializing 'sb.path' earlier in 'cmd_blame', when some of its other fields are initialized, so that it is set when passed to 'parse_range_arg'.


这是我个人的答案。但是,令我失望的是,在 git version 2.35.1 中,如果您正在寻找一个 C++ 类的成员函数,并且您想要做合理的事情,即像这样完全限定函数名称以及类名称:git blame -L :SomeClass::SomeMemberFunction -- ./some_source_file.cpp,它返回一个使用错误。[续] - bgoodr
继续上文:相反,您必须像这样删除SomeClass::限定符:git blame -L :SomeMemberFunction -- ./some_source_file.cpp。在我看来,这可能会浪费时间:如果不幸的是,您正在研究在同一源文件中定义了两个或更多类,每个类都包含SomeMemberFunction的定义,那么Git将选择分析哪个类的成员函数呢? - bgoodr
@bgoodr 看来确实很不幸。你试过加引号吗?-L“:SomeClass :: SomeMemberFunction” - VonC
考虑到我使用的是在Linux平台上运行的bash交互式shell,并且在该shell中冒号字符不是元字符,至少在该用法中,双引号将是多余的。 - bgoodr

0

git log -L 只在文件的最高级别上搜索 funcname。您可以使用该命令查看任何类或类外任何函数的历史记录,但不幸的是它无法找到类内部的函数。

您能做的最好的事情是 git log -L :moreStuff:index.php,并在输出中搜索函数日志。


1
请澄清这里的“在文件的最高级别”是什么意思。 - bgoodr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接