Comment faire pour grep (search) code engagé dans l'histoire git?

j'ai supprimé un fichier ou un code dans un fichier dans le passé. Puis-je noter dans le contenu (pas dans les messages de propagation)?

une très mauvaise solution est de grep le log:

git log -p | grep <pattern>

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

1151
demandé sur Joe White 2010-05-28 15:36:06

13 réponses

pour rechercher commit content (i.e., lignes réelles de source, par opposition à commit messages et similaires), ce que vous devez faire est:

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

Mises à jour : git rev-list --all | xargs git grep expression ne fonctionnera que si vous exécutez dans une "liste d'arguments trop longue" erreur

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

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

cela passera à travers tout votre texte de propagation pour regexp.

la raison pour passer le chemin dans les deux commandes est parce que rev-list retournera la liste des révisions où toutes les modifications à lib/util se sont produites, mais aussi vous devez passer à grep de sorte qu'il ne cherchera que sur lib/util .

imaginez le scénario suivant: grep pourrait trouver le même <regexp> sur les autres fichiers qui sont contenus dans la même révision retournés par rev-list (même si ce fichier n'a pas été modifié lors de cette révision).

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

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

git grep <regexp>

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

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

rechercher l'arbre de travail pour les lignes de texte correspondant à l'expression régulière regexp1 et regexp2, en indiquant seulement les chemins des fichiers:

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

rechercher l'arbre 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>

rechercher l'arbre de travail pour les lignes modifiées du motif de correspondance de texte:

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

Recherche de toutes les révisions pour l'expression régulière regexp:

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 regexp:

git grep <regexp> $(git rev-list <rev1>..<rev2>)
1528
répondu Jeet 2018-01-09 13:55:22

vous devez utiliser la pioche ( -S ) option de git log

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 - trouver perdu de ligne par mot-clé pour plus d'.


Comme Jakub Narębski a commenté:

  • ce cherche des différences qui introduisent ou suppriment une instance de <string> .

    Il signifie habituellement " révisions où vous avez ajouté ou supprimé la ligne avec 'Foo'".

  • l'option --pickaxe-regex vous permet d'utiliser POSIX regex étendu au lieu de chercher une chaîne de caractères.


comme Rob commenté, cette recherche est sensible à la casse, il a ouvert un question de suivi faire une recherche insensible à la casse.

451
répondu VonC 2017-11-02 15:19:05

ma façon préférée de le faire est avec git log 's -G option (ajouté 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 les options -G et -S déterminent si une propagation correspond:

  • l'option -S compte essentiellement le nombre de fois que votre recherche s'effectue dans un fichier avant et après une propagation. La livraison est indiqué dans le journal si l'avant et l'après les nombres sont différents. Cela n'affichera pas, par exemple, les propagations où une ligne correspondant à votre recherche a été déplacée.
  • avec l'option -G , la propagation est affichée dans le journal si votre recherche correspond à une ligne ajoutée, supprimée ou modifiée.

Prenez cet exemple de commit:

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

parce que le nombre de fois où "hello" apparaît dans le fichier est le même avant et après ce commit, il ne sera pas match en utilisant -Shello . Cependant, comme il y a eu un changement à une ligne correspondant à hello , la propagation sera affichée en utilisant -Ghello .

213
répondu Tyler Holien 2014-05-20 16:43:21

si vous voulez parcourir les changements de code (voir ce qui a été réellement changé avec le mot donné dans toute l'histoire) aller pour 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 ;) )
35
répondu Bartek Skwira 2014-04-17 08:17:38

j'ai pris la réponse de @Jeet et je l'ai ajouté à 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 qui a supprimé cette expression n'apparaît pas dans le résultat de la commande, mais plutôt de s'engager au préalable.

22
répondu ripper234 2017-05-23 12:03:04

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

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

de Ces journaux de liste de commandes s'engage à ce que d'ajouter ou de supprimer la chaîne de recherche/regex, (en général) les plus récents en premier. L'option -p permet d'afficher la différence pertinente à l'endroit où le motif a été ajouté ou supprimé, de sorte que vous pouvez le voir en contexte.

ayant trouvé une propagation pertinente qui ajoute le texte que vous cherchiez (par ex. 8beeff00d), trouver les branches qui contiennent le commit:

git branch -a --contains 8beeff00d
13
répondu Edward Anderson 2017-06-23 00:38:58

recherche dans toute révision, tous les fichiers :

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

recherche seulement dans certains fichiers, par exemple les fichiers xml:

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

les lignes de résultat doivent 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
répondu Christophe Roussy 2018-03-19 08:14:54

pour toute autre personne essayant de faire cela dans SourceTree , il n'y a pas de commande directe dans L'interface utilisateur pour cela (à partir de la version 1.6.21.0). Toutefois, vous pouvez utiliser les commandes spécifiées dans la réponse acceptée en ouvrant la fenêtre Terminal (bouton disponible dans la barre d'outils principale) et en les copiant/collant.

Remarque: SourceTree Recherche vue peut en partie faire la recherche de texte pour vous. Appuyez Sur Ctrl + 3 pour aller à la vue de recherche (ou cliquez sur l'onglet Recherche disponible en bas). De l'extrême droite, définissez le type de recherche à changements de fichier et tapez ensuite la chaîne de caractères que vous voulez rechercher. Cette méthode présente les limites suivantes par rapport à la commande ci-dessus:

  1. SourceTree affiche seulement le commits qui contiennent le mot de recherche dans l'un des fichiers modifiés. Trouver le fichier exact que contient le texte de recherche est encore une fois une tâche manuelle.
  2. RegEx n'est pas supporté.
5
répondu dotNET 2015-10-01 05:51:21

pour la simplicité, je suggérerais d'utiliser GUI: gitk-le navigateur de dépôt Git , son assez flexible

  1. pour le code de recherche: enter image description here
  2. Pour fichier de recherche: enter image description here
  3. de cause il soutient également regex: enter image description here

et vous pouvez naviguer à travers les résultats en utilisant la flèche Haut/Bas

3
répondu watashiSHUN 2018-02-07 07:35:46

alors essayez-vous de passer à travers les anciennes versions du code pour voir où est la dernière chose qui existe?

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 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 ceci trouvera quand le code a été retiré.

2
répondu Rob Di Marco 2010-05-28 11:52:32

la réponse de @Jeet fonctionne en PowerShell.

git grep -n <regex> $(git rev-list --all)

ce qui suit affiche tous les fichiers, dans n'importe quelle propagation, qui contiennent un password .

# store intermediate result
$result = git grep -n "password" $(git rev-list --all)

# display unique file names
$result | select -unique { $_ -replace "(^.*?:)|(:.*)", "" }
2
répondu Shaun Luttin 2014-12-16 02:17:29
git rev-list --all | xargs -n 5 git grep EXPRESSION

est un tweak à la solution de @Jeet donc il montre des résultats pendant qu'il cherche et pas seulement à la fin (ce qui peut prendre beaucoup de temps dans un gros repo).

1
répondu laktak 2017-12-19 18:59:34

dans mon cas, j'ai eu besoin de rechercher une courte Commit et les solutions énumérées ne fonctionnaient malheureusement pas.

j'ai réussi à le faire avec: (remplacer le REGEX jeton)

for commit in $(git rev-list --all --abbrev-commit)
do
    if [[ $commit =~ __REGEX__ ]]; then 
        git --no-pager show -s --format='%h %an - %s' $commit
    fi
done
0
répondu xyz 2015-07-31 22:44:08