web-dev-qa-db-fra.com

Est-il préférable d'utiliser git grep plutôt que grep si l'on souhaite effectuer une recherche dans le code source versionné?

Dans un référentiel git, existe-t-il une différence/avantage utilisant git grep par rapport au bon vieux grep?
Un exemple serait?

39
Jim

Les deux sont très similaires. La principale différence est que git grep utilise par défaut la recherche dans les fichiers suivis par git.

Exemples

Si je veux trouver foo dans mon projet, je peux utiliser git grep ou bon vieux autonome grep:

git grep foo
grep -R foo .

La version git grep ne cherchera que dans les fichiers suivis par git, alors que la version grep cherchera dans tout le répertoire. Jusqu'ici si semblable. l'un ou l'autre pourrait être mieux dépendant de ce que vous voulez réaliser.

Que faire si nous voulons limiter la recherche à uniquement les fichiers .rb?

git grep foo -- *.rb
grep -R --include=*.rb foo .

La vieille version grep devient un peu plus verbeuse, mais si vous êtes habitué à utiliser grep, cela ne posera peut-être pas un problème. Ils ne vont toujours pas rechercher exactement les mêmes fichiers, mais encore une fois, cela dépend de ce que vous voulez réaliser.

Qu'en est-il de la recherche dans la version précédente du projet?

git grep foo HEAD^
git checkout HEAD^; grep -R foo .; git checkout -

C'est ici que git grep fait une réelle différence: vous pouvez effectuer une recherche dans une autre révision du projet sans l'avoir extrait au préalable. Ce n'est pas une situation qui arrive trop souvent pour moi cependant; J'ai l'habitude de chercher dans la version du projet que j'ai extrait.

Configuration de git grep

Certaines variables git config modifient le comportement de git grep et évitent de devoir passer deux arguments en ligne de commande:

  • grep.lineNumber: affichez toujours les numéros de ligne des correspondances (vous pouvez passer -n à la fois grep et git grep pour obtenir ce comportement)
  • grep.extendedRegexp: utilisez toujours des expressions régulières étendues (vous pouvez transmettre -E à grep et git grep pour obtenir ce comportement)

En pratique

En pratique, gg est associé à git grep -En et cela fait presque toujours ce que je veux.

35
georgebrock

Le principal avantage de git grep est qu’il peut trouver les modèles dans le référentiel git, i. e. également dans d'autres que la version actuelle de la source. Cela ne peut pas être fait en utilisant la variable standard grep bien sûr. De plus, il y a beaucoup plus de fonctionnalités dans git grep telles que l'arithmétique des motifs (des choses comme git grep -e pattern1 --and --not \( -e pattern2 -e pattern3 \)), la recherche dans l'arborescence à l'aide de glob (des choses comme git grep pattern -- '*.[ch]' pour rechercher uniquement dans les fichiers .c et .h) et quelques autres.

Voici un exemple de session pour rechercher dans une révision plus ancienne:

$ mkdir git-test                 # create fresh repository
$ cd git-test/
$ git init .
Initialized empty Git repository in /home/alfe/git-test/.git/
$ echo eins zwei drei > bla      # create example file
$ git add bla                    # add and commit it
$ git commit bla
[master (root-commit) 7494515] .
 1 file changed, 1 insertion(+)
 create mode 100644 bla
$ echo vier fuenf sechs > bla    # perform a change on that file
$ git commit -m 'increase' bla   # commit it
[master 062488e] increase
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git grep eins | cat            # grep for outdated pattern in current version
                                  # (finds nothing)
$ git grep eins master^ | cat    # grep for outdated pattern on former version
                                  # finds it:
master^:bla:eins zwei drei
13
Alfe

Si vous recherchez des modèles/chaînes dans un référentiel git (c'est-à-dire dans des fichiers déjà suivis), alors oui, git grep devrait être beaucoup plus rapide, en général, que grep normal, car il est indexé. (Vous pouvez essayer cela manuellement, le git-grep devrait être sensiblement plus rapide)

2
PlagueHammer

git grep recherche uniquement dans les fichiers suivis dans le référentiel.

Avec grep, vous devez passer la liste des fichiers dans lesquels vous souhaitez effectuer la recherche et vous devez filtrer vous-même tous les fichiers non suivis.

Donc, si vous recherchez quelque chose que vous savez se trouver dans le dépôt, git grep vous fait gagner du temps car tout ce que vous avez à faire est de fournir le modèle. C'est également utile pour ne pas avoir à chercher dans tout ce qui n'est pas suivi dans le repo.

1
Schleis

Si vous recherchez dans un dépôt Git, git grep est plus rapide.

Et avec Git 2.20 (T4 2018), il est également plus compatible, en ce qui concerne les options, avec la variable grep.

Comme indiqué dans ce git grep "liste de souhaits" :

J'utilise souvent "grep -r $pattern" pour récursivement grep un arbre source.
Si cela prend trop de temps, je tape ^C et marque "git" devant la ligne de commande, puis je le relance.
Git se plaint alors que "error: unknown switchr '" because "git grep`" est naturellement récursif.

Pourrions-nous avoir "git grep -r" accepter l'argument de compatibilité?
D'autres commutateurs importants de grep, tels que "-i", sont compatibles. L'ajout de -r améliorerait la convivialité.

Ceci est maintenant (Git 2.20, Q4 2018) fait:

Voir commit 0a09e5e (01 oct 2018) de René Scharfe (rscharfe) .
Proposé par: Junio ​​C Hamano (gitster) .
(Fusion par Junio ​​C Hamano - gitster - in commit 9822b8f , 19 octobre 2018)

grep: ajouter -r/--[no-]recursive

Reconnaître -r et --recursive comme synonymes de --max-depth=-1 pour des raisons de compatibilité avec GNU grep; c'est toujours la valeur par défaut pour git grep.

Cela ajoute également --no-recursive comme synonyme de --max-depth=0 gratuitement, , Ce qui est bienvenu pour des raisons d’intégralité et de cohérence.

Corrigez la description de --max-depth alors que nous y sommes. Les valeurs négatives autres que -1 désactivent la récursivité, c’est-à-dire qu’elles équivalent à --max-depth=0.

0
VonC