È possibile eseguire una 'ricerca grep' in tutti i rami di un progetto Git?


Risposte:


189

La domanda " Come grep (ricerca) codice commesso nella cronologia di Git? " Raccomanda:

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

Che cerca in tutti i commit, che dovrebbe includere tutti i rami.

Un'altra forma sarebbe:

git rev-list --all | (
    while read revision; do
        git grep -F 'yourWord' $revision
    done
)

Puoi trovare ancora più esempi in questo articolo :

Ho provato quanto sopra su un progetto abbastanza grande che Git si è lamentato della dimensione dell'argomento, quindi se ti imbatti in questo problema, fai qualcosa del tipo:

git rev-list --all | (while read rev; do git grep -e <regexp> $rev; done)

(vedi un'alternativa nell'ultima sezione di questa risposta, di seguito)

Non dimenticare quelle impostazioni, se le vuoi:

# Allow Extended Regular Expressions
git config --global grep.extendRegexp true
# Always Include Line Numbers
git config --global grep.lineNumber true

Anche questo alias può aiutare:

git config --global alias.g "grep --break --heading --line-number"

Nota: chernjie ha suggerito che git rev-list --allè eccessivo.

Un comando più raffinato può essere:

git branch -a | tr -d \* | xargs git grep <regexp>

Che ti permetterà di cercare solo le filiali (comprese le filiali remote)

Puoi persino creare un alias bash / zsh per questo:

alias grep_all="git branch -a | tr -d \* | xargs git grep"
grep_all <regexp>

Aggiornamento agosto 2016: RM raccomanda nei commenti

Ho ottenuto un " fatal: bad flag '->' used after filename" quando provavo la git branchversione. L'errore era associato a una HEADnotazione di aliasing.

L'ho risolto aggiungendo una sed '/->/d'nel tubo, tra tri xargscomandi e.

 git branch -a | tr -d \* | sed '/->/d' | xargs git grep <regexp>

Questo è:

alias grep_all="git branch -a | tr -d \* | sed '/->/d' | xargs git grep"
grep_all <regexp>

Non è una buona idea convogliare l'output di git branchin tr o sed; git branchè un comando di porcellana destinato al consumo umano. Consulta stackoverflow.com/a/3847586/2562319 per le alternative preferite.
jbyler,

@jbyler Un buon punto. Ironia della sorte, ho pubblicato la risposta su porcellana molto prima di questa risposta: stackoverflow.com/a/6978402/6309 . E lo uso ad esempio in stackoverflow.com/a/19206916/6309 .
VonC,

Sì, bello. Osservando le altre risposte, penso che la risposta di @errordeveloper sia la più pulita: stackoverflow.com/a/21284342/2562319 : "git grep <regexp> $ (git for-each-ref --format = '% (refname) 'refs /) "
jbyler,

1
C'è un modo per mostrare il nome del ramo che corrisponde alla ricerca?
franksands

63

git log può essere un modo più efficace di cercare testo tra tutti i rami, specialmente se ci sono molte corrispondenze e si desidera prima vedere le modifiche (rilevanti) più recenti.

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

L'elenco di questi comandi di log consente di aggiungere o rimuovere la stringa di ricerca / regex specificata, (generalmente) prima più recente. L' -popzione fa sì che il diff rilevante sia mostrato dove il pattern è stato aggiunto o rimosso, in modo da poterlo vedere nel contesto.

Dopo aver trovato un commit pertinente che aggiunge il testo che stavi cercando (ad es. 8beeff00d), trova i rami che contengono il commit:

git branch -a --contains 8beeff00d

22

Ho trovato questo molto utile:

git grep -i foo `git for-each-ref --format='%(refname)' refs/`

Dovresti modificare gli ultimi argomenti a seconda che tu voglia guardare solo le filiali remote rispetto a quelle locali, ovvero:

  • git grep -i foo $(git for-each-ref --format='%(refname)' refs/remotes)
  • git grep -i foo $(git for-each-ref --format='%(refname)' refs/heads)

L'alias che ho creato è simile al seguente:

grep-refs = !sh -c 'git grep "$0" "$@" "$(git for-each-ref --format=\"%(refname)\"" refs/)'

1
Alias ​​interessante. +1. Più preciso che nella mia risposta.
VonC,

Come far funzionare il tuo alias per la ricerca di frasi? Quando passo "foo bar" come parametro, ottengo: fatal: argomento ambiguo 'bar': revisione sconosciuta o percorso che non si trova nell'albero di lavoro. Usa '-' per separare i percorsi dalle revisioni
jutky

Prova a fuggire dallo spazio: "foo \ bar"
Garry Gomez

Questa sarà chiaramente la risposta accettata;) Mi sono espanso su di essa per cercare solo tra gli ultimi rami del mio progetto (ne ho più di 500, non chiedere, e ogni grep impiega circa 4 secondi quindi non ne voglio né ho bisogno per cercare tra più di, diciamo, i 100 più recenti). Per questo ho aggiornato il git for-each-refcon --sort=-committerdate --count=100! Grazie per l'idea originale!
Vser

6

È possibile farlo in due modi comuni: alias Bash o Git

Ecco tre comandi:

  1. git grep-branch - Cerca in tutte le filiali locali e remote
  2. git grep-branch-local - Cerca solo nelle filiali locali
  3. git grep-branch-remote - Solo filiali remote

L'utilizzo è lo stesso di git grep

git grep-branch "find my text"
git grep-branch --some-grep-options "find my text"

GREP utilizzando: Git aliases

File ~ / .gitconfig

I comandi dovrebbero essere aggiunti manualmente al ~/.gitconfigfile, perché git config --global aliasvaluta il codice complesso che aggiungi e confondilo.


[alias]
    grep-branch        = "!f(){ git branch -a | sed -e 's/[ \\*]*//' | grep -v -e '\\->' | xargs git grep $@; };f "
    grep-branch-remote = "!f(){ git branch -a | sed -e 's/[ \\*]*//' | grep -v -e '\\->' | grep '^remotes' | xargs git grep $@; };f"
    grep-branch-local  = "!f(){ git branch -a | sed -e 's/[ \\*]*//' | grep -v -e '\\->' -e '^remotes' | xargs git grep $@;  };f "

Nota: quando si aggiungono alias e non riescono a funzionare, controllare le barre rovesciate \che potrebbero richiedere ulteriore escape \\rispetto ai comandi bash .

  • git branch -a - Visualizza tutti i rami;
  • sed -e 's/[ \\*]*//'- Taglia spazi (da branch -a) e * (il nome del ramo attivo ce l'ha);
  • grep -v -e '\\->'- Ignora nomi complessi come remotes/origin/HEAD -> origin/master;
  • grep '^remotes' - Ottieni tutte le filiali remote;
  • grep -v -e '^remotes'- Ottieni filiali ad eccezione di filiali remote;

Esempio git grep-branch-local -n getTastyCookies

-n Prefisso il numero di riga su righe corrispondenti.

[user@pc project]$ git grep-branch-local -n getTastyCookies

dev:53:modules/factory/getters.php:function getTastyCookies($user);
master:50:modules/factory/getters.php:function getTastyCookies($user)

L'attuale struttura è:

: - Separatore

  1. Ramo: dev
  2. Numero riga: 53
  3. Percorso del file: modules/factory/getters.php
  4. Linea di corrispondenza: function getTastyCookies($user)

GREP utilizzando: BASH

Come dovresti sapere: i comandi di Bash dovrebbero essere archiviati negli .shscript o eseguiti in una shell.

Solo filiali locali

git branch -a | sed -e 's/[ \*]*//' | grep -v -e '\->' -e '^remotes' | xargs git grep "TEXT"

Solo filiali remote

git branch -a | sed -e 's/[ \*]*//' | grep -v -e '\->' | grep '^remotes' | xargs git grep "TEXT"

Filiali locali e remote

git branch -a | sed -e 's/[ \*]*//' | grep -v -e '\->' | xargs git grep "TEXT"

Sembra bello, ma ho ricevuto questo errore da git grep-branch "find my text":fatal: ambiguous argument 'client': both revision and filename
nealmcb

Perché usare sempre -a, che mostra tutti i rami? Suggerirei di usare le opzioni al git branchcomando per separare i braches. Quando si guardano le filiali locali, ce n'è solo una *, quindi non c'è bisogno di scappare per sed. Quindi: solo git branch | sed -e 's/*/ /' | xargs git grep "TEXT"per le filiali locali, solo git branch -r | grep -v -- "->" | xargs git grep "TEXT"per le filiali remote e git branch -a | grep -v -- "->" | xargs git grep "TEXT"per tutte le filiali
jalanb

4

Ecco come lo faccio:

git for-each-ref --format='%(*refname)' | xargs git grep SEARCHTERM

2
L'unica soluzione che ha funzionato per me su Windows (in Git bash)
Ivan

4

Se si assegna a un commit un valore hash SHA-1, git grepè necessario cercarlo al posto della copia di lavoro.

Per cercare tutti i rami, puoi ottenere tutti gli alberi con git rev-list --all. Metti tutto con

git grep "regexp" $(git rev-list --all)

... e abbi pazienza

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.