Comment grep Git commit diffs ou contenus pour un certain mot?

623

Dans un référentiel de code Git, je veux répertorier toutes les validations qui contiennent un certain mot. J'ai essayé

git log -p | grep --context=4 "word"

mais cela ne me rend pas nécessairement le nom du fichier (à moins qu'il ne soit à moins de 5 lignes du mot que j'ai recherché. J'ai aussi essayé

git grep "word"

mais cela ne me donne que les fichiers présents et non l'historique.

Comment puis-je rechercher tout l'historique afin de pouvoir suivre les changements sur un mot particulier? J'ai l'intention de rechercher dans ma base de code des occurrences de mots pour suivre les modifications (recherche dans l'historique des fichiers).

Jesper Rønn-Jensen
la source

Réponses:

907

Si vous souhaitez trouver toutes les validations où le message de validation contient un mot donné, utilisez

$ git log --grep=word

Si vous voulez trouver toutes les validations où "mot" a été ajouté ou supprimé dans le contenu du fichier (pour être plus précis: où le nombre d'occurrences de "mot" a changé), c'est-à-dire rechercher le contenu de la validation , utilisez la recherche dite "pioche" avec

$ git log -Sword

Dans git moderne il y a aussi

$ git log -Gword

pour rechercher les différences dont la ligne ajoutée ou supprimée correspond à "word" (également valider le contenu ).

Notez que -Gpar défaut accepte une regex, tandis que -Saccepte une chaîne, mais peut être modifié pour accepter les regex en utilisant le --pickaxe-regex.

Pour illustrer la différence entre -S<regex> --pickaxe-regexet -G<regex>, envisagez une validation avec la différence suivante dans le même fichier:

+    return !regexec(regexp, two->ptr, 1, &regmatch, 0);
...
-    hit = !regexec(regexp, mf2.ptr, 1, &regmatch, 0);

While git log -G"regexec\(regexp"affichera cette validation, git log -S"regexec\(regexp" --pickaxe-regexne le sera pas (car le nombre d'occurrences de cette chaîne n'a pas changé).


Avec Git 2.25.1 (février 2020), la documentation est clarifiée autour de ces expressions régulières.

Voir commit 9299f84 (06 fév 2020) de Martin Ågren (``) .
(Fusionné par Junio ​​C Hamano - gitster- en commit 0d11410 , 12 fév 2020)

diff-options.txt: éviter la surcharge "regex" dans l'exemple

Signalé par: Adam Dinwoodie
Signé par: Martin Ågren Révisé
par: Taylor Blau

Lorsque nous illustrons la différence entre -Get -S(en utilisant --pickaxe-regex), nous le faisons en utilisant un exemple de diff et d' git diffinvocation impliquant "regexec", "regexp", "regmatch", ...

L'exemple est correct, mais nous pouvons faciliter le démêlage en évitant d'écrire «regex. *» À moins que cela ne soit vraiment nécessaire pour faire valoir notre argument.

Utilisez plutôt des mots inventés et non-regexy.

La git diffdocumentation comprend désormais:

Pour illustrer la différence entre -S<regex> --pickaxe-regexet -G<regex>, envisagez une validation avec la différence suivante dans le même fichier:

+    return frotz(nitfol, two->ptr, 1, 0);
...
-    hit = frotz(nitfol, mf2.ptr, 1, 0);

While git log -G"frotz\(nitfol"affichera cette validation, git log -S"frotz\(nitfol" --pickaxe-regexne le sera pas (car le nombre d'occurrences de cette chaîne n'a pas changé).

Jakub Narębski
la source
3
@TankorSmash -S<string>Recherchez les différences qui introduisent ou suppriment une instance de <string>. -G<string>Recherchez les différences dont la ligne ajoutée ou supprimée correspond à la <regex> donnée.
m-ric
1
@ m-ric Oh je vois, une seule instance de chaîne, contre une ligne entière! Merci
TankorSmash
3
@ m-ric, @TankorSmash: La différence est que -S<string>c'est plus rapide car il vérifie seulement si le nombre d'occurrences a <string>changé, tandis que les -G<string>recherches ont ajouté et supprimé des lignes dans chaque diff de validation.
Jakub Narębski
3
Si vous devez rechercher des mots avec un espace entre les deux git log --grep="my words",.
MEM
4
@MEM, --grepest différent de -Set -G. Vous pouvez citer la chaîne à chacun de ces arguments.
Acumenus
255

git logla pioche trouvera des commits avec des changements incluant "word" avec git log -Sword

u0b34a0f6ae
la source
60
Ce n'est pas tout à fait précis. -S <string> Recherchez les différences qui introduisent ou suppriment une instance de <string>. Notez que ceci est différent de la chaîne apparaissant simplement dans la sortie diff;
tymtam
4
Bien que ce soit généralement la bonne réponse, j'ai rétrogradé uniquement pour encourager les autres à lire cette réponse ( stackoverflow.com/a/1340245/586983 ) qui a 3 manières différentes et explique leurs subtilités.
jakeonrails
18
ça alors! Je ne pense pas que ce soit une bonne raison de dévaloriser une bonne réponse ... vous n'étiez pas convaincu que l'inclusion du lien dans un commentaire serait un encouragement suffisant?
Deborah
@jakeonrails, Cette réponse aurait dû être une modification de celle-ci (plus ancienne), nous n'avons donc pas ces doublons ennuyeux. Mais les gens ne veulent que la réputation, au lieu d'une page de réponses claire.
Iulian Onofrei
22

Après beaucoup d'expérimentation, je peux recommander ce qui suit, qui montre les validations qui introduisent ou suppriment des lignes contenant une expression rationnelle donnée, et affiche les modifications de texte dans chacune, avec des couleurs montrant des mots ajoutés et supprimés.

git log --pickaxe-regex -p --color-words -S "<regexp to search for>"

Il faut du temps pour courir ... ;-)

CharlesW
la source
2
C'est l'un des meilleurs à ce jour. Astuce: pour simplement lister tous les résultats sans pagination, GIT_PAGER=catajoutez la commande ou ajoutez-la| cat
Zack Morris
Spécifier un chemin ou un fichier serait beaucoup plus rapidegit log --pickaxe-regex -p --color-words -S "<regexp to search for>" <file or fiepath>
fangxing
10

Vous pouvez essayer la commande suivante:

git log --patch --color=always | less +/searching_string

ou en utilisant grepde la manière suivante:

git rev-list --all | GIT_PAGER=cat xargs git grep 'search_string'

Exécutez cette commande dans le répertoire parent où vous souhaitez rechercher.

kenorb
la source
2
J'aime cette méthode parce que les validations que je regarde ont des centaines de lignes de changements non liés, et je ne suis intéressé que par les correctifs réels qui impliquent le mot que je recherche. Pour obtenir la couleur, utilisez git log --patch --color=always | less +/searching_string.
Radon Rosborough
9

Une autre façon / syntaxe de le faire est: git log -S "word"
comme ça, vous pouvez rechercher par exemplegit log -S "with whitespaces and stuff @/#ü !"

1u-
la source
1

vim-fugitive est polyvalent pour ce type d'examen dans Vim.

Utilisez :Ggreppour le faire. Pour plus d'informations, vous pouvez installer vim-fugitive et rechercher le turorial par :help Grep. Et cet épisode: explorer-l'histoire-d'un-dépôt-git vous guidera pour faire tout cela.

Lerner Zhang
la source
1

Pour utiliser un connecteur booléen sur une expression régulière:

git log --grep '[0-9]*\|[a-z]*'

Cette expression régulière recherche l'expression régulière [0-9] * ou [az] * dans les messages de validation.

Reudismam
la source
-1

Si vous souhaitez rechercher des données sensibles afin de les supprimer de votre historique Git (c'est la raison pour laquelle j'ai atterri ici), il existe des outils pour cela. Github en tant que page d'aide dédiée à ce problème .

Voici l'essentiel de l'article:

Le BFG Repo-Cleaner est une alternative plus rapide et plus simple à la branche de filtre git pour supprimer les données indésirables. Par exemple, pour supprimer votre fichier contenant des données sensibles et laisser votre dernier commit intact), exécutez:

bfg --delete-files YOUR-FILE-WITH-SENSITIVE-DATA

Pour remplacer tout le texte répertorié dans passwords.txt où qu'il se trouve dans l'historique de votre référentiel, exécutez:

bfg --replace-text passwords.txt

Voir la documentation de BFG Repo-Cleaner pour une utilisation complète et des instructions de téléchargement.

edelans
la source
Vous voudrez peut-être ajouter cette réponse à stackoverflow.com/questions/872565/… au lieu d'ici
lacostenycoder