2012-05-02 16 views
97

Gibt es eine Möglichkeit, git-Repository mit git grep suchen, aber bestimmte Pfade/Verzeichnisse/Dateien aus der Suche auszuschließen? Wie die Option --exclude im normalen grep-Befehl.Wie bestimmte Verzeichnisse/Dateien von git grep search ausschließen

Wenn Sie neugierig sind: Ich möchte nicht normal grep verwenden, da es viel langsamer als git grep ist, wenn die Größe des Git-Repository groß ist.

+0

Doing es auf Bash wäre eine mögliche Problemumgehung: http://StackOverflow.com/Questions/216995/How-can-i-use-inverse-or-negative-wildcards-when-pattern-matching-in-a -unix-linu –

+5

Diese Funktion wurde in 1.9.0 hinzugefügt [siehe meine Antwort unten] (/ a/30084612/436287) – onlynone

Antwort

16

Es ist nicht möglich, aber has been discussed recently. Vorgeschlagene Abhilfe in Verbindung:

können Sie *.dll setzen Datei .gitignore dann git grep --exclude-standard.

EDIT siehe nurnone Antwort, seit Git 1.9.0 ist es möglich.

+0

Irgendeine Idee, wenn das immer noch nicht möglich ist? Oder hat sich in den letzten 2 Jahren etwas verändert? –

+3

@ mustafa.0x siehe die meistbeantwortete Antwort, es ist möglich – CharlesB

+1

Überprüfen Sie nur die Antwort, es ist möglich, dies vollständig innerhalb von git jetzt zu tun. – David

54

Aktualisierung: Für Git> = 1.9 gibt es native Unterstützung für Ausschlussmuster, siehe onlyone's answer.

Dies kann nach hinten scheinen, aber Sie können eine Liste von Dateien passieren nicht Ihre ausschließen Muster git grep wie dies passend:

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

grep -v kehrt <exclude-pattern> jeder Weg nicht entsprechen. Beachten Sie, dass auch einen --exclude Parameter verwendet, aber das gilt nur für untracked Dateien.

+0

Danke dafür! Git Grep ist so viel schneller als Ack & Co, aber nicht in der Lage zu sein, willkürliche Pfade auszuschließen, war ein bisschen zu unbequem, sozusagen :) –

+1

Leider hat mein Repo eine Menge Dateien. Wenn ich @ kynans Ansatz versuche, bekomme ich: "-bash:/usr/bin/git: Argumentliste zu lang" – Benissimo

+1

Das sollte sowohl das "Argument list" -Problem von Benissimo als auch mein Problem mit dem von bash interpretierten dateinamen caracters lösen (wie []) oder Dateinamen mit Leerzeichen im Repository: git ls-files | grep -v | xargs -d '\ n' git grep - – Scout

2

Mit dem Beispiel von @KYNAN als Basis habe ich dieses Skript gemacht und es in meinen Pfad (~/bin/) als gg. Es verwendet git grep, vermeidet jedoch einige angegebene Dateitypen.

In unserem Repo gibt es eine Menge Bilder, also habe ich die Bilddateien ausgeschlossen, und das dauert die Serchtime auf 1/3 runter, wenn ich das ganze Repo suche. Aber das Skript könnte leicht modifiziert werden, um andere Dateitypen oder Geleralmuster auszuschließen.

#!/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 "[email protected]" -- `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 "[email protected]"; 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                  

Anmerkung 1

Nach this soll es möglich sein, das Ding git-gg zu nennen und es nennen zu können, als reguläres git Kommando:

$ git gg searchstring 

Aber ich kann Lass das nicht funktionieren. Ich erstellte das Skript in meinem ~/bin/ und machte einen git-gg Symlink in /usr/lib/git-core/.

Anmerkung 2

Der Befehl kann nicht in einen regulären sh git-Alias ​​gemacht werden, da es dann an der Wurzel des Repo aufgerufen werden. Und das will ich nicht!

122

In Git 1.9.0 wurde das "magische Wort" exclude zu pathspec s hinzugefügt.Also, wenn Sie für foobar in jeder Datei suchen möchten, außer für diejenigen, *.java passende können Sie tun:

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

Oder die ! „Kurzform“ unter Verwendung für auszuschließen:

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

Beachten Sie, dass bei Verwendung eines Ausschließen pathspec, Sie müssen mindestens eine "inklusive" pathspec haben. In den obigen Beispielen ist dies die ./* (rekursiv alles unter dem aktuellen Verzeichnis enthalten).

Sie können auch etwas wie :(top) (Kurzform:) verwenden, um alles von der Oberseite des Repos aufzunehmen. Aber dann solltest du wahrscheinlich auch deinen Exclude pathspec so anpassen, dass er auch von oben startet: :/!*.java (sonst würden nur *.java Dateien aus deinem aktuellen Verzeichnis ausgeschlossen).

Es gibt eine gute Referenz für alle "magische Wörter" erlaubt in einem pathspec um git-scm.com (oder nur git help glossary). Aus irgendeinem Grund sind die Dokumente unter kernel.org wirklich veraltet, obwohl sie oft bei Google-Suchen an erster Stelle stehen.

+1

'git grep clock.gettime - './*' ':! Arch/**' ':! Drivers/**'' um mehrere ganze Verzeichnisse auszuschließen. Ich glaube nicht, dass es die Rekursion verhindert. –

+0

Für häufige Verwendung können Sie einen Git Alias ​​mit den Ausschlüssen machen: 'git config alias.mygrep '! Git grep" $ @ "-" $ {GIT_PREFIX}/* "":! *. Java * "#'' . Dann einfach "git mygrep foobar". (Mit Alias ​​[Shell # Trick] (http://StackOverflow.com/A/39523506/647002) und [aktuelle Dir] (http://StackOverflow.com/A/22039008/647002).) – medmunds

+0

das Problem, das ich nicht kann Lösung mit dieser Lösung ist, dass die gemeldeten Pfade der Dateien relativ zum WC-Stamm sind. Also, wenn ich in einem Unterverzeichnis der WC bin, kann ich nicht einfach den Pfad der gefundenen Datei (en) verwenden (z.B. für weniger), sondern muss gemeinsame Pfade haben. Gibt es dafür eine Lösung (ohne mich selbst zu sedieren)? [git bash auf win7] – elonderin

Verwandte Themen