web-dev-qa-db-ja.com

git grep検索から特定のディレクトリ/ファイルを除外する方法

git grepを使用してgitリポジトリを検索する方法はありますが、特定のパス/ディレクトリ/ファイルを検索から除外しますか?通常のgrepコマンドの--excludeオプションと同様です。

好奇心が強い場合:gitリポジトリのサイズが大きい場合、git grepよりもはるかに遅いため、通常のgrepは使用しません。

118

それは不可能ですが、 最近議論されました 。リンクで提案された回避策:

*.dll to .gitignore file then git grep --exclude-standard

編集 onlynone's answer を参照してください。git1.9.0以降は可能です。

16
CharlesB

Git 1.9.0では、「マジックワード」excludepathspecsに追加されました。したがって、一致する_*.Java_を除くすべてのファイルでfoobarを検索する場合は、次のようにします。

_git grep foobar -- './*' ':(exclude)*.Java'
_

または、除外に_!_「短縮形」を使用します。

_git grep foobar -- './*' ':!*.Java'
_

V2.12までのgitバージョンでは、exclude pathspecを使用する場合、少なくとも1つの「包括的」pathspecが必要であることに注意してください。上記の例では、これは_./*_です(再帰的に現在のディレクトリの下にすべてを含めます)。 git v2.13ではこの制限が解除され、_git grep foobar -- ':!*.Java'_は_./*_なしで機能します。

:(top)(短縮形:_:/_)のようなものを使用して、リポジトリの先頭からすべてを含めることもできます。ただし、除外pathspecを調整して、先頭から開始することもできます:_:/!*.Java_(それ以外の場合は、現在のディレクトリの下から_*.Java_ファイルのみを除外します)。

git-scm.com (または単に_git help glossary_)のpathspecで許可されているすべての「マジックワード」に関する適切なリファレンスがあります。何らかの理由で、 kernel.org のドキュメントは、Google検索で頻繁に最初に表示される場合でも、本当に古くなっています。

171
onlynone

更新:git> = 1.9の場合、除外パターンのネイティブサポートがあります。 one's answer を参照してください。

これは逆に思えるかもしれませんが、次のように、除外パターンに一致しないファイルのリストをgit grepに渡すことができます。

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

grep -vはすべてのパスを返しますnot一致する<exclude-pattern>git ls-files--excludeパラメーターを使用しますが、これは未追跡ファイルにのみ適用されることに注意してください。

60
kynan

リポジトリに属性ファイルを作成することにより、ファイルまたはディレクトリをバイナリとしてマークできます。

$ 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]
2
coberlin

@kynanの例をベースにして、このスクリプトを作成し、ggとしてパス(~/bin/)に入れました。 git grepを使用しますが、一部の指定されたファイルタイプを回避します。

リポジトリには多数の画像があるため、画像ファイルを除外しました。これにより、リポジトリ全体を検索すると、検索時間が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にすることはできません。これは、リポジトリのルートで呼び出されるためです。そして、それは私が欲しいものではありません!

2
UlfR