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

我有一个很少有分支和悬空提交的Git存储库。我想在存储库中搜索一个特定字符串的所有这样的提交。

我知道如何获得历史中所有提交的日志,但这些不包括分支或悬垂的blobs,只包括HEAD的历史。我想把它们都找回来,找到一个被放错地方的特定提交。

我还想知道如何在Mercurial做到这一点,因为我正在考虑切换。

135044 次浏览

任何以引用作为参数的命令都将接受--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并且可以从分支或标记访问的提交(我假设你的悬空提交至少有一个标记命名)。

你可以用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天,并且您使reflogs过期或运行了使它们过期的命令,则可能会发生这种情况。

我不知道git,但在Mercurial中,我只是将hg log的输出管道到一些sed/perl/任何脚本来搜索你正在寻找的东西。如果您愿意,可以使用模板或样式自定义hg日志的输出,使其更易于搜索。

这将包括回购中所有已命名的分支。Mercurial没有像悬挂blobs之类的东西。

除了使用git log -g --grep=<regexp>git grep -e <regexp> $(git log -g --pretty=format:%h)richq回答:看看下面的博客文章,由Junio C Hamano,当前的git维护者


总结

git grepGit log——grep都是线的,因为它们查找匹配指定模式的行。

你可以使用git log --grep=<foo> --grep=<bar>(或内部转换为两个--grepgit log --author=<foo> --grep=<bar>)来查找匹配模式要么的提交(隐式的语义)。

因为是面向行的,所以有用的语义是使用git log --all-match --grep=<foo> --grep=<bar>来找到< em >提交< / em >,它首先匹配这两个行,然后在某个地方匹配第二行。

使用git grep,你可以将多个模式(所有模式都必须使用-e <regexp>形式)与--or(默认值)、--and--not()组合在一起。对于grep, --all-match意味着文件< em > < / em >必须有与每个替代项匹配的行。

在Mercurial中,你做了一个

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

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

在Mercurial中,你使用hg log --keyword来搜索提交消息中的关键字,使用hg log --user来搜索特定的用户。有关限制日志的其他方法,请参见hg help log

基于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命令?

如果您是vim用户,您可以安装tig (apt-get install tig),并使用/,相同的命令在vim上搜索

https://blogs.atlassian.com/2013/05/git-tig/

为了补充一个尚未提到的解决方案,我不得不说,使用gitg的图形搜索框对我来说是最简单的解决方案。它将选择第一个事件,您可以使用Ctrl-G找到下一个事件。

git中的一个命令,我认为它更容易找到一个字符串:

git log --pretty=oneline --grep "string to search"

适用于Git 2.0.4