200 votes

Comment exclure certains répertoires/fichiers de la recherche git grep ?

Existe-t-il un moyen d'exclure certains chemins/répertoires/fichiers lors d'une recherche dans un dépôt git à l'aide de la fonction git grep ? Quelque chose de similaire à la --exclude dans l'option normale grep commande ?

J'ai besoin d'utiliser git grep car en utilisant grep fonctionne directement trop lentement sur les gros dépôts git.

0 votes

Le faire sur bash serait une solution de contournement possible : stackoverflow.com/questions/216995/

9 votes

Cette fonctionnalité a été ajoutée dans la version 1.9.0. voir ma réponse ci-dessous

301voto

onlynone Points 472

Dans git 1.9.0, le "mot magique" exclude a été ajouté à pathspec s. Ainsi, si vous souhaitez rechercher foobar dans tous les fichiers, sauf ceux qui correspondent à *.java vous pouvez faire :

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

Ou en utilisant le ! "Forme courte" pour exclure :

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

Notez que dans les versions de git jusqu'à la v2.12, lors de l'utilisation d'un exclude pathspec vous devez avoir au moins un "inclusif". pathspec . Dans les exemples ci-dessus, il faut ajouter ./* (inclure récursivement tout ce qui se trouve sous le répertoire courant) quelque part après la balise -- également. Dans git v2.13 cette restriction a été levée et git grep foobar -- ':!*.java' fonctionne sans le ./* .

Il existe une bonne référence pour tous les "mots magiques" autorisés dans une pathspec à l'adresse git-scm.com (ou simplement git help glossary ).

66voto

kynan Points 2334

Mise à jour : Pour git >= 1.9, il y a un support natif pour les motifs d'exclusion, cf. réponse de onlyone .

Cela peut sembler contradictoire, mais vous pouvez passer une liste de fichiers ne correspondant pas à votre modèle d'exclusion à git grep comme ça :

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

grep -v renvoie tous les chemins no correspondant à <exclude-pattern> . Notez que git ls-files prend également un --exclude mais cela ne s'applique qu'à fichiers non suivis .

1 votes

Merci pour cela ! Git grep est tellement plus rapide que ack & co mais ne pas pouvoir exclure des chemins arbitraires était un peu trop gênant pour ainsi dire :)

2 votes

Malheureusement mon repo a beaucoup de fichiers. Quand j'essaie l'approche de @kynan, j'obtiens : "-bash : /usr/bin/git : Argument list too long"

2 votes

Cela devrait résoudre à la fois le problème "Argument list too long" de Benissimo et mon problème avec les caractères de nom de fichier interprétés par bash (comme []) ou les noms de fichier contenant des espaces dans le dépôt : git ls-files | grep -v <exclue-pattern> | xargs -d ' \n ' git grep <pattern> --

24voto

coberlin Points 61

Vous pouvez marquer les fichiers ou les répertoires comme binaires en créant un fichier d'attributs dans votre référentiel, par exemple

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

Les correspondances dans les fichiers binaires sont listées sans la ligne d'inclusion, par ex.

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

19voto

CharlesB Points 27070

Ce n'est pas possible, mais a été discuté récemment . Solution de rechange proposée dans le lien :

Vous pouvez mettre *.dll au fichier .gitignore puis git grep --exclude-standard .

Voir EDIT réponse de onlynone Depuis git 1.9.0, c'est possible.

2 votes

C'était vrai auparavant mais plus maintenant, c'est désormais possible dans git. Voyez ce qui devrait être la vraie réponse ci-dessous : stackoverflow.com/a/30084612/1391445

2voto

UlfR Points 677

Avec l'exemple de @kynan comme base j'ai fait ce script et l'ai mis dans mon chemin ( ~/bin/ ) comme gg . Il utilise git grep mais évite certains types de fichiers spécifiés.

Dans notre référentiel, il y a beaucoup d'images. J'ai donc exclu les fichiers images, ce qui réduit le temps de recherche à un tiers si je recherche dans l'ensemble du référentiel. Mais le script pourrait facilement être modifié pour exclure d'autres types de fichiers ou 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                                                                      

Note 1

Selon ce il devrait être possible de nommer la chose git-gg et être capable de l'appeler comme une commande git normale comme :

$ git gg searchstring

Mais je n'arrive pas à le faire fonctionner. J'ai crée le script dans mon ~/bin/ git-gg lien symbolique dans /usr/lib/git-core/ .

Note 2

La commande ne peut pas être transformée en une commande régulière sh git-alias car il sera alors invoqué à la racine du repo. Et ce n'est pas ce que je veux !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X