如何在存储库中的所有Git和Mercurial提交中搜索某个字符串?


287

我有一个几乎没有分支和悬挂提交的Git存储库。我想在存储库中搜索所有此类提交以查找特定字符串。

我知道如何获取历史记录中的所有提交的日志,但是这些不包括分支或悬挂的Blob,而仅包括HEAD的历史记录。我想把它们全部拿走,找到放错地方的特定提交。

我也想知道如何在Mercurial中执行此操作,因为我正在考虑进行切换。


Answers:


331

您可以看到带有的悬空提交git log -g

-g, --walk-reflogs
 Instead of walking the commit ancestry chain, walk reflog entries from
 the most recent one to older ones. 

因此,您可以执行以下操作在悬空的提交消息中找到特定的字符串:

git log -g --grep=search_for_this

另外,如果您要搜索特定字符串的更改,则可以使用镐搜索选项“ -S”:

git log -g -Ssearch_for_this
# this also works but may be slower, it only shows text-added results
git grep search_for_this $(git log -g --pretty=format:%h)

Git 1.7.4将添加-G选项,使您可以传递-G <regexp>来查找何时移动了包含<regexp>的行,而-S无法做到。-S仅在包含字符串的总行数发生更改(即添加/删除字符串)时告诉您。

最后,您可以使用gitk通过以下方式可视化悬空的提交:

gitk --all $(git log -g --pretty=format:%h)

然后使用其搜索功能查找放错位置的文件。所有这些工作都假设丢失的提交尚未“过期”并被垃圾回收,如果它悬垂了30天并且您使reflog过期或运行使它们过期的命令,则可能会发生。


4
也许不是在一定数量(可能很多)的提交上运行“ git grep”,而是在项目中某处找到所有具有“ search_for_this”的提交,而是使用所谓的“ pickaxe”搜索,即git log的“ -S”选项,查找引入或删除了给定字符串的提交,或更准确地说,是给定字符串的出现次数发生了变化。
JakubNarębski09年

5
您可以指定多个分支,或使用“--all”选项,例如“git的日志--grep =‘字符串提交信息’--all”
的JakubNarębski

这只是让我发现了一份为期2天的工作所遗失的承诺。彻底救了我的屁股,谢谢!
Mike Chamberlain 2012年

2
我遇到过某些情况,其中我的数据库中有提交,但我的reflog中没有。我不知道这有多普遍。我正在尝试不同的hg / git桥。我认为藏匿垃圾也可能引起这种情况。无论如何,此别名可以很好地捕获这些情况:!git fsck --unreachable | sed -ne 's/^unreachable commit //p' | xargs git log --no-walk
dubiousjim 2012年

注意,这不包括搜索注释对象。尚未实现:git.661346.n2.nabble.com/…–
Antony Stubbs

54

在Mercurial中,您可以hg log --keyword用来搜索提交消息中的关键字并hg log --user搜索特定的用户。请参阅参考资料hg help log,以限制日志。


36
乔西普(Josip)写道,他正在考虑改用Mercurial,他也想听听那里的情况。
马丁·盖斯勒

1
hg log -k搜索也将用户名和文件名提交到变更集中(我在commands.py:log中看到了),这是我在hg中不了解的少数内容之一。应该有单独的选项来搜索提交消息和文件名。似乎hg log --template '{desc}\n'|grep是肯定的方法。
郑浩

@GeoffreyZheng:有很多方法可以做到这一点。请参见“ hg帮助修订集”,尤其是desc(),user()和file()函数。大多数情况下,还有汞日志开关。以我的经验,尽管-k / keyword()通常是最有用的搜索方式。
凯文·霍恩

如何搜索实际提交的文件内容...差异?我知道这将是一个缓慢的搜索,但是我想对缺少的函数名进行深入搜索。
乔纳森

哦,这是:hg grep --all <term>
Jonathan

24

除了使用or的richq答案外:还请查看以下git维护者Junio C Hamano的博客文章:git log -g --grep=<regexp>git grep -e <regexp> $(git log -g --pretty=format:%h)


摘要

这两个混帐的grep--grep git的日志面向行的,在他们查找符合指定模式的行。

您可以使用git log --grep=<foo> --grep=<bar>(或git log --author=<foo> --grep=<bar>在内部转换为两个--grep)来查找与任何一种模式(隐式语义)匹配的提交。

由于是面向行的,因此有用的AND语义git log --all-match --grep=<foo> --grep=<bar>用于查找某处同时具有第一行匹配和第二行匹配的提交

随着git grep您可以将多个模式(所有这一切都必须使用组合-e <regexp>与形式)--or(这是默认), ,,--and 和。对于grep 意味着该文件必须具有与每个替代项匹配的行。--not()--all-match


嘿,雅各布(Jakub),在这里整合这些博客文章的引用/摘要吗?看起来现在是老式的仅链接的答案之一。
内森·塔吉

11

基于rq的答案,我发现这行符合我的要求:

git grep "search for something" $(git log -g --pretty=format:%h -S"search for something")

它将报告提交ID,文件名并显示匹配的行,如下所示:

91ba969:testFile:this is a test

...是否有人同意这将是标准git grep命令中包含的一个不错的选择?


5

任何将引用作为参数的命令将接受--all手册页中记录的选项git rev-list,如下所示:

   --all
       Pretend as if all the refs in $GIT_DIR/refs/ are listed on the
       command line as <commit>.

因此,例如git log -Sstring --all将显示所有提及的提交,这些提交string可从分支或标签访问(我假设您的悬空提交至少使用标签命名)。


3
似乎并非如此git grep--all似乎已被翻译为或用作--all-match。对我来说,这似乎是一个错误。.使用Git 1.7.2.3(使用$(git rev-list --all)作品)。
2011年

5

使用Mercurial,您可以

$ hg grep "search for this" [file...]

还有其他选项可以缩小搜索的修订范围。


1
我也喜欢国旗hg grep --all
Jonathan

2

不了解git,但是在Mercurial中,我只是将hg日志的输出通过管道传递到sed / perl /任何脚本中,以搜索所需的内容。您可以根据需要使用模板或样式自定义hg日志的输出,以使其更易于搜索。

这将包括回购中的所有命名分支。水星没有悬挂的斑点afaik之类的东西。


1
我不知道此答案与指定问题有何关系。
jribeiro

3
这是Mercurial问题的答案,原始问题在上一段中提出。
Kurt Schelfthout,2013年


1

要添加仅一个尚未提及的解决方案,我不得不说使用gitg的图形搜索框对我来说是最简单的解决方案。它将选择第一个匹配项,您可以使用Ctrl-G查找下一个匹配项。


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.