Come grep Git commette diff o contenuti per una determinata parola?


622

In un repository di codice Git voglio elencare tutti i commit che contengono una determinata parola. Ci ho provato

git log -p | grep --context=4 "word"

ma non mi restituisce necessariamente il nome del file (a meno che non sia a meno di 5 righe dalla parola che ho cercato. Ho anche provato

git grep "word"

ma mi dà solo i file presenti e non la cronologia.

Come posso cercare nell'intera cronologia per poter seguire le modifiche su una determinata parola? Ho intenzione di cercare nella mia base di codice le occorrenze di parole per rintracciare le modifiche (ricerca nella cronologia dei file).


Risposte:


906

Se si desidera trovare tutti i commit in cui il messaggio di commit contiene una determinata parola, utilizzare

$ git log --grep=word

Se si desidera trovare tutti i commit in cui "parola" è stata aggiunta o rimossa nel contenuto del file (per essere più precisi: dove il numero di occorrenze di "parola" è cambiato), ovvero cercare il contenuto del commit , utilizzare la cosiddetta ricerca "piccone" con

$ git log -Sword

Nel git moderno c'è anche

$ git log -Gword

per cercare le differenze la cui linea aggiunta o rimossa corrisponde a "parola" ( commetti anche i contenuti ).

Si noti che -Gper impostazione predefinita accetta una regex, mentre -Saccetta una stringa, ma può essere modificato per accettare regex utilizzando il --pickaxe-regex.

Per illustrare la differenza tra -S<regex> --pickaxe-regexe -G<regex>, considerare un commit con la seguente diff nello stesso file:

+    return !regexec(regexp, two->ptr, 1, &regmatch, 0);
...
-    hit = !regexec(regexp, mf2.ptr, 1, &regmatch, 0);

Mentre git log -G"regexec\(regexp"mostrerà questo commit, git log -S"regexec\(regexp" --pickaxe-regexnon lo farà (perché il numero di occorrenze di quella stringa non è cambiato).


Con Git 2.25.1 (febbraio 2020), la documentazione viene chiarita attorno a queste regex.

Vedi commit 9299f84 (06 febbraio 2020) di Martin Ågren (``) .
(Unita da Junio ​​C Hamano - gitster- in commit 0d11410 , 12 febbraio 2020)

diff-options.txt: evitare il sovraccarico "regex" nell'esempio

Segnalato da: Adam Dinwoodie
Firmato da: Martin Ågren.
Commentato da: Taylor Blau

Quando esemplificiamo la differenza tra -Ge -S(usando --pickaxe-regex), lo facciamo usando un esempio diff e git diffinvocazione che coinvolge "regexec", "regexp", "regmatch", ...

L'esempio è corretto, ma possiamo rendere più facile districare evitando di scrivere "regex. *" A meno che non sia realmente necessario per chiarire il nostro punto.

Usa invece alcune parole inventate, non regexy.

La git diffdocumentazione ora include:

Per illustrare la differenza tra -S<regex> --pickaxe-regexe -G<regex>, considerare un commit con la seguente diff nello stesso file:

+    return frotz(nitfol, two->ptr, 1, 0);
...
-    hit = frotz(nitfol, mf2.ptr, 1, 0);

Mentre git log -G"frotz\(nitfol"mostrerà questo commit, git log -S"frotz\(nitfol" --pickaxe-regexnon lo farà (perché il numero di occorrenze di quella stringa non è cambiato).


3
@TankorSmash -S<string>Cerca le differenze che introducono o rimuovono un'istanza di <stringa>. -G<string>Cerca le differenze la cui linea aggiunta o rimossa corrisponda al <regex> indicato.
m-ric,

1
@ m-ric Oh, vedo, una singola istanza di stringa, rispetto a un'intera riga! Grazie
TankorSmash,

3
@ m-ric, @TankorSmash: la differenza è che -S<string>è più veloce perché controlla solo se il numero di occorrenze è <string>cambiato, mentre le -G<string>ricerche aggiungono e rimuovono la linea in ogni differenza di commit.
Jakub Narębski,

3
Se devi cercare parole con uno spazio in mezzo git log --grep="my words",.
MEM,

4
@MEM, --grepè diverso da -Se -G. Puoi citare la stringa per ciascuno di questi argomenti.
Acumenus,

255

git logIl piccone troverà commit con modifiche incluso "word" con git log -Sword


60
Questo non è del tutto preciso. -S <stringa> Cerca le differenze che introducono o rimuovono un'istanza di <stringa>. Si noti che questo è diverso dalla stringa che appare semplicemente nell'output diff;
tymtam,

4
Sebbene questa sia generalmente la risposta giusta, ho effettuato il downvoting solo per incoraggiare gli altri a leggere questa risposta ( stackoverflow.com/a/1340245/586983 ) che ha 3 modi diversi e spiega le loro sottigliezze.
jakeonrails,

18
Perbacco! Non penso che sia una buona ragione per votare una risposta giusta ... non eri sicuro che includere il link in un commento sarebbe stato un incoraggiamento sufficiente?
Deborah,

@jakeonrails, Quella risposta avrebbe dovuto essere una modifica a questa (più vecchia), quindi non abbiamo questi fastidiosi duplicati. Ma le persone vogliono solo la reputazione, anziché una pagina di risposte chiare.
Iulian Onofrei,

22

Dopo molte sperimentazioni, posso raccomandare quanto segue, che mostra i commit che introducono o rimuovono le righe contenenti una data regexp e mostra le modifiche del testo in ciascuna, con i colori che mostrano le parole aggiunte e rimosse.

git log --pickaxe-regex -p --color-words -S "<regexp to search for>"

Ci vuole un po 'per correre però ... ;-)


2
Questo è uno dei migliori finora grazie. Suggerimento: per elencare tutti i risultati senza cercapersone, anteporre il comando GIT_PAGER=cato aggiungerlo con| cat
Zack Morris,

Specificare un percorso o un file sarebbe molto più velocegit log --pickaxe-regex -p --color-words -S "<regexp to search for>" <file or fiepath>
fangxing il

10

Puoi provare il seguente comando:

git log --patch --color=always | less +/searching_string

o usando grepnel modo seguente:

git rev-list --all | GIT_PAGER=cat xargs git grep 'search_string'

Esegui questo comando nella directory principale in cui desideri effettuare la ricerca.


2
Mi piace questo metodo perché i commit che sto osservando hanno centinaia di righe di modifiche non correlate e sono interessato solo alle patch effettive che coinvolgono la parola che sto cercando. Per ottenere l'uso del colore git log --patch --color=always | less +/searching_string.
Radon Rosborough,

9

Un altro modo / sintassi per farlo è: in git log -S "word"
questo modo è possibile cercare ad esempiogit log -S "with whitespaces and stuff @/#ü !"



1

Per utilizzare il connettore booleano sull'espressione regolare:

git log --grep '[0-9]*\|[a-z]*'

Questa espressione regolare cerca l'espressione regolare [0-9] * o [az] * nei messaggi di commit.


-1

Se vuoi cercare dati sensibili per rimuoverli dalla tua cronologia git (che è il motivo per cui sono arrivato qui), ci sono strumenti per quello. Github come pagina di aiuto dedicata per quel problema .

Ecco l'essenza dell'articolo:

Il BFG Repo-Cleaner è un più veloce, più semplice alternativa a git filter-branch per la rimozione di dati non desiderati. Ad esempio, per rimuovere il file con dati sensibili e lasciare intatto l'ultimo commit), eseguire:

bfg --delete-files YOUR-FILE-WITH-SENSITIVE-DATA

Per sostituire tutto il testo elencato in passwords.txt ovunque sia presente nella cronologia del repository, eseguire:

bfg --replace-text passwords.txt

Consultare la documentazione di BFG Repo-Cleaner per le istruzioni complete su download e utilizzo.


Potresti voler aggiungere questa risposta a stackoverflow.com/questions/872565/… invece che qui
lacostenycoder
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.