如何从git grep搜索中排除某些目录/文件

时间:2012-05-02 23:31:46

标签: git grep

有没有办法使用git grep搜索git存储库,但是从搜索中排除某些路径/目录/文件?与普通grep命令中的--exclude选项类似。

如果你很好奇:我不想使用普通的grep,因为当git存储库的大小很大时,它比git grep慢得多。

5 个答案:

答案 0 :(得分:163)

在git 1.9.0中,“魔术词”exclude被添加到pathspec s。因此,如果您要在每个文件中搜索foobar,除了匹配*.java的文件外,您可以执行以下操作:

git grep foobar -- './*' ':(exclude)*.java'

或使用!“简短形式”进行排除:

git grep foobar -- './*' ':!*.java'

请注意,使用排除pathspec时,您必须至少有一个“包含”pathspec。在上面的示例中,这是./*(递归地包含当前目录下的所有内容)。

您还可以使用:(top)(简称::/)之类的内容来包含repo顶部的所有内容。但是,您可能还希望将排除pathspec调整为从顶部开始::/!*.java(否则它只会排除当前目录下的*.java个文件。)< / p>

pathspec git-scm.com(或git help glossary)允许的所有“魔术词汇”都有很好的参考。由于某些原因,kernel.org的文档确实已过时,即使它们经常出现在谷歌搜索中。

答案 1 :(得分:59)

更新:对于git&gt; = 1.9,对排除模式有原生支持,请参阅onlyone's answer

这可能看起来倒退,但您可以将与您的排除模式不匹配的文件列表传递给git grep,如下所示:

git grep <pattern> -- `git ls-files | grep -v <exclude-pattern>`

grep -v会返回匹配<exclude-pattern> 的每条路径。请注意,git ls-files也会使用--exclude参数,但这仅适用于未跟踪文件

答案 2 :(得分:15)

这是不可能的,但是has been discussed recently。链接中提议的解决方法:

  

您可以将*.dll放入.gitignore文件,然后git grep --exclude-standard

编辑看onlynone's answer,因为git 1.9.0是可能的。

答案 3 :(得分:2)

以@kynan作为基础的示例,我制作了这个脚本,并将其作为~/bin/放在我的路径(gg)中。它确实使用git grep但避免了一些指定的文件类型。

在我们的回购中它有很多图像,所以我已经排除了图像文件,如果我搜索整个回购,这会将serchtime降低到1/3。但是可以很容易地修改脚本以排除其他文件类型或geleralpatterns。

#!/bin/bash                                                                    
#                                                                              
# Wrapper of git-grep that excludes certain filetypes.                         
# NOTE: The filetypes to exclude is hardcoded for my specific needs.           
#                                                                              
# The basic setup of this script is from here:                                 
#   https://stackoverflow.com/a/14226610/42580                                  
# But there is issues with giving extra path information to the script         
# therefor I crafted the while-thing that moves path-parts to the other side   
# of the '--'.                                                                 

# Declare the filetypes to ignore here                                         
EXCLUDES="png xcf jpg jpeg pdf ps"                                             

# Rebuild the list of fileendings to a good regexp                             
EXCLUDES=`echo $EXCLUDES | sed -e 's/ /\\\|/g' -e 's/.*/\\\.\\\(\0\\\)/'`      

# Store the stuff that is moved from the arguments.                            
moved=                                                                         

# If git-grep returns this "fatal..." then move the last element of the        
# arg-list to the list of files to search.                                     
err="fatal: bad flag '--' used after filename"                                 
while [ "$err" = "fatal: bad flag '--' used after filename" ]; do              
    {                                                                          
        err=$(git grep "$@" -- `git ls-files $moved | grep -iv "$EXCLUDES"` \  
            2>&1 1>&3-)                                                        
    } 3>&1                                                                     

    # The rest of the code in this loop is here to move the last argument in   
    # the arglist to a separate list $moved. I had issues with whitespace in   
    # the search-string, so this is loosely based on:                          
    #   http://www.linuxjournal.com/content/bash-preserving-whitespace-using-set-and-eval
    x=1                                                                        
    items=                                                                     
    for i in "$@"; do                                                          
        if [ $x -lt $# ]; then                                                 
            items="$items \"$i\""                                              
        else                                                                   
            moved="$i $moved"                                                  
        fi                                                                     
        x=$(($x+1))                                                            
    done                                                                       
    eval set -- $items                                                         
done                                                                           
# Show the error if there was any                                              
echo $err                                                                      

注1

根据this,应该可以将事物命名为git-gg,并且可以将其称为常规git命令,如:

$ git gg searchstring

但我不能让这个工作。我在~/bin/中创建了该脚本,并在git-gg中创建了/usr/lib/git-core/符号链接。

注2

该命令不能成为常规sh git-alias,因为它将在repo的根目录中调用。这不是我想要的!

答案 4 :(得分:1)

您可以通过在存储库中创建属性文件来将文件或目录标记为二进制文件,例如

$ cat .git/info/attributes 
directory/to/ignore/*.* binary
directory/to/ignore/*/*.* binary
another_directory/to/also/ignore/*.* binary

列出了二进制文件中的匹配项,但没有包含行,例如

$ git grep "bar"
Binary file directory/to/ignore/filename matches
other_directory/other_filename:      foo << bar - bazz[:whatnot]