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


144

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

大規模なgitリポジトリで直接git grep使用grepすると動作が遅すぎるため、使用する必要があります。


:bashの上でそれを行うことは可能な回避策になりstackoverflow.com/questions/216995/...
チロSantilli郝海东冠状病六四事件法轮功

8
この機能は、1.9.0で追加された以下の私の答えを参照
onlynone

回答:


17

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

あなたは置くことができ*.dll、その後.gitignoreファイルにgit grep --exclude-standard

EDITは見onlynoneの答えを gitの1.9.0は、それが可能なので、。


2
これは以前は真実でしたが、もはやgitで可能になりました。下記の本当の答えがどうあるべきかを参照してください:stackoverflow.com/a/30084612/1391445
user1391445

205

git 1.9.0では、「魔法の言葉」excludepathspecs に追加されました。したがって、foobar一致*.javaするものを除くすべてのファイルを検索する場合は、次のようにできます。

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(または)pathspecで許可されているすべての「魔法の言葉」についての適切なリファレンスがあります。何らかの理由で、kernel.orgのドキュメントは、Google検索で最初に表示されることが多いにもかかわらず、実際には古くなっています。git help glossary


4
git grep clock.gettime -- './*' ':!arch/**' ':!drivers/**'複数のディレクトリ全体を除外します。再帰を防ぐことはできないと思います。
Ciro Santilli郝海东冠状病六四事件法轮功

2
頻繁に使用する場合は、除外してgitエイリアスを作成できますgit config alias.mygrep '!git grep "$@" -- "${GIT_PREFIX}/*" ":!*.java*" #'。その後だけgit mygrep foobarです。(エイリアスシェル#トリック現在のディレクトリを使用します。)
medmunds 2017年

このソリューションで解決できない問題は、報告されたファイルのパスがWCルートからの相対パスであることです。したがって、WCのサブディレクトリにいる場合は、見つかったファイルのパスをそのまま使用することはできません(例:少ない場合)。ただし、一般的なパスをジャンクする必要があります。これに対する解決策はありますか(自分でemped sedする必要はありません)?[win7のgit bash]
elonderin 2017

1
@elonderinこのソリューションは、一致したファイルのレポート方法とは関係ありません。しかし、私はちょうどしようとしたgit grepgit ls-files、カレントディレクトリからの相対サブディレクトリとの両方のレポートのファイル名から(あなたが使用している場合でも、':(top)'PATHSPEC含まれます)。どちらのコマンドにも、--full-nameルートに関連する名前を報告するオプションがありますが、デフォルトではオフになっています。
nonenone '28

1
私はgitエイリアスを使用しないのでbash関数を作成しましたが、gitエイリアスの方が良いかもしれませんgist.github.com/cmdcolin/04e2378b60f4457a41904c659368066f
Colin D

62

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

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

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

grep -v一致しないすべてのパスを返します<exclude-pattern>。注git ls-filesまた、かかる--excludeパラメータを、それだけに適用される人跡未踏のファイル


これをありがとう!Git grepはack&coよりはるかに高速ですが、任意のパスを除外できないので、いささか不便です:)
TomaszZielińskiJun

2
残念ながら、私のリポジトリにはたくさんのファイルがあります。@kynanのアプローチを試してみると、「-bash:/ usr / bin / git:引数リストが長すぎます」
Benissimo、

2
これにより、Benissimoの「引数リストが長すぎる」問題と、bashで解釈されるファイル名の文字([]など)またはリポジトリにスペースを含むファイル名の問題が解決されます。git ls-files | grep -v <exclue-pattern> | xargs -d '\ n' git grep <pattern>
Scout

2
nonenoneの答えのみを確認してください。これをgit(の最新バージョン)内で完全に実行する可能性があります。
デビッド

なぜ反対票?この回答は、1.9より前のgitバージョンにも適用されます。一人だけの回答を記載したメモを追加しました。
kynan

5

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

$ 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

@kynanの例をベースにして、このスクリプトを作成し、パス(~/bin/)にとして配置しました gggit grep特定のファイルタイプを使用しますが、回避します。

私たちのレポには画像がたくさんあるので、画像ファイルを除外しました。これにより、レポ全体を検索すると、serchtimeが1/3に下がります。しかし、スクリプトを簡単に変更して、他のファイルタイプやジェルパターンを除外することができます。

#!/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

よると、このことは、事に名前を付けることが可能でなければならないgit-ggなど、通常のgitコマンドとしてそれを呼び出すことができます。

$ git gg searchstring

しかし、私はこれを機能させることができません。でスクリプトを作成し~/bin/、でgit-ggシンボリックリンクを作成しました/usr/lib/git-core/

注2

コマンドshはレポのルートで呼び出されるため、通常のgit-alias にすることはできません。そして、それは私が望むものではありません!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.