Comment faire une recherche dans l'historique de Git ?

J'ai supprimé un fichier ou du code dans un fichier à un moment donné dans le passé. Puis-je faire une recherche dans le contenu (pas dans les messages de validation) ?

Une très mauvaise solution est de grepter le journal :

git log -p | grep <pattern>

Cependant, cela ne renvoie pas directement le hash du commit. J'ai joué avec git grep en vain.

Solution

Pour rechercher le contenu d'un commit (c'est-à-dire les lignes de source réelles, par opposition aux messages de commit et autres), vous devez faire ce qui suit :

git grep  $(git rev-list --all)

git rev-list --all | xargs git grep fonctionnera si vous rencontrez une erreur "Argument list too long".

Si vous voulez limiter la recherche à un sous-arbre (par exemple, "lib/util"), vous devrez le passer à la sous-commande rev-list et à grep également :

git grep  $(git rev-list --all -- lib/util) -- lib/util

Ceci va rechercher regexp dans tous vos textes de commit.

La raison pour laquelle vous passez le chemin dans les deux commandes est que rev-list retournera la liste des révisions où toutes les modifications de lib/util ont eu lieu, mais vous devez aussi le passer à grep pour qu'il ne cherche que dans lib/util.

Imaginez le scénario suivant : grep pourrait trouver le même `sur d'autres fichiers qui sont contenus dans la même révision retournée parrev-list` (même s'il n'y a pas eu de modification de ce fichier sur cette révision).

Voici d'autres façons utiles de rechercher votre source :

Rechercher dans l'arbre de travail le texte correspondant à l'expression régulière regexp :

git grep 

Rechercher dans l'arbre de travail les lignes de texte correspondant à l'expression régulière regexp1 ou regexp2 :

git grep -e  [--or] -e 

Rechercher dans l'arbre de travail les lignes de texte correspondant aux expressions régulières regexp1 et regexp2, en indiquant uniquement les chemins d'accès aux fichiers :

git grep -e  --and -e 

Recherche dans l'arbre de travail des fichiers dont les lignes de texte correspondent à l'expression régulière regexp1 et aux lignes de texte correspondant à l'expression régulière regexp2 :

git grep -l --all-match -e  -e 

Rechercher dans l'arbre de travail les lignes de texte modifiées correspondant au motif :

git diff --unified=0 | grep 

Rechercher dans toutes les révisions le texte correspondant à l'expression régulière regexp :

git grep  $(git rev-list --all)

Rechercher dans toutes les révisions entre rev1 et rev2 le texte correspondant à l'expression régulière regexp :

git grep  $(git rev-list ..)
Commentaires (19)

Vous devez utiliser l'option [pickaxe (-S)][4] de [git log][1].

pour rechercher Foo :

git log -SFoo -- path_containing_change 
git log -SFoo --since=2009.1.1 --until=2010.1.1 -- path_containing_change

Voir Historique de Git - retrouver une ligne perdue par mot-clé pour plus d'informations.


Comme [Jakub Narębski][3] l'a commenté :

  • ceci s'intéresse aux différences qui introduisent ou suppriment une instance de ``.
    Cela signifie généralement "les révisions où vous avez ajouté ou supprimé une ligne avec 'Foo'".

  • L'option --pickaxe-regex vous permet d'utiliser une regex POSIX étendue au lieu de rechercher une chaîne de caractères.


Comme Rob l'a fait remarquer, cette recherche est sensible à la casse - il a ouvert une question complémentaire sur la façon de rechercher sans tenir compte de la casse.

[1] : http://git-scm.com/docs/git-log

[3] : https://stackoverflow.com/users/46058/jakub-narebski [4] : https://git-scm.com/docs/git-log#git-log--Sltstringgt

Commentaires (7)

Donc, vous essayez de parcourir les anciennes versions du code pour voir où quelque chose existe en dernier ?

Si je faisais cela, j'utiliserais probablement [git bisect][1]. En utilisant bisect, vous pouvez spécifier une bonne version connue, une mauvaise version connue, et un script simple qui fait une vérification pour voir si la version est bonne ou mauvaise (dans ce cas, un grep pour voir si le code que vous recherchez est présent). L'exécution de ce script permettra de trouver quand le code a été supprimé.

[1] : http://www.kernel.org/pub/software/scm/git/docs/git-bisect.html

Commentaires (3)