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.
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, puisgit grep --exclude-standard
.
EDIT voir la réponse de onlynone , depuis git 1.9.0 c'est possible.
Dans Git 1.9.0, le "mot magique" exclude
a été ajouté à pathspec
s. 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.
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.
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!
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]