是否可以在Git项目的所有分支中执行“ grep搜索”?


Answers:


189

问题“ 如何在git历史中grep(搜索)已提交的代码? ”建议:

 git grep <regexp> $(git rev-list --all)

它将搜索所有提交,其中应包括所有分支。

另一种形式是:

git rev-list --all | (
    while read revision; do
        git grep -F 'yourWord' $revision
    done
)

您可以在本文中找到更多示例:

我在一个足够大的项目上尝试了上述方法,使得git抱怨参数大小,因此,如果遇到此问题,请执行以下操作:

git rev-list --all | (while read rev; do git grep -e <regexp> $rev; done)

(请参见下面的此答案的最后一部分中的替代方法)

如果需要,请不要忘记这些设置:

# Allow Extended Regular Expressions
git config --global grep.extendRegexp true
# Always Include Line Numbers
git config --global grep.lineNumber true

此别名也可以提供帮助:

git config --global alias.g "grep --break --heading --line-number"

注意:chernjie 认为git rev-list --all是一个过大的杀伤力。

更精细的命令可以是:

git branch -a | tr -d \* | xargs git grep <regexp>

这将使您仅搜索分支(包括远程分支)

您甚至可以为其创建bash / zsh别名:

alias grep_all="git branch -a | tr -d \* | xargs git grep"
grep_all <regexp>

2016年8月更新:RM建议在评论中

fatal: bad flag '->' used after filename尝试git branch版本时出现了“ ” 。该错误与HEAD别名表示法相关。

我通过sed '/->/d'trxargs命令之间在管道中添加一个来解决此问题。

 git branch -a | tr -d \* | sed '/->/d' | xargs git grep <regexp>

那是:

alias grep_all="git branch -a | tr -d \* | sed '/->/d' | xargs git grep"
grep_all <regexp>

将输出通过管道传输git branch到tr或sed中不是一个好主意;git branch是供人类食用的瓷器命令。有关首选的替代方法,请参见stackoverflow.com/a/3847586/2562319
jbyler '17

@jbyler好点。具有讽刺意味的是,我早在答案之前就将答案发布在瓷器上:stackoverflow.com/a/6978402/6309。我在stackoverflow.com/a/19206916/6309中使用了它。
VonC

是的,很好。查看其他答案,我认为@errordeveloper的答案是最干净的:stackoverflow.com/a/21284342/2562319:“ git grep <regexp> $(git for-each-ref --format ='%(refname) 'refs /)“
jbyler's

1
有什么方法可以显示与搜索匹配的分支名称?
franksands,

63

git log 可以是一种在所有分支中搜索文本的更有效方法,尤其是在存在许多匹配项并且您希望首先查看最新(相关)更改的情况下。

git log -p --all -S 'search string'
git log -p --all -G 'match regular expression'

这些日志命令列出提交,这些提交添加或删除给定的搜索字符串/正则表达式(通常)是最近的。该-p选项使相关的差异显示在添加或删除模式的位置,因此您可以在上下文中看到它。

找到相关的提交以添加您要查找的文本(例如8beeff00d)后,找到包含该提交的分支:

git branch -a --contains 8beeff00d

22

我发现这最有用:

git grep -i foo `git for-each-ref --format='%(refname)' refs/`

您需要根据是否只想查看远程分支还是本地分支来调整最后一个参数,即:

  • git grep -i foo $(git for-each-ref --format='%(refname)' refs/remotes)
  • git grep -i foo $(git for-each-ref --format='%(refname)' refs/heads)

我创建的别名如下所示:

grep-refs = !sh -c 'git grep "$0" "$@" "$(git for-each-ref --format=\"%(refname)\"" refs/)'

1
有趣的别名。+1。比我的回答更精确。
VonC 2014年

如何使您的别名适用于短语搜索?当我将“ foo bar”作为参数传递时,我得到:致命:模棱两可的参数“ bar”:未知版本或不在工作树中的路径。使用“-”将路径与修订版本分开
挺高的

尝试逃避空间:“ foo \ bar”
Garry Gomez,

这显然是可以接受的答案;)我已经在其上进行了扩展,仅在项目的最新分支中进行搜索(获得了500多个,不要问,每个grep大约需要4秒钟,所以我既不需要也不需要搜索超过100个最新搜索)。为此,我已经更新了git for-each-ref--sort=-committerdate --count=100!感谢您的初衷!
Vser

6

可以通过两种常见的方式来做到这一点:Bash或Git别名

这是三个命令:

  1. git grep-branch -搜索所有本地和远程分支机构
  2. git grep-branch-local -仅在本地分支机构中搜索
  3. git grep-branch-remote -仅远程分支

用法与 git grep

git grep-branch "find my text"
git grep-branch --some-grep-options "find my text"

GREP使用:Git别名

文件〜/ .gitconfig

应该手动将命令添加到~/.gitconfig文件,因为git config --global alias评估添加的复杂代码并将其弄乱。


[alias]
    grep-branch        = "!f(){ git branch -a | sed -e 's/[ \\*]*//' | grep -v -e '\\->' | xargs git grep $@; };f "
    grep-branch-remote = "!f(){ git branch -a | sed -e 's/[ \\*]*//' | grep -v -e '\\->' | grep '^remotes' | xargs git grep $@; };f"
    grep-branch-local  = "!f(){ git branch -a | sed -e 's/[ \\*]*//' | grep -v -e '\\->' -e '^remotes' | xargs git grep $@;  };f "

注意:添加别名后,别名将无法运行- 与bash命令相比,检查反斜杠\可能需要其他转义。\\

  • git branch -a -显示所有分支;
  • sed -e 's/[ \\*]*//'-修剪空格(来自branch -a)和*(活动分支名称具有);
  • grep -v -e '\\->'-忽略复杂的名称,例如remotes/origin/HEAD -> origin/master
  • grep '^remotes' -获取所有远程分支;
  • grep -v -e '^remotes'-获取远程分支机构以外的分支机构;

git grep-branch-local -n getTastyCookies

-n 在行号之前添加匹配行。

[user@pc project]$ git grep-branch-local -n getTastyCookies

dev:53:modules/factory/getters.php:function getTastyCookies($user);
master:50:modules/factory/getters.php:function getTastyCookies($user)

当前结构为:

: - 分隔器

  1. 科: dev
  2. 电话号码: 53
  3. 文件路径: modules/factory/getters.php
  4. 配套线: function getTastyCookies($user)

GREP使用:BASH

如您所知:Bash命令应存储在.sh脚本中或在Shell中运行。

仅本地分行

git branch -a | sed -e 's/[ \*]*//' | grep -v -e '\->' -e '^remotes' | xargs git grep "TEXT"

仅远程分支

git branch -a | sed -e 's/[ \*]*//' | grep -v -e '\->' | grep '^remotes' | xargs git grep "TEXT"

本地和远程分支机构

git branch -a | sed -e 's/[ \*]*//' | grep -v -e '\->' | xargs git grep "TEXT"

听起来不错,但我收到以下错误消息git grep-branch "find my text"fatal: ambiguous argument 'client': both revision and filename
nealmcb

为什么总是使用-a,它显示所有分支?我建议对git branch命令使用选项来分隔分支。在查看本地分支机构时,只有一个*,因此无需为sed而对其进行转义。因此:git branch | sed -e 's/*/ /' | xargs git grep "TEXT"git branch -r | grep -v -- "->" | xargs git grep "TEXT"适用于本地分支机构,仅适用于远程分支机构,以及git branch -a | grep -v -- "->" | xargs git grep "TEXT"所有分支机构
jalanb

4

这是我的方法:

git for-each-ref --format='%(*refname)' | xargs git grep SEARCHTERM

2
Windows上唯一适用于我的解决方案(使用Git bash)
Ivan

4

如果您给任何提交一个SHA-1哈希值,git grep就在其中而不是工作副本中进行搜索。

要搜索所有分支,可以使用获取所有git rev-list --all。全部放在一起

git grep "regexp" $(git rev-list --all)

...并且有耐心

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.