Czy można przeprowadzić „wyszukiwanie grep” we wszystkich gałęziach projektu Git?


Odpowiedzi:


189

Pytanie „ Jak grepować (wyszukiwać) zatwierdzony kod w historii git? ” Zaleca:

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

To przeszukuje wszystkie zatwierdzenia, które powinny obejmować wszystkie gałęzie.

Inną formą byłoby:

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

Jeszcze więcej przykładów znajdziesz w tym artykule :

Wypróbowałem powyższe na jednym projekcie na tyle dużym, że git narzekał na rozmiar argumentu, więc jeśli napotkasz ten problem, zrób coś takiego:

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

(zobacz alternatywę w ostatniej sekcji tej odpowiedzi poniżej)

Nie zapomnij o tych ustawieniach, jeśli je chcesz:

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

Ten alias też może pomóc:

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

Uwaga: chernjie zasugerował, że git rev-list --allto przesada.

Bardziej wyrafinowanym poleceniem może być:

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

Co pozwoli ci przeszukać tylko oddziały (w tym oddziały zdalne)

Możesz nawet utworzyć dla niego alias bash / zsh:

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

Aktualizacja sierpień 2016: RM zaleca w komentarzach

fatal: bad flag '->' used after filenamePodczas testowania git branchwersji wyświetla się „ ” . Błąd był związany z HEADnotacją aliasingu.

I rozwiązać przez wprowadzenie sed '/->/d'do rury, pomiędzy tri na xargspolecenia.

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

To jest:

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

Nie jest dobrym pomysłem potokowanie wyjścia git branchdo tr lub sed; git branchto porcelanowe polecenie przeznaczone do spożycia przez ludzi. Zobacz stackoverflow.com/a/3847586/2562319, aby uzyskać preferowane alternatywy.
jbyler

@jbyler Słuszna uwaga. Jak na ironię, opublikowałem odpowiedź na porcelanie na długo przed tą odpowiedzią: stackoverflow.com/a/6978402/6309 . I używam go na przykład w stackoverflow.com/a/19206916/6309 .
VonC

Tak, fajnie. Przeglądając inne odpowiedzi, myślę, że odpowiedź od @errordeveloper jest najczystsza: stackoverflow.com/a/21284342/2562319 : "git grep <regexp> $ (git for-each-ref --format = '% (refname) 'refs /) "
jbyler

1
Czy istnieje sposób, aby wyświetlić nazwę oddziału, który pasuje do wyszukiwania?
franksands

63

git log może być skuteczniejszym sposobem wyszukiwania tekstu we wszystkich gałęziach, zwłaszcza jeśli jest wiele dopasowań i chcesz najpierw zobaczyć nowsze (istotne) zmiany.

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

Te polecenia dziennika zawierają listę zatwierdzeń, które dodają lub usuwają podany ciąg wyszukiwania / wyrażenie regularne, (zazwyczaj) najpierw nowszy. -pOpcja powoduje istotne diff być pokazany w którym wzór został dodany lub usunięty, dzięki czemu można zobaczyć go w kontekście.

Po znalezieniu odpowiedniego zatwierdzenia, które dodaje tekst, którego szukasz (np. 8beeff00d), znajdź gałęzie zawierające zatwierdzenie:

git branch -a --contains 8beeff00d

22

Uważam, że to najbardziej przydatne:

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

Musiałbyś dostosować ostatnie argumenty w zależności od tego, czy chcesz patrzeć tylko na oddziały zdalne, czy lokalne, tj .:

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

Utworzony przeze mnie alias wygląda następująco:

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

1
Ciekawy alias. +1. Dokładniej niż w mojej odpowiedzi.
VonC

Jak sprawić, by alias działał przy wyszukiwaniu fraz? Kiedy podaję „foo bar” jako parametr, otrzymuję: fatal: ambiguous argument „bar”: nieznana wersja lub ścieżka nie znajduje się w drzewie roboczym. Użyj
znaku

Spróbuj uciec od spacji: „foo \ bar”
Garry Gomez

To powinna być oczywiście akceptowana odpowiedź;) Rozszerzyłem ją, aby wyszukiwać tylko w najnowszych gałęziach mojego projektu (Mam więcej niż 500, nie pytaj, a każdy grep zajmuje około 4 sekund, więc nie chcę ani nie potrzebuję aby przeszukać więcej niż, powiedzmy, 100 ostatnich z nich). W tym celu zaktualizowałem za git for-each-refpomocą --sort=-committerdate --count=100! Dzięki za oryginalny pomysł!
Vser

6

Można to zrobić na dwa popularne sposoby: aliasy Bash lub Git

Oto trzy polecenia:

  1. git grep-branch - Szukaj we wszystkich oddziałach lokalnych i zdalnych
  2. git grep-branch-local - Szukaj tylko w oddziałach lokalnych
  3. git grep-branch-remote - Tylko oddziały zdalne

Użycie jest takie samo jak git grep

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

GREP przy użyciu: aliasy Git

Plik ~ / .gitconfig

Polecenia należy dodawać ręcznie do ~/.gitconfigpliku, ponieważ git config --global aliasoceniają dodawany złożony kod i psują go.


[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 "

Uwaga: Kiedy dodajesz aliasy i nie działają one - sprawdź odwrotne ukośniki \, mogą wymagać dodatkowego znaku ucieczki \\w porównaniu z poleceniami bash .

  • git branch -a - Wyświetl wszystkie gałęzie;
  • sed -e 's/[ \\*]*//'- Przytnij spacje (od branch -a) i * (ma to nazwa aktywnej gałęzi);
  • grep -v -e '\\->'- Ignoruj ​​złożone nazwy, takie jak remotes/origin/HEAD -> origin/master;
  • grep '^remotes' - Zdobądź wszystkie zdalne oddziały;
  • grep -v -e '^remotes'- Zdobądź oddziały z wyjątkiem oddziałów zdalnych;

Przykład git grep-branch-local -n getTastyCookies

-n Prefiks numer linii do pasujących linii.

[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)

Obecna struktura to:

: - Separator

  1. Gałąź: dev
  2. Numer kolejki: 53
  3. Ścieżka pliku: modules/factory/getters.php
  4. Pasująca linia: function getTastyCookies($user)

GREP przy użyciu: BASH

Jak powinieneś wiedzieć: Polecenia Bash powinny być przechowywane w .shskryptach lub uruchamiane w powłoce.

Tylko oddziały lokalne

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

Tylko oddziały zdalne

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

Lokalne i zdalne oddziały

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

Brzmi nieźle, ale otrzymałem ten błąd z git grep-branch "find my text":fatal: ambiguous argument 'client': both revision and filename
nealmcb

Dlaczego zawsze używać -a, który pokazuje wszystkie gałęzie? Sugerowałbym użycie opcji do git branchpolecenia, aby oddzielić pręty. Patrząc na lokalne oddziały, jest tylko jeden *, więc nie ma potrzeby uciekać przed sedem. A więc: tylko git branch | sed -e 's/*/ /' | xargs git grep "TEXT"dla oddziałów lokalnych, tylko git branch -r | grep -v -- "->" | xargs git grep "TEXT"dla oddziałów zdalnych i git branch -a | grep -v -- "->" | xargs git grep "TEXT"dla wszystkich oddziałów
jalanb

4

Oto jak to robię:

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

2
Jedyne rozwiązanie, które działało dla mnie w systemie Windows (w Git bash)
Ivan

4

Jeśli nadasz jakiemukolwiek zatwierdzeniu wartość skrótu SHA-1 git grep, to przeszukuje je zamiast kopii roboczej.

Aby przeszukać wszystkie gałęzie, możesz pobrać wszystkie drzewa za pomocą git rev-list --all. Połóż to wszystko z

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

... i miej cierpliwość

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.