Belirli dizinleri / dosyaları git grep aramasından hariç tutma


144

Git deposunu kullanarak arama yaparken belirli yolları / dizinleri / dosyaları dışlamanın bir yolu var mı git grep? --excludeNormal grepkomuttaki seçeneğe benzer bir şey mi?

git grepKullanmak gerekir çünkü grepdoğrudan kullanarak büyük git depolarda çok yavaş çalışır.


Bunu bash üzerinde yapmak olası bir çözüm olacaktır: stackoverflow.com/questions/216995/…
Ciro Santilli 法轮功 冠状 病 六四 事件

8
Bu özellik
1.9.0'da

Yanıtlar:



206

Git 1.9.0'da "sihirli kelime" s'ye excludeeklendi pathspec. Eşleşenler foobarhariç her dosyada arama *.javayapmak istiyorsanız şunları yapabilirsiniz:

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

Veya !hariç tutmak için "kısa formu" kullanarak :

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

V2.12'ye kadar git sürümlerinde, bir hariç tutma kullanırken pathspecen az bir "dahil" olması gerektiğini unutmayın pathspec. Yukarıdaki örneklerde bu ./*(geçerli dizinin altındaki her şeyi özyineli olarak ekleyin). Git v2.13 bu kısıtlama kaldırıldı ve git grep foobar -- ':!*.java'olmadan çalışır ./*.

Reponun üst kısmındaki her şeyi dahil etmek için :(top)(kısa form :) gibi bir şey de kullanabilirsiniz :/. Ancak, muhtemelen hariç tutma pathspecdurumunuzu en baştan başlayacak şekilde de ayarlamak istersiniz : :/!*.java(aksi takdirde yalnızca *.javageçerli dizininizin altındaki dosyaları hariç tutar ).

Bir izin tüm "sihirli kelime" için iyi bir referans var pathspecen git-scm.com (ya da sadece git help glossary). Bazı nedenlerden dolayı, kernel.org'daki dokümanlar, Google aramalarında sıklıkla ilk gelmelerine rağmen gerçekten güncel değil.


4
git grep clock.gettime -- './*' ':!arch/**' ':!drivers/**'birden çok tüm dizini hariç tutmak için. Yine de özyinelemeyi önlediğini sanmıyorum.
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功

2
Sık kullanım için, istisnalar ile bir git takma yapabilirsiniz: git config alias.mygrep '!git grep "$@" -- "${GIT_PREFIX}/*" ":!*.java*" #'. O zaman sadece git mygrep foobar. (Kullanma takma # trick kabuk ve geçerli dir .)
medmunds

Bu çözüm ile çözemiyorum sorun dosyaların bildirilen yolları WC kökü göreli olmasıdır. Yani, eğer WC alt dizin içinde iseniz, ben sadece olduğu gibi bulunan dosya (lar) yolunu kullanamazsınız (örneğin daha az) ama ortak yollar junc zorunda. Bunun bir çözümü var mı (kendimi zorlamak zorunda kalmadan)? [
git7

1
@elonderin bu çözümün eşleşen dosyaların nasıl rapor edildiği ile ilgisi yoktur. Ama ben sadece bir git grepve git ls-filesalt dizinlerden denedim ve her iki dosya adlarını geçerli dizine göre rapor (hatta ':(top)'pathspec dahil kullandığınızda bile ). Her iki komutun da --full-nameadları köke göre raporlama seçeneği vardır, ancak bu varsayılan olarak kapalıdır.
onlynone

1
Git takma adları kullanmıyorum, bu yüzden bir bash işlevi yaptım, ancak muhtemelen bir git takma adı daha iyi gist.github.com/cmdcolin/04e2378b60f4457a41904c659368066f
Colin D

62

Güncelleme: Git> = 1.9 için bkz desenleri dışlamak için doğal destek var onlyone cevabını .

Bu geriye doğru görünebilir, ancak hariç tutma düzeninizle eşleşmeyen dosyaların bir listesini şöyle yapabilirsiniz git grep:

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

grep -vHer yol verir değil eşleştirme <exclude-pattern>. Bunun git ls-filesbir --excludeparametre aldığını, ancak yalnızca izlenmeyen dosyalara uygulandığını unutmayın .


Bunun için teşekkürler! Git grep, ack & co'dan çok daha hızlıdır, ancak keyfi yolları dışlayamamak, konuşmak için biraz rahatsız edici oldu :)
Tomasz Zieliński

2
Ne yazık ki depomda çok fazla dosya var. @ Kynan'ın yaklaşımını denediğimde: "-bash: / usr / bin / git: Bağımsız değişken listesi çok uzun"
Benissimo

2
Bu, hem Benissimo'nun "Bağımsız değişken listesi çok uzun" sorununu hem de bash ([]) gibi yorumlanan dosya adı karakterleriyle veya havuzdaki boşlukları içeren dosya adlarıyla ilgili sorunumu çözmelidir: git ls-files | grep -v <exclue-pattern> | xargs -d '\ n' git grep <desen> -
İzci

2
Sadece yanıtını kontrol edin, muhtemelen bunu tamamen git (modern versiyonları) içinde yapmak mümkündür.
David

Neden inişler? Bu cevap 1.9'dan önceki git sürümleri için de geçerlidir. Onlyone'un cevabına ilişkin bir not ekledim.
kynan

5

Deponuzda bir öznitelik dosyası oluşturarak dosyaları veya dizinleri ikili olarak işaretleyebilirsiniz, ör.

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

İkili dosyalardaki eşleşmeler dahil satırı olmadan listelenir, ör.

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

2

@Kynan tarafından örnek olarak bu komut dosyasını hazırladım ve yoluma ( ~/bin/) olarak koydum gg. git grepBelirtilen bazı dosya türlerini kullanır ancak bunlardan kaçınır.

Repomuzda çok fazla resim var, bu yüzden imagefiles'i dışladım ve tüm repoyu ararsam serchtime'ı 1/3'e indirir. Ancak komut dosyası, diğer dosya türlerini veya geleral desenleri dışlayacak şekilde kolayca değiştirilebilir.

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

Not 1

Göre bu o şey söyle mümkün olmalıdır git-ggve benzeri düzenli git komutu olarak adlandırmak mümkün:

$ git gg searchstring

Ama bunu çalıştıramıyorum. Komut dosyasını benim oluşturdum ~/bin/ve bir git-ggsembolik link yaptım /usr/lib/git-core/.

Not 2

Komut normal bir shgit-alias olarak yapılamaz çünkü repo kökünde çağrılır. Ve istediğim bu değil!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.