【问题标题】:How to search through all Git and Mercurial commits in the repository for a certain string?如何在存储库中搜索某个字符串的所有 Git 和 Mercurial 提交?
【发布时间】:2010-10-19 07:14:56
【问题描述】:

我有一个 Git 存储库,其中很少有分支和悬空提交。我想在存储库中搜索所有此类提交以查找特定字符串。

我知道如何获取历史中所有提交的日志,但这些不包括分支或悬空 blob,仅包括 HEAD 的历史。我想全部获取它们,以找到放错位置的特定提交。

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

【问题讨论】:

标签: git mercurial


【解决方案1】:

您可以使用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 将add the -G option,允许您通过 -G 来查找包含 的行何时被移动,而 -S 无法做到这一点。 -S 只会告诉您包含字符串的总行数何时更改(即添加/删除字符串)。

最后,您可以使用 gitk 来可视化悬空提交:

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

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

【讨论】:

  • 也许不是在(可能很大)数量的提交上运行“git grep”,这会找到项目中某处具有“search_for_this”的所有提交,使用所谓的“pickaxe”搜索,即git log 的“-S”选项,它查找引入或删除给定字符串的提交,或者更准确地说,给定字符串的出现次数发生了变化。
  • 你可以指定多个分支,或者使用'--all'选项,例如'git log --grep="提交消息中的字符串" --all'
  • 这只是让我为 2 天的工作找到丢失的提交。完全救了我的命,谢谢!
  • 我遇到过一些情况,我的数据库中有提交,但引用日志中没有。我不知道这有多普遍。我正在尝试不同的 hg/git 桥接器。我认为它也可能出现在掉落的藏匿处。无论如何,这个别名可以很好地捕捉这些情况:!git fsck --unreachable | sed -ne 's/^unreachable commit //p' | xargs git log --no-walk
  • 笔记,不包括搜索笔记对象。尚未实施:git.661346.n2.nabble.com/…
【解决方案2】:

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

【讨论】:

  • Josip 写道,他正在考虑改用 Mercurial,并且他还想听听那里是如何做到的。
  • hg log -k 也在变更集中搜索提交用户名和文件名(我在 commands.py:log 中看到),这是我在 hg.应该有单独的选项来搜索提交消息和文件名。似乎hg log --template '{desc}\n'|grep 是肯定的方法。
  • @GeoffreyZheng:有办法做到这一点。请参阅“hg help revsets”,尤其是 desc()、user() 和 file() 函数。大多数这种行为也有 hg 日志开关。根据我的经验,虽然 -k/keyword() 通常是最有用的搜索方式。
  • 如何搜索实际提交的文件内容...差异?我知道这会是一个缓慢的搜索,但我想深入搜索缺少的函数名称。
  • 哦,这里是:hg grep --all <term>
【解决方案3】:

除了使用git log -g --grep=<regexp>git grep -e <regexp> $(git log -g --pretty=format:%h)richq answer:查看以下由当前 git 维护者 Junio C Hamano 撰写的博文


总结

git grepgit log --grep 都是面向行的,因为它们会寻找与指定模式匹配的行。

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

由于是面向行的,有用的 AND 语义是使用 git log --all-match --grep=<foo> --grep=<bar> 来查找 commit 具有 both 在某处首先匹配行,然后匹配第二行。

使用git grep,您可以将多个模式(所有模式都必须使用-e <regexp> 形式)与--or(这是默认设置)、--and--not() 组合在一起。 For grep --all-match 意味着 file 必须包含与每个替代项匹配的行。

【讨论】:

  • 嘿 Jakub,介意在此处整合这些博客文章中的引用/摘要吗?看起来像现在的老式链接答案之一。
【解决方案4】:

基于 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】:

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

       --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 grep 的情况似乎并非如此,其中--all 似乎被翻译为/用作--all-match。这对我来说似乎是一个错误.. 使用 Git 1.7.2.3(使用 $(git rev-list --all) 有效)。
    【解决方案6】:

    使用 Mercurial,您可以做一个

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

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

    【讨论】:

    • 我也喜欢旗帜hg grep --all
    • 这个动作现在被称为hg histgrep,见hg help histgrep
    【解决方案7】:

    不了解 git,但在 Mercurial 中,我只需将 hg 日志的输出通过管道传输到一些 sed/perl/whatever 脚本,以搜索您要查找的任何内容。如果您愿意,您可以使用模板或样式自定义 hg log 的输出,以便于搜索。

    这将包括 repo 中的所有命名分支。 Mercurial 没有像悬空的 blobs afaik 之类的东西。

    【讨论】:

    • 我不明白这个答案与指定的问题有什么关系。
    • 这是对 Mercurial 问题的回答,原始问题在最后一段中提出。
    【解决方案8】:

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

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

    【讨论】:

      【解决方案9】:

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

      【讨论】:

        【解决方案10】:

        git中的一个命令,我认为查找字符串要容易得多:

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

        在 Git 2.0.4 中工作

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-10-30
          • 2015-09-14
          • 1970-01-01
          • 2011-03-19
          • 2016-07-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多