Jak grep Git zatwierdzić różnice lub zawartość dla określonego słowa?

622

W repozytorium kodu Git chcę wyświetlić listę wszystkich zatwierdzeń zawierających określone słowo. Próbowałem tego

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

ale niekoniecznie zwraca mi nazwę pliku (chyba że jest mniej niż 5 linii od szukanego słowa. Próbowałem także

git grep "word"

ale daje mi tylko obecne pliki, a nie historię.

Jak przeszukać całą historię, aby śledzić zmiany dotyczące określonego słowa? Zamierzam przeszukać bazę kodów pod kątem występowania słów w celu śledzenia zmian (wyszukiwanie w historii plików).

Jesper Rønn-Jensen
źródło

Odpowiedzi:

904

Jeśli chcesz znaleźć wszystkie zatwierdzenia, w których komunikat zatwierdzenia zawiera dane słowo, użyj

$ git log --grep=word

Jeśli chcesz znaleźć wszystkie zatwierdzenia, w których „słowo” zostało dodane lub usunięte w treści pliku (a ściślej: gdzie zmieniła się liczba wystąpień „słowa”), tj. Przeszukaj zawartość zatwierdzenia , użyj tak zwanego wyszukiwania „kilof” za pomocą

$ git log -Sword

W nowoczesnym git jest też

$ git log -Gword

szukać różnic, których dodana lub usunięta linia pasuje do „słowa” (również zatwierdza treść ).

Zauważ, że -Gdomyślnie akceptuje regex, podczas gdy -Sakceptuje ciąg, ale można go zmodyfikować, aby akceptował regex za pomocą --pickaxe-regex.

Aby zilustrować różnicę między -S<regex> --pickaxe-regexi -G<regex>rozważyć commit z następującym diff w tym samym pliku:

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

Chociaż git log -G"regexec\(regexp"pokaże to zatwierdzenie, git log -S"regexec\(regexp" --pickaxe-regexnie zmieni się (ponieważ liczba wystąpień tego ciągu nie uległa zmianie).


W Git 2.25.1 (luty 2020) dokumentacja została wyjaśniona wokół tych wyrażeń regularnych.

Zobacz commit 9299f84 (06 lutego 2020) autorstwa Martina Ågrena (``) .
(Połączone przez Junio ​​C Hamano - gitster- w commit 0d11410 , 12 lutego 2020)

diff-options.txt: na przykład unikaj przeciążenia „regex”

Zgłoszony przez: Adam Dinwoodie
Podpisany przez: Martin Ågren
Oceniony przez: Taylor Blau

Kiedy pokazujemy różnicę między -Gi -S(za pomocą --pickaxe-regex), robimy to za pomocą przykładowego diff i git diffwywołania obejmującego „regexec”, „regexp”, „regmatch”, ...

Przykład jest poprawny, ale możemy ułatwić rozplątywanie, unikając pisania „regex. *”, Chyba że jest to naprawdę potrzebne, aby o tym powiedzieć.

Zamiast tego użyj gotowych słów, które nie są wyrażeniami regularnymi.

git diffDokumentacja obejmuje obecnie:

Aby zilustrować różnicę między -S<regex> --pickaxe-regexi -G<regex>rozważyć commit z następującym diff w tym samym pliku:

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

Chociaż git log -G"frotz\(nitfol"pokaże to zatwierdzenie, git log -S"frotz\(nitfol" --pickaxe-regexnie zmieni się (ponieważ liczba wystąpień tego ciągu nie uległa zmianie).

Jakub Narębski
źródło
3
@TankorSmash -S<string>Poszukaj różnic, które wprowadzają lub usuwają wystąpienie <ciąg>. -G<string>Poszukaj różnic, których dodana lub usunięta linia pasuje do podanego <regex>.
m-ric,
1
@ m-ric Och, widzę, instancja pojedynczego ciągu, a cała linia! Dzięki
TankorSmash
3
@ m-ric, @TankorSmash: Różnica polega na tym, że -S<string>jest szybsza, ponieważ sprawdza ona tylko, czy liczba wystąpień się <string>zmieniła, podczas gdy -G<string>wyszukiwania dodawały i usuwały wiersz w każdej zmianie zatwierdzenia.
Jakub Narębski
3
Jeśli chcesz wyszukać słowa ze spacją między nimi git log --grep="my words",.
MEM
4
@MEM, --grepróżni się od -Si -G. Możesz zacytować ciąg do każdego z tych argumentów.
Acumenus,
255

git logKilof znajdzie zmiany ze zmianami, w tym „słowo” z git log -Sword

u0b34a0f6ae
źródło
60
To nie jest do końca precyzyjne. -S <ciąg> Szukaj różnic, które wprowadzają lub usuwają wystąpienie <ciąg>. Zauważ, że różni się to od łańcucha po prostu pojawiającego się na wyjściu diff;
tymtam,
4
Chociaż jest to ogólnie właściwa odpowiedź, oddałem głos tylko po to, aby zachęcić innych do przeczytania tej odpowiedzi ( stackoverflow.com/a/1340245/586983 ), która ma 3 różne sposoby i wyjaśnia ich subtelności.
jakeonrails
18
Boże! Nie sądzę, żeby to był dobry powód, by głosować za właściwą odpowiedzią ... nie byłeś pewny, czy dodanie linku w komentarzu byłoby wystarczającą zachętą?
Deborah
@jakeonrails, Ta odpowiedź powinna być zmianą w tej (starszej), więc nie mamy tych irytujących duplikatów. Ale ludzie chcą tylko reputacji zamiast czystej strony z odpowiedziami.
Iulian Onofrei
22

Po wielu eksperymentach mogę polecić następujące, które pokazują zatwierdzenia, które wprowadzają lub usuwają wiersze zawierające dane wyrażenie regularne, i wyświetlają zmiany tekstu w każdym z kolorów pokazujących słowa dodane i usunięte.

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

Trwa jednak trochę czasu ... ;-)

CharlesW
źródło
2
To jedno z najlepszych do tej pory dzięki. Wskazówka: aby po prostu wyświetlić wszystkie wyniki bez stronicowania, albo wstaw polecenie, GIT_PAGER=catalbo dołącz je za pomocą| cat
Zack Morris
Określ ścieżkę lub plik byłoby znacznie szybszegit log --pickaxe-regex -p --color-words -S "<regexp to search for>" <file or fiepath>
fangxing
10

Możesz spróbować wykonać następujące polecenie:

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

lub używając grepw następujący sposób:

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

Uruchom to polecenie w katalogu nadrzędnym, w którym chcesz wyszukać.

kenorb
źródło
2
Podoba mi się ta metoda, ponieważ zmiany, na które patrzę, zawierają setki wierszy niezwiązanych ze sobą zmian, a interesują mnie tylko łatki zawierające szukane słowo. Aby uzyskać kolor, użyj git log --patch --color=always | less +/searching_string.
Radon Rosborough
9

Jeszcze jeden sposób / składnia, aby to zrobić: W git log -S "word"
ten sposób możesz na przykład wyszukaćgit log -S "with whitespaces and stuff @/#ü !"

1u-
źródło
1

vim-fugitive jest wszechstronny do tego rodzaju badań w Vimie.

Użyj, :Ggrepaby to zrobić. Aby uzyskać więcej informacji, możesz zainstalować vim-fugitive i przejrzeć turorial :help Grep. A ten odcinek: badanie historii repozytorium git poprowadzi cię do tego wszystkiego.

Lerner Zhang
źródło
1

Aby użyć łącznika boolowskiego w wyrażeniu regularnym:

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

To wyrażenie regularne szuka wyrażenia regularnego [0-9] * lub [az] * w komunikatach zatwierdzania.

Reudismam
źródło
-1

Jeśli chcesz wyszukać poufne dane, aby usunąć je z historii gitów (to jest powód, dla którego tu trafiłem), istnieją na to narzędzia. Github jako dedykowana strona pomocy dla tego problemu .

Oto treść artykułu:

BFG Repo-Cleaner jest szybsza, prostsza alternatywa do git branży filtracyjnej do usuwania niechcianych danych. Na przykład, aby usunąć plik z wrażliwymi danymi i pozostawić ostatnie zatwierdzenie nietknięte), uruchom:

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

Aby zastąpić cały tekst wymieniony w pliku passwords.txt w dowolnym miejscu w historii repozytorium, uruchom:

bfg --replace-text passwords.txt

Patrz dokumentacja BFG Repo czytelnia jest na pełne wykorzystanie i pobierania instrukcji.

edelany
źródło
Możesz dodać tę odpowiedź do stackoverflow.com/questions/872565/... zamiast tutaj
lacostenycoder