如何grep Git提交特定单词的差异或内容?


622

在Git代码存储库中,我想列出所有包含特定单词的提交。我试过了

git log -p | grep --context=4 "word"

但这并不一定会返回文件名(除非它与我搜索的单词相距少于5行。我也尝试过

git grep "word"

但是它只给我当前文件而不是历史记录。

如何搜索整个历史记录,以便可以跟踪特定单词的变化?我打算在我的代码库中搜索单词的出现以跟踪更改(在文件历史记录中搜索)。


Answers:


904

如果要查找所有提交消息中包含给定单词的提交,请使用

$ git log --grep=word

如果要查找在文件内容中添加或删除了“单词”的所有提交(更确切地说:“单词”的出现次数已更改的位置),即搜索提交内容,请使用所谓的“ pickaxe”搜索

$ git log -Sword

在现代git中,

$ git log -Gword

查找添加或删除的行与“ word”相匹配的差异(也提交内容)。

请注意,-G默认情况下接受正则表达式,而-S接受字符串,但是可以使用进行修改以接受正则表达式--pickaxe-regex

为了说明之间的区别-S<regex> --pickaxe-regex,并-G<regex>考虑在同一个文件中的以下DIFF提交:

+    return !regexec(regexp, two->ptr, 1, &regmatch, 0);
...
-    hit = !regexec(regexp, mf2.ptr, 1, &regmatch, 0);

虽然git log -G"regexec\(regexp"将显示此提交,但git log -S"regexec\(regexp" --pickaxe-regex不会(因为该字符串的出现次数未更改)。


使用Git 2.25.1(2020年2月),围绕这些正则表达式澄清了文档。

参见MartinÅgren(``)提交的9299f84(2020年2月6日
(通过合并JUNIOÇ滨野- gitster-提交0d11410,2020年2月12日)

diff-options.txt:在示例中避免“ regex”重载

报告人:Adam Dinwoodie
签名人:MartinÅgren
评论人:Taylor Blau

当我们举例说明之间的差异-G-S(使用--pickaxe-regex),我们可能会使用一个例子diff和git diff调用涉及“regexec”,“正则表达式”,“regmatch”,...

这个例子是正确的,但是我们可以避免编写“ regex。*”,从而使它更容易解开,除非确实需要我们指出这一点。

改用一些虚构的,非正规的单词。

git diff文档现在包括:

为了说明之间的区别-S<regex> --pickaxe-regex,并 -G<regex>考虑在同一个文件中的以下DIFF提交:

+    return frotz(nitfol, two->ptr, 1, 0);
...
-    hit = frotz(nitfol, mf2.ptr, 1, 0);

虽然git log -G"frotz\(nitfol"将显示此提交,但git log -S"frotz\(nitfol" --pickaxe-regex不会(因为该字符串的出现次数未更改)。


3
@TankorSmash -S<string>寻找引入或删除<string>实例的差异。-G<string>查找其添加或删除的行与给定的<regex>相匹配的差异。
m-ric 2013年

1
@ m-ric哦,我知道是单个字符串实例,而不是整行!谢谢
TankorSmash 2013年

3
@ m-ric,@ TankorSmash:区别在于-S<string>速度更快,因为它仅检查是否发生<string>更改的次数,而-G<string>在每个提交差异中搜索添加和删除的行。
JakubNarębski2013年

3
如果您需要搜索之间有空格的单词,请输入git log --grep="my words"
MEM 2014年

4
@MEM --grep-S和不同-G。您可以在每个这些参数中加上字符串。
Acumenus

255

git log的镐会发现包含“ word”在内的更改的提交 git log -Sword


60
这并不完全精确。-S <string>查找引入或删除<string>实例的差异。请注意,这不同于仅出现在diff输出中的字符串。
tymtam

4
虽然这通常是正确的答案,但我只是鼓励其他人阅读此答案(stackoverflow.com/a/1340245/586983),它有3种不同的方式并解释了它们的精妙之处。
jakeonrails

18
天哪!我认为这不是拒绝正确答案的充分理由……您不确定在评论中包含链接是否足以鼓励您?
Deborah

@jakeonrails,该答案应该是对此(旧)答案的修改,所以我们没有这些烦人的重复内容。但是人们只想要声誉,而不是干净的答案页。
Iulian Onofrei

22

经过大量的实验,我可以推荐以下内容,其中显示了引入或删除包含给定regexp的行的提交,并显示了每行中的文本更改,颜色显示了添加和删除的单词。

git log --pickaxe-regex -p --color-words -S "<regexp to search for>"

虽然需要一段时间才能运行... ;-)


2
这是迄今为止最好的感谢之一。提示:仅列出所有结果而不进行分页,可以在命令前加上GIT_PAGER=cat或附加| cat
Zack Morris

指定路径或文件会快得多git log --pickaxe-regex -p --color-words -S "<regexp to search for>" <file or fiepath>
fangxing

10

您可以尝试以下命令:

git log --patch --color=always | less +/searching_string

grep以以下方式使用:

git rev-list --all | GIT_PAGER=cat xargs git grep 'search_string'

在要搜索的父目录中运行此命令。


2
我喜欢这种方法,因为我正在查看的提交有数百行无关的更改,并且我只对涉及到我要搜索的单词的实际补丁感兴趣。要使用颜色git log --patch --color=always | less +/searching_string
Radon Rosborough

9

另一种方法/语法是:git log -S "word"
这样,您可以搜索例如git log -S "with whitespaces and stuff @/#ü !"


1

vim-fugitive对于在Vim中进行这种检查是通用的。

使用:Ggrep做到这一点。有关更多信息,您可以安装vim-fugitive并通过查找turorial :help Grep。而这一集:探索git存储库的历史将指导您完成所有这些工作。


1

要在正则表达式上使用布尔连接器:

git log --grep '[0-9]*\|[a-z]*'

该正则表达式在提交消息上搜索正则表达式[0-9] *或[az] *。


-1

如果您想搜索敏感数据以便将其从git历史记录中删除(这就是我登陆此处的原因),那么可以使用一些工具。Github作为该问题的专用帮助页面

这是本文的要旨:

BFG回购清机是与git滤波器分支更快,更简单的替代用于去除不想要的数据。例如,要删除包含敏感数据的文件并保持最新提交不变,请运行:

bfg --delete-files YOUR-FILE-WITH-SENSITIVE-DATA

要替换在passwords.txt中列出的所有文本,只要在存储库的历史记录中可以找到它,请运行:

bfg --replace-text passwords.txt

有关完整用法和下载说明,请参见BFG Repo-Cleaner的文档


您可能想将此答案添加到stackoverflow.com/questions/872565/…而不是此处
lacostenycoder
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.