Comment rechercher dans toutes les validations Git et Mercurial dans le référentiel une certaine chaîne?

287

J'ai un référentiel Git avec quelques branches et des commits suspendus. Je voudrais rechercher toutes ces validations dans le référentiel pour une chaîne spécifique.

Je sais comment obtenir un journal de toutes les validations de l'histoire, mais celles-ci n'incluent pas les branches ou les blobs pendants, juste l'histoire de HEAD. Je veux les obtenir tous, trouver un commit spécifique qui a été mal placé.

J'aimerais également savoir comment faire cela dans Mercurial, car je pense au changement.

Josip
la source

Réponses:

331

Vous pouvez voir les commissions pendantes git log -g.

-g, --walk-reflogs
 Instead of walking the commit ancestry chain, walk reflog entries from
 the most recent one to older ones. 

Vous pouvez donc faire cela pour trouver une chaîne particulière dans un message de validation qui pend:

git log -g --grep=search_for_this

Alternativement, si vous souhaitez rechercher les modifications pour une chaîne particulière, vous pouvez utiliser l'option de recherche de pioche, "-S":

git log -g -Ssearch_for_this
# this also works but may be slower, it only shows text-added results
git grep search_for_this $(git log -g --pretty=format:%h)

Git 1.7.4 sera ajoutera l'option -G , vous permettant de passer -G <regexp> pour trouver quand une ligne contenant <regexp> a été déplacée, ce que -S ne peut pas faire. -S ne vous indiquera que lorsque le nombre total de lignes contenant la chaîne a changé (c'est-à-dire l'ajout / la suppression de la chaîne).

Enfin, vous pouvez utiliser gitk pour visualiser les validations pendantes avec:

gitk --all $(git log -g --pretty=format:%h)

Et puis utilisez ses fonctions de recherche pour rechercher le fichier égaré. Tous ces travaux en supposant que la validation manquante n'a pas «expiré» et ont été récupérés, ce qui peut se produire si elle est suspendue pendant 30 jours et que vous expirez reflogs ou exécutez une commande qui les expire.

richq
la source
4
Peut-être qu'au lieu d'exécuter "git grep" sur un nombre (éventuellement important) de validations, qui trouverait toutes les validations qui ont 'search_for_this' quelque part dans un projet, utilisez la recherche dite "pioche", c'est-à-dire l'option '-S' pour git log , qui trouve les validations qui ont introduit ou supprimé une chaîne donnée, ou pour être plus précis lorsque le nombre d'occurrences d'une chaîne donnée a changé.
Jakub Narębski
5
Vous pouvez spécifier plusieurs branches, ou utiliser l'option '--all', par exemple 'git log --grep = "chaîne dans un message de validation" --all'
Jakub Narębski
Cela m'a juste permis de retrouver un engagement perdu pour 2 jours de travail. Totalement sauvé mon cul, merci!
Mike Chamberlain
2
J'ai rencontré des situations où j'avais des commits dans ma base de données mais pas dans mon reflog. Je ne sais pas à quel point c'est courant. J'essayais différents ponts hg / git. Je pense que cela peut également survenir avec des cachettes abandonnées. Dans tous les cas, cet alias fonctionne bien pour attraper ces cas:!git fsck --unreachable | sed -ne 's/^unreachable commit //p' | xargs git log --no-walk
dubiousjim
Remarque, cela n'inclut pas la recherche d'objets de note. Cela n'a pas encore été implémenté: git.661346.n2.nabble.com/…
Antony Stubbs
54

Dans Mercurial, vous utilisez hg log --keywordpour rechercher des mots clés dans les messages de validation et hg log --userpour rechercher un utilisateur particulier. Voir hg help logpour d'autres moyens de limiter le journal.

Martin Geisler
la source
36
Josip a écrit qu'il envisageait de passer à Mercurial et qu'il aimerait également savoir comment cela se fait là-bas.
Martin Geisler
1
hg log -kles recherches engagent également le nom d'utilisateur et les noms de fichiers dans les ensembles de modifications (je vois cela dans commands.py:log), ce qui est l'une des rares choses que je ne comprends pas dans hg. Il devrait y avoir des options distinctes pour rechercher dans les messages de validation et les noms de fichiers. On dirait que hg log --template '{desc}\n'|grepc'est le moyen sûr.
Geoffrey Zheng
@GeoffreyZheng: il existe des moyens de le faire. Voir "hg help revsets", en particulier les fonctions desc (), user () et file (). Il existe également des commutateurs de journal hg pour la plupart de ce comportement. D'après mon expérience, bien que -k / keyword () soit généralement le moyen le plus utile pour rechercher des choses.
Kevin Horn
Comment recherche-t-on le contenu réel d'un fichier engagé ... les différences? Je sais que ce serait une recherche lente, mais je veux faire une recherche approfondie pour un nom de fonction manquant.
Jonathan
Oh le voici:hg grep --all <term>
Jonathan
24

En plus de la réponse richq d'utiliser git log -g --grep=<regexp>ou git grep -e <regexp> $(git log -g --pretty=format:%h): jetez un œil aux articles de blog suivants de Junio ​​C Hamano, actuel responsable de git


Résumé

Les deux grep git et log git --grep sont orientés en ligne dans la mesure où ils recherchent des lignes correspondant au critère spécifié.

Vous pouvez utiliser git log --grep=<foo> --grep=<bar>(ou git log --author=<foo> --grep=<bar>cela se traduit en interne par deux --grep) pour trouver des validations qui correspondent à l' un des modèles (implicite OU sémantique).

En raison de son orientation linéaire, l' ET utile sémantique est d'utiliser git log --all-match --grep=<foo> --grep=<bar>pour trouver un commit qui a à la fois une correspondance de ligne en premier et une seconde correspondance de ligne quelque part.

Avec git grepvous pouvez combiner plusieurs modèles (tous qui doivent utiliser le -e <regexp>formulaire) avec --or(qui est la valeur par défaut),--and , --not, (et ). Pour grep --all-matchsignifie que le fichier doit avoir des lignes qui correspondent à chacune des alternatives.

Jakub Narębski
la source
Hé Jakub, vous voulez intégrer des citations / résumés de ces articles de blog ici? Il semble que l'une des réponses vintage uniquement liées aux liens soit en ce moment.
Nathan Tuggy
11

Sur la base de la réponse de rq, j'ai trouvé que cette ligne fait ce que je veux:

git grep "search for something" $(git log -g --pretty=format:%h -S"search for something")

Qui rapportera l'ID de validation, le nom de fichier et affichera la ligne correspondante, comme ceci:

91ba969:testFile:this is a test

... Quelqu'un convient-il que ce serait une bonne option à inclure dans la commande git grep standard?

Sam Hiatt
la source
5

Toute commande qui prend des références comme arguments acceptera l' --alloption décrite dans la page de manuel git rev-listcomme suit:

   --all
       Pretend as if all the refs in $GIT_DIR/refs/ are listed on the
       command line as <commit>.

Ainsi, par exemple git log -Sstring --all, affichera toutes les validations qui mentionnent stringet qui sont accessibles à partir d'une branche ou d'une balise (je suppose que vos validations pendantes sont au moins nommées avec une balise).

adl
la source
3
Cela ne semble pas être le cas pour git grep, où --allsemble être traduit / utilisé comme --all-match. Cela ressemble à un bug pour moi .. en utilisant Git 1.7.2.3 (en utilisant des $(git rev-list --all)œuvres).
blueyed le
5

Avec Mercurial vous faites

$ hg grep "search for this" [file...]

Il existe d'autres options qui réduisent la gamme de révisions recherchées.

Yawar
la source
1
J'aime aussi le drapeauhg grep --all
Jonathan
2

Je ne sais pas pour git, mais dans Mercurial, je dirigerais simplement la sortie de hg log vers un script sed / perl / quel que soit pour rechercher ce que vous recherchez. Vous pouvez personnaliser la sortie du journal hg à l'aide d'un modèle ou d'un style pour faciliter la recherche, si vous le souhaitez.

Cela inclura toutes les branches nommées dans le référentiel. Mercurial n'a pas quelque chose comme des blobs pendants afaik.

Kurt Schelfthout
la source
1
Je ne comprends pas en quoi cette réponse est pertinente pour le problème spécifié.
jribeiro
3
C'est une réponse à la question de Mercurial, à propos de laquelle la question d'origine pose dans le dernier paragraphe.
Kurt Schelfthout
1

Pour ajouter une seule solution non encore mentionnée, je devais dire que l'utilisation de la boîte de recherche graphique de gitg était la solution la plus simple pour moi. Il sélectionnera la première occurrence et vous pourrez trouver la suivante avec Ctrl-G.

icarito
la source
1

Une commande dans git que je pense qu'il est beaucoup plus facile de trouver une chaîne:

git log --pretty=oneline --grep "string to search"

fonctionne dans Git 2.0.4

Adriano Rosa
la source