web-dev-qa-db-fra.com

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

Existe-t-il un moyen de rechercher le référentiel git en utilisant git grep tout en excluant certains chemins/répertoires/fichiers de la recherche? Comme l'option --exclude dans la commande grep normale. 

Si vous êtes curieux: je ne veux pas utiliser grep normal car il est beaucoup plus lent que git grep lorsque la taille du référentiel git est grande. 

111

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

Vous pouvez mettre *.dll dans le fichier .gitignore, puis git grep --exclude-standard

EDIT voir la réponse de onlynone , depuis git 1.9.0 c'est possible. 

16
CharlesB

Dans Git 1.9.0, le "mot magique" exclude a été ajouté à pathspecs. Donc, si vous voulez rechercher foobar dans tous les fichiers sauf ceux correspondant à *.Java, vous pouvez faire:

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

Ou en utilisant le ! "forme abrégée" pour exclure:

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

Notez que lorsque vous utilisez une exclusion pathspec, vous devez avoir au moins un "inclusif" pathspec. Dans les exemples ci-dessus, il s'agit du ./* (tout inclure sous le répertoire actuel).

Vous pouvez également utiliser quelque chose comme :(top) (forme abrégée: :/) pour tout inclure à partir du haut du référentiel. Mais alors, vous voudrez probablement aussi ajuster votre exclusion pathspec pour qu'elle commence également par le haut: :/!*.Java (sinon, seuls les fichiers *.Java seront exclus du sous-répertoire actuel).

Il existe une bonne référence pour tous les "mots magiques" autorisés dans un pathspec à git-scm.com (ou simplement git help glossary). Pour une raison quelconque, les documents de kernel.org sont vraiment obsolètes, même s’ils apparaissent souvent en premier dans les recherches sur Google.

154
onlynone

Update: Pour git> = 1.9, il existe une prise en charge native des modèles d'exclusion, voir la réponse de one-one .

Cela peut sembler arriéré, mais vous pouvez passer une liste de fichiers ne correspondant pas à votre modèle d'exclusion à git grep comme ceci:

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

grep -v renvoie tous les chemins non correspondants <exclude-pattern>. Notez que git ls-files prend également un paramètre --exclude, mais il ne s'applique qu'à fichiers non suivis.

59
kynan

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

Dans notre repo, il y a beaucoup d'images, j'ai donc exclu les fichiers image, ce qui ramène le temps de rotation à 1/3 si je cherche dans tout le repo. Mais le script pourrait facilement être modifié pour exclure d'autres types de fichiers ou modèles de fichiers.

#!/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 this , il devrait être possible de nommer la chose git-gg et de l’appeler comme une commande git normale comme:

$ git gg searchstring

Mais je ne peux pas que cela fonctionne. J'ai créé le script dans mon ~/bin/ et créé un lien symbolique git-gg dans /usr/lib/git-core/.

Note 2

La commande ne peut pas être transformée en un sh git-alias normal car elle sera ensuite invoquée à la racine du référentiel. Et ce n'est pas ce que je veux!

2
UlfR

Vous pouvez marquer des fichiers ou des 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 répertoriées sans la ligne incluse, par exemple.

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