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

Jos*_*sip 287 git mercurial

我有一个Git存储库,有很少的分支和悬挂提交.我想在存储库中搜索所有此类提交以获取特定字符串.

我知道如何记录历史上所有提交的日志,但这些不包括分支或悬空blob,只是HEAD的历史记录.我希望得到所有这些,找到一个错位的特定提交.

我也想知道如何在Mercurial中做到这一点,因为我正在考虑转换.

ric*_*chq 330

你可以看到悬挂的提交git log -g.

-g, --walk-reflogs
 Instead of walking the commit ancestry chain, walk reflog entries from
 the most recent one to older ones. 
Run Code Online (Sandbox Code Playgroud)

所以你可以这样做,在悬挂的提交消息中找到一个特定的字符串:

git log -g --grep=search_for_this
Run Code Online (Sandbox Code Playgroud)

或者,如果要搜索特定字符串的更改,可以使用pickaxe搜索选项"-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)
Run Code Online (Sandbox Code Playgroud)

Git 1.7.4将添加-G选项,允许您传递-G <regexp>以查找何时移动包含<regexp>的行,-S无法执行.-S只会告诉你包含字符串的行总数何时发生变化(即添加/删除字符串).

最后,您可以使用gitk来显示悬空提交:

gitk --all $(git log -g --pretty=format:%h)
Run Code Online (Sandbox Code Playgroud)

然后使用其搜索功能查找放错位置的文件.所有这些工作假设丢失的提交没有"过期"并且被垃圾收集,如果它悬挂30天并且您使explog到期或运行使它们到期的命令,则可能发生这种情况.

  • 您可以指定多个分支,或使用'--all'选项,例如'git log --grep ="提交消息中的字符串"--all' (5认同)
  • 也许不是在(可能很大的)提交数量上运行"git grep",而是在项目的某处找到所有提交"search_for_this"的提交,使用所谓的"pickaxe"搜索,即git log的'-S'选项,查找引入或删除给定字符串的提交,或者更确切地说,给定字符串的出现次数发生变化. (4认同)
  • 我遇到过一些情况,我在我的数据库中提交但不在我的reflog中.我不知道这有多常见.我正在尝试不同的hg/git桥.我认为它也可能出现在被丢弃的藏匿处.无论如何,这个别名可以很好地捕捉到这些情况:`!git fsck --unreachable | sed -ne's/^ unreachable commit // p'| xargs git log --no-walk` (2认同)

Mar*_*ler 54

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

  • Josip写道,他正在考虑转向Mercurial,并且他也想听听它是如何在那里完成的. (36认同)

Jak*_*ski 24

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


摘要

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

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

由于是面向行的,有用的语义是使用git log --all-match --grep=<foo> --grep=<bar>发现两种线路匹配第一和线路匹配第二某处.

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


Sam*_*att 11

基于rq的答案,我发现这条线做了我想要的:

git grep "search for something" $(git log -g --pretty=format:%h -S"search for something")
Run Code Online (Sandbox Code Playgroud)

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

91ba969:testFile:this is a test
Run Code Online (Sandbox Code Playgroud)

...有没有人同意这是一个很好的选择,可以包含在标准的git grep命令中?


adl*_*adl 5

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

   --all
       Pretend as if all the refs in $GIT_DIR/refs/ are listed on the
       command line as <commit>.
Run Code Online (Sandbox Code Playgroud)

因此,例如,git log -Sstring --all将显示提及的所有提交string以及可从分支或标记访问的提交(我假设您的悬挂提交至少以标记命名).

  • 这似乎不是`git grep`的情况,其中`--all`似乎被翻译为/用作`--all-match`.这看起来像是一个bug ...使用Git 1.7.2.3(使用`$(git rev-list --all)`works). (3认同)

Yaw*_*war 5

使用Mercurial,你可以做到

$ hg grep "search for this" [file...]
Run Code Online (Sandbox Code Playgroud)

还有其他选项可以缩小搜索范围.