Come cercare tutti i commit di Git e Mercurial nel repository per una determinata stringa?


287

Ho un repository Git con pochi rami e commit penzolanti. Vorrei cercare tutti questi commit nel repository per una stringa specifica.

So come ottenere un registro di tutti i commit nella storia, ma questi non includono rami o chiazze penzolanti, solo la storia di HEAD. Voglio ottenerli tutti, per trovare un commit specifico che è stato fuori posto.

Vorrei anche sapere come farlo in Mercurial, poiché sto valutando il passaggio.


Risposte:


331

Puoi vedere commettere penzoloni con git log -g.

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

Quindi potresti farlo per trovare una stringa particolare in un messaggio di commit che è penzolante:

git log -g --grep=search_for_this

In alternativa, se si desidera cercare le modifiche per una stringa particolare, è possibile utilizzare l'opzione di ricerca del piccone, "-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 aggiungerà l'opzione -G , permettendoti di passare -G <regexp> per trovare quando una linea contenente <regexp> è stata spostata, cosa che -S non può fare. -S ti dirà solo quando il numero totale di righe contenenti la stringa è cambiato (cioè aggiungendo / rimuovendo la stringa).

Infine, puoi usare gitk per visualizzare le commit penzolanti con:

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

E poi usa le sue funzionalità di ricerca per cercare il file fuori posto. Tutto questo lavoro presupponendo che il commit mancante non sia "scaduto" ed è stato raccolto in modo inutile, cosa che può accadere se pende per 30 giorni e si scadono i reflog o si esegue un comando che li fa scadere.


4
Forse invece di eseguire "git grep" su un numero (probabilmente elevato) di commit, che troverebbe tutti i commit che hanno "search_for_this" da qualche parte in un progetto, utilizzare la cosiddetta ricerca "piccone", cioè l'opzione "-S" per accedere a log , che trova i commit che hanno introdotto o rimosso una determinata stringa o, per essere più precisi, dove è cambiato il numero di occorrenze di una determinata stringa.
Jakub Narębski,

5
È possibile specificare più rami o utilizzare l'opzione '--all', ad esempio 'git log --grep = "stringa in un messaggio di commit" --all'
Jakub Narębski

Questo mi ha permesso di trovare un impegno perso per un lavoro di 2 giorni. Totalmente salvato il mio culo, grazie!
Mike Chamberlain,

2
Mi sono imbattuto in alcune situazioni in cui mi ero impegnato nel mio database ma non nel mio reflog. Non so quanto sia comune. Stavo provando diversi ponti hg / git. Penso che possa sorgere anche con stash caduti. In ogni caso, questo alias funziona bene per catturare quei casi:!git fsck --unreachable | sed -ne 's/^unreachable commit //p' | xargs git log --no-walk
dubiousjim

Nota, ciò non include la ricerca di oggetti nota. Che non è stato ancora implementato: git.661346.n2.nabble.com/…
Antony Stubbs il

54

In Mercurial usi hg log --keywordper cercare parole chiave nei messaggi di commit e hg log --userper cercare un utente particolare. Vedere hg help logper altri modi per limitare il registro.


36
Josip ha scritto che sta pensando di passare a Mercurial e che vorrebbe anche sapere come è stato fatto lì.
Martin Geisler,

1
hg log -kle ricerche commettono il nome utente e i nomi dei file anche nei changeset (lo vedo in command.py:log), che è una delle poche cose che non capisco in hg. Dovrebbero esserci opzioni separate per la ricerca nei messaggi di commit e nei nomi dei file. Sembra che hg log --template '{desc}\n'|grepsia il modo sicuro.
Geoffrey Zheng,

@GeoffreyZheng: ci sono modi per farlo. Vedi "hg help revsets", esp le funzioni desc (), user () e file (). Ci sono anche opzioni di registro hg per la maggior parte di questo comportamento. Nella mia esperienza, sebbene -k / keyword () sia di solito il modo più utile per cercare cose.
Kevin Horn,

Come si fa a cercare tra i contenuti di file effettivamente impegnati ... le differenze? So che sarebbe una ricerca lenta, ma voglio fare una ricerca approfondita per un nome di funzione mancante.
Jonathan,

Oh eccolo qui:hg grep --all <term>
Jonathan,

24

Oltre alla risposta richq sull'uso di git log -g --grep=<regexp>o git grep -e <regexp> $(git log -g --pretty=format:%h): dai un'occhiata ai seguenti post sul blog di Junio ​​C Hamano, attuale manutentore di git


Sommario

Sia git grep che git log --grep sono orientati alla linea , in quanto cercano le linee che corrispondono al modello specificato.

È possibile utilizzare git log --grep=<foo> --grep=<bar>(o git log --author=<foo> --grep=<bar>che si traduce internamente in due --grep) per trovare commit che corrispondono a uno dei pattern (implicito O semantico).

Essendo orientato alla linea, l'utile AND semantico è da usare git log --all-match --grep=<foo> --grep=<bar>per trovare commit che abbia sia la corrispondenza della riga prima che la corrispondenza della riga da qualche parte.

Con git grepè possibile combinare più modelli (tutti che devono utilizzare il -e <regexp>modulo), con --or(che è il default), --and, --not, (e ). Per grep --all-matchsignifica che il file deve avere linee che corrispondono a ciascuna delle alternative.


Ehi Jakub, ti dispiace integrare citazioni / riassunti da quei post sul blog qui? Sembra una delle risposte solo al link vintage in questo momento.
Nathan Tuggy,

11

Sulla base della risposta di rq, ho scoperto che questa riga fa quello che voglio:

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

Che riporterà l'ID commit, il nome file e visualizzerà la riga corrispondente, in questo modo:

91ba969:testFile:this is a test

... Qualcuno è d'accordo sul fatto che questa sarebbe una buona opzione da includere nel comando git grep standard?


5

Qualsiasi comando che accetta riferimenti come argomenti accetterà l' --allopzione documentata nella pagina man git rev-listcome segue:

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

Ad esempio, git log -Sstring --allverranno visualizzati tutti i commit citati stringe accessibili da un ramo o da un tag (suppongo che i tuoi commit penzolanti siano almeno nominati con un tag).


3
Questo non sembra essere il caso di git grep, dove --allsembra essere tradotto / usato come --all-match. Questo mi sembra un bug ... usando Git 1.7.2.3 (usando $(git rev-list --all)lavori).
blueyed

5

Con Mercurial fai un

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

Esistono altre opzioni che restringono la gamma di revisioni cercate.


1
Mi piace anche la bandierahg grep --all
Jonathan,

2

Non so di git, ma in Mercurial invierei semplicemente l'output di hg log a qualche script sed / perl / qualunque per cercare qualunque cosa tu stia cercando. È possibile personalizzare l'output di hg log utilizzando un modello o uno stile per semplificare la ricerca, se lo si desidera.

Ciò includerà tutti i rami nominati nel repository. Mercurial non ha qualcosa di simile alle chiazze penzolanti afaik.


1
Non capisco come questa risposta sia rilevante per il problema specificato.
jribeiro,

3
È una risposta alla domanda di Mercurial, che la domanda originale pone nell'ultimo paragrafo.
Kurt Schelfthout,


1

Per aggiungere solo un'altra soluzione non ancora menzionata, dovevo dire che usare la casella di ricerca grafica di gitg era la soluzione più semplice per me. Seleziona la prima occorrenza e puoi trovare la successiva con Ctrl-G.


1

Un comando in git che penso sia molto più facile trovare una stringa:

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

funziona in Git 2.0.4

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.