乐闻世界logo
搜索文章和话题

Git 如何通过 grep 搜索历史提交的代码历史?

8 个月前提问
4 个月前修改
浏览次数100

7个答案

1
2
3
4
5
6
7

当您想要在 Git 的代码历史中搜索特定的关键词或模式时,可以使用 git grep 配合 git log 的一些参数来实现。以下是实现这个目的的一个基本步骤:

  1. 使用 git grep 搜索工作目录中的内容:

    若您只是想搜索当前工作目录中的文件,可以直接使用 git grep 命令。例如:

    shell
    git grep '搜索关键字'
  2. 搜索历史提交中的内容:

    如果您想搜索历史提交中的内容,可以使用 git log-p 参数和 grep 命令组合起来。例如,搜索历史提交中包含“搜索关键字”的内容:

    shell
    git log -p -S'搜索关键字'

    这里的 -p 参数会显示每个提交的差异(即代码更改),而 -S 参数用于指定要搜索的字符串。-S 会查找添加或删除了指定字符串的那些提交。

  3. 结合使用 git log 和外部的 grep 命令:

    您也可以通过管道将 git log 的输出传递给外部的 grep 命令,这样可以利用 grep 的强大搜索能力。例如:

    shell
    git log -p | grep '搜索关键字'

    如果您想要更具体的信息,比如显示匹配到关键字的提交哈希,可以通过添加额外的参数来实现。例如:

    shell
    git log -p | grep -B 4 '搜索关键字'

    这里 -B 4 表示除了显示匹配行之外,还会显示匹配行之前的四行,这通常包括了提交信息。

  4. 使用 git log -G 进行正则表达式搜索:

    如果要进行更复杂的搜索,可以使用 -G 参数,后面跟上正则表达式:

    shell
    git log -p -G'regex'
  5. 限定搜索的文件范围:

    如果您只对特定类型的文件或特定的文件路径进行搜索,可以在 git grep 命令中指定文件路径或模式。例如,只搜索所有 .c 文件:

    shell
    git grep '搜索关键字' -- '*.c'
  6. 搜索特定分支或标签中的内容:

    如果您想搜索特定分支或标签中的内容,可以在 git grep 命令中指定分支或标签名。例如,在名为“feature-branch”的分支中搜索:

    shell
    git grep '搜索关键字' feature-branch

通过以上步骤,您可以灵活地搜索 Git 历史中的代码。记得替换 '搜索关键字''regex' 为您实际想要搜索的内容。

2024年6月29日 12:07 回复

要搜索提交_内容_(即实际的源代码行,而不是提交消息等),您需要执行以下操作:

shell
git grep <regexp> $(git rev-list --all)

git rev-list --all | xargs git grep <expression>如果您遇到“参数列表太长”错误,它将起作用。

如果您想将搜索限制在某个子树(例如“lib/util”),您需要将其传递给子rev-list命令,grep并且:

shell
git grep <regexp> $(git rev-list --all -- lib/util) -- lib/util

这将 grep 遍历您的所有提交文本regexp

在两个命令中传递路径的原因是因为rev-list将返回发生所有更改的修订列表lib/util,但您还需要传递 togrep以便它只在lib/util.

想象一下以下场景:可能会在返回的同一修订版中包含的其他文件上grep找到相同的内容(即使该修订版上的该文件没有更改)。<regexp>``rev-list

以下是搜索来源的一些其他有用方法:

在工作树中搜索与正则表达式 regexp 匹配的文本:

shell
git grep <regexp>

在工作树中搜索与正则表达式 regexp1 或 regexp2 匹配的文本行:

shell
git grep -e <regexp1> [--or] -e <regexp2>

在工作树中搜索与正则表达式 regexp1 和 regexp2 匹配的文本行,仅报告文件路径:

shell
git grep -l -e <regexp1> --and -e <regexp2>

在工作树中搜索具有与正则表达式 regexp1 匹配的文本行和与正则表达式 regexp2 匹配的文本行的文件:

shell
git grep -l --all-match -e <regexp1> -e <regexp2>

在工作树中搜索已更改的文本匹配模式行:

shell
git diff --unified=0 | grep <pattern>

搜索所有修订版本以查找与正则表达式 regexp 匹配的文本:

shell
git grep <regexp> $(git rev-list --all)

搜索 rev1 和 rev2 之间的所有修订版本以查找与正则表达式 regexp 匹配的文本:

shell
git grep <regexp> $(git rev-list <rev1>..<rev2>)
2024年6月29日 12:07 回复

您应该使用 的pickaxe ( -S)选项git log

要搜索Foo

shell
git log -SFoo -- path_containing_change git log -SFoo --since=2009.1.1 --until=2010.1.1 -- path_containing_change

有关更多信息,请参阅Git 历史记录 - 按关键字查找丢失的行。

-S(名为pickaxe)最初来自一个git diff选项(Git v0.99,2005 年 5 月)。然后-S( pickaxe)于 2006 年 5 月用 Git 1.4.0-rc1移植到。git log


正如雅库布·纳伦布斯基 (Jakub Narębski)评论的那样:

  • 会查找引入或删除 实例的差异<string>。它通常意味着“添加或删除带有‘Foo’的行的修订”。

  • --pickaxe-regex选项允许您使用扩展的 POSIX 正则表达式而不是搜索字符串。示例(来自git log):git log -S"frotz\(nitfol" --pickaxe-regex


正如Rob评论的那样,此搜索区分大小写 - 他提出了有关如何搜索不区分大小写的后续问题。


嗨天使在评论中指出:

执行 a git log -G<regexp> --branches --all(与正则表达式-G相同)与接受的执行( ) 执行相同的操作,但速度快得多!-Sgit grep <regexp> $(git rev-list --all)

接受的答案在我运行约 10 分钟后仍在搜索文本,而这个答案在约 4 秒后给出结果🤷‍♂️。这里的输出也更有用

2024年6月29日 12:07 回复

我最喜欢的方法是使用git log's-G选项(在版本 1.7.4 中添加)。

shell
-G<regex> Look for differences whose added or removed line matches the given <regex>.

-G-S选项确定提交是否匹配的方式之间存在细微差别:

  • -S选项本质上是计算提交之前和之后您的搜索在文件中匹配的次数。如果之前和之后的计数不同,则提交会显示在日志中。例如,这不会显示与您的搜索匹配的行被移动的提交。
  • 使用该-G选项,如果您的搜索与添加、删除或更改的任何行匹配,则提交将显示在日志中。

以这次提交为例:

shell
diff --git a/test b/test index dddc242..60a8ba6 100644 --- a/test +++ b/test @@ -1 +1 @@ -hello hello +hello goodbye hello

因为在这次提交之前和之后文件中出现“hello”的次数是相同的,所以使用-Shello. 但是,由于匹配的行发生了更改hello,因此将使用 来显示提交-Ghello

2024年6月29日 12:07 回复

git log可以是跨所有分支搜索文本的更有效方法,特别是如果有很多匹配项,并且您希望首先查看更新的(相关)更改。

shell
git log -p --all -S 'search string' git log -p --all -G 'match regular expression'

这些日志命令列出添加或删除给定搜索字符串/正则表达式的提交,(通常)首先是最近的。该-p选项会导致在添加或删除模式的位置显示相关差异,以便您可以在上下文中查看它。

找到添加您要查找的文本的相关提交(例如 8beeff00d)后,找到包含该提交的分支:

shell
git branch -a --contains 8beeff00d
2024年6月29日 12:07 回复

如果您想浏览代码更改(查看整个历史记录中给定单词实际更改的内容),请选择patch模式 - 我发现了一个非常有用的组合:

shell
git log -p # Hit '/' for search mode. # Type in the word you are searching. # If the first search is not relevant, hit 'n' for next (like in Vim ;) )
2024年6月29日 12:07 回复

Git 的代码历史中搜索特定的关键词或模式时,可以使用 git grep 配合 git log 的一些参数来实现。以下是实现这个目的的一个基本步骤:

  1. 使用 git grep 搜索工作目录中的内容:

    若您只是想搜索当前工作目录中的文件,可以直接使用 git grep 命令。例如:

    shell
    git grep '搜索关键字'
  2. 搜索历史提交中的内容:

    如果您想搜索历史提交中的内容,可以使用 git log-p 参数和 grep 命令组合起来。例如,搜索历史提交中包含“搜索关键字”的内容:

    shell
    git log -p -S'搜索关键字'

    这里的 -p 参数会显示每个提交的差异(即代码更改),而 -S 参数用于指定要搜索的字符串。-S 会查找添加或删除了指定字符串的那些提交。

  3. 结合使用 git log 和外部的 grep 命令:

    您也可以通过管道将 git log 的输出传递给外部的 grep 命令,这样可以利用 grep 的强大搜索能力。例如:

    shell
    git log -p | grep '搜索关键字'

    如果您想要更具体的信息,比如显示匹配到关键字的提交哈希,可以通过添加额外的参数来实现。例如:

    shell
    git log -p | grep -B 4 '搜索关键字'

    这里 -B 4 表示除了显示匹配行之外,还会显示匹配行之前的四行,这通常包括了提交信息。

  4. 使用 git log -G 进行正则表达式搜索:

    如果要进行更复杂的搜索,可以使用 -G 参数,后面跟上正则表达式:

    shell
    git log -p -G'regex'
  5. 限定搜索的文件范围:

    如果您只对特定类型的文件或特定的文件路径进行搜索,可以在 git grep 命令中指定文件路径或模式。例如,只搜索所有 .c 文件:

    shell
    git grep '搜索关键字' -- '*.c'
  6. 搜索特定分支或标签中的内容:

    如果您想搜索特定分支或标签中的内容,可以在 git grep 命令中指定分支或标签名。例如,在名为“feature-branch”的分支中搜索:

    shell
    git grep '搜索关键字' feature-branch

通过以上步骤,您可以灵活地搜索 Git 历史中的代码。记得替换 '搜索关键字''regex' 为您实际想要搜索的内容。

2024年6月29日 12:07 回复

你的答案