Question Comment grep (rechercher) code commis dans l'histoire git?


J'ai supprimé un fichier ou du code dans un fichier par le passé. Puis-je grep dans le contenu (pas dans les messages de validation)?

Une solution très pauvre est de grep le journal:

git log -p | grep <pattern>

Cependant, cela ne retourne pas le hash de commit tout de suite. J'ai joué avec git grep en vain.


1112
2018-05-28 11:36


origine


Réponses:


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

git grep <regexp> $(git rev-list --all)

Mises à jour: git rev-list --all | xargs git grep expression fonctionnera si vous rencontrez une erreur "Liste d'arguments trop longue"

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

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

Cela va grep à travers tout votre texte de validation pour regexp.

La raison de passer le chemin dans les deux commandes est parce que rev-list retournera la liste des révisions où tous les changements à lib/util arrivé, mais aussi vous devez passer à grep pour qu'il ne cherche que sur lib/util.

Imaginez le scénario suivant: grep pourrait trouver la même chose <regexp> sur d'autres fichiers qui sont contenus dans la même révision retournée par rev-list (même s'il n'y avait pas de changement à ce fichier sur cette révision).

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

Rechercher l'arbre de travail pour l'expression rationnelle de l'expression rationnelle correspondant au texte:

git grep <regexp>

Recherche dans l'arborescence des lignes de texte correspondant à l'expression régulière regexp1 ou regexp2:

git grep -e <regexp1> [--or] -e <regexp2>

Recherchez l'arbre de travail pour les lignes de texte correspondant à l'expression rationnelle regexp1 et regexp2, en indiquant uniquement les chemins d'accès aux fichiers:

git grep -e <regexp1> --and -e <regexp2>

Recherchez l'arborescence de travail pour les fichiers qui ont des lignes de texte correspondant à l'expression régulière regexp1 et des lignes de texte correspondant à l'expression régulière regexp2:

git grep -l --all-match -e <regexp1> -e <regexp2>

Recherche arbre de travail pour les lignes modifiées du modèle de correspondance de texte:

git diff --unified=0 | grep <pattern>

Rechercher toutes les révisions pour le texte correspondant expression rationnelle expression rationnelle:

git grep <regexp> $(git rev-list --all)

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

git grep <regexp> $(git rev-list <rev1>..<rev2>)

1483
2018-05-28 13:47



Vous devriez utiliser le pioche (-S) option de git log

Rechercher Foo:

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

Voir Git history - recherche de ligne perdue par mot clé pour plus.


Comme Jakub Narębski a commenté:

  • ce recherche les différences qui introduisent ou suppriment une instance de <string>.
    Cela signifie généralement "révisions où vous avez ajouté ou supprimé la ligne avec" Foo "".

  • la --pickaxe-regex Cette option vous permet d'utiliser une extension regex POSIX au lieu de rechercher une chaîne.


Comme Rob commenté, cette recherche est sensible à la casse - il a ouvert une question de suivi sur la façon de rechercher insensible à la casse.


439
2018-05-28 11:57



Ma façon préférée de le faire est avec git logde -G option (ajoutée dans la version 1.7.4).

-G<regex>
       Look for differences whose added or removed line matches the given <regex>.

Il y a une différence subtile entre la façon dont -G et -S Les options déterminent si un commit correspond:

  • le -S option compte essentiellement le nombre de fois que votre recherche correspond dans un fichier avant et après une validation. La validation est affichée dans le journal si les comptes avant et après sont différents. Cela ne montrera pas, par exemple, les commits où une ligne correspondant à votre recherche a été déplacée.
  • Avec le -G option, la validation est affichée dans le journal si votre recherche correspond à une ligne ajoutée, supprimée ou modifiée.

Prenez ce commit comme exemple:

diff --git a/test b/test
index dddc242..60a8ba6 100644
--- a/test
+++ b/test
@@ -1 +1 @@
-hello hello
+hello goodbye hello

Étant donné que le nombre de fois que "Bonjour" apparaît dans le fichier est le même avant et après cette validation, il ne correspond pas à l'aide de -Shello. Cependant, comme il y a eu un changement de ligne hello, le commit sera montré en utilisant -Ghello.


204
2017-09-14 18:34



Si vous voulez parcourir les changements de code (voir ce qui a réellement été changé avec le mot donné dans l'histoire entière) allez-y patch mode - J'ai trouvé une combinaison très utile de faire:

git log -p
# hit '/' for search mode
# type in the word you are searching
# if the first search is not relevant hit 'n' for next (like in vim ;) )

33
2018-04-17 08:17



j'ai pris La réponse de Jeet et l'a adapté à Windows (grâce à cette réponse):

FOR /F %x IN ('"git rev-list --all"') DO @git grep <regex> %x > out.txt

Notez que pour moi, pour une raison quelconque, le commit réel qui a supprimé cette regex n'apparaissait pas dans la sortie de la commande, mais plutôt un commit avant celui-ci.


22
2017-11-17 09:35



Rechercher dans toute révision, tous les fichiers:

git rev-list --all | xargs git grep <regexp>

Rechercher uniquement dans certains fichiers donnés, par exemple des fichiers xml:

git rev-list --all | xargs -I{} git grep <regexp> {} -- "*.xml"

Les lignes de résultat devraient ressembler à ceci: 6988bec26b1503d45eb0b2e8a4364afb87dde7af: bla.xml: texte de la ligne trouvée ...

Vous pouvez alors obtenir plus d'informations comme auteur, date, diff en utilisant git show:

git show 6988bec26b1503d45eb0b2e8a4364afb87dde7af

10
2018-04-02 15:03



git log peut être un moyen plus efficace de rechercher du texte dans toutes les branches, en particulier s'il y a beaucoup de correspondances, et vous souhaitez voir les changements les plus récents (pertinents) en premier.

git log -p --all -S 'search string'
git log -p --all -G 'match regular expression'

Cette liste de commandes de journal valide que vous ajoutez ou supprimez la chaîne / regex de recherche donnée, (généralement) plus récente en premier. le -p L'option provoque l'affichage du diff pertinent où le motif a été ajouté ou supprimé, de sorte que vous pouvez le voir en contexte.

Après avoir trouvé un commit pertinent qui ajoute le texte que vous cherchiez (par exemple, 8beeff00d), trouvez les branches qui contiennent le commit:

git branch -a --contains 8beeff00d

8
2018-06-23 00:38



Pour quelqu'un d'autre qui essaie de le faire dans SourceTree, il n'y a pas de commande directe dans l'interface utilisateur pour cela (à partir de la version 1.6.21.0). Cependant, vous pouvez utiliser les commandes spécifiées dans la réponse acceptée en ouvrant Terminal fenêtre (bouton disponible dans la barre d'outils principale) et les copier / coller.

Note: SourceTree's Chercher La vue peut partiellement faire de la recherche de texte pour vous. presse Ctrl + 3 pour accéder à l'affichage Recherche (ou cliquez sur l'onglet Rechercher disponible en bas). De l'extrême droite, définissez le type de recherche sur Changements de fichier puis tapez la chaîne que vous souhaitez rechercher. Cette méthode a les limitations suivantes par rapport à la commande ci-dessus:

  1. SourceTree affiche uniquement le commet qui contiennent le mot de recherche dans l'un des fichiers modifiés. Trouver le fichier exact qui contient le texte de recherche est encore une tâche manuelle.
  2. RegEx n'est pas supporté.

5
2017-10-01 05:51



Alors essayez-vous de parcourir les anciennes versions du code pour voir où il y a quelque chose en dernier?

Si je faisais cela, j'utiliserais probablement git bisect. En utilisant bisect, vous pouvez spécifier une bonne version connue, une mauvaise version connue, et un script simple qui vérifie si la version est bonne ou mauvaise (dans ce cas, un grep pour voir si le code que vous cherchez est présent) ). L'exécution de ceci trouvera quand le code a été enlevé.


2
2018-05-28 11:52