Jak grep (search) committed code w historii Gita?

Kiedyś w przeszłości usunąłem plik lub jakiś kod z pliku. Czy Mogę grep w treści (nie w wiadomościach commit)?

Bardzo słabym rozwiązaniem jest grep log:

git log -p | grep <pattern>

To jednak nie zwraca hash commit od razu. Grałem z git grep bez skutku.

 1151
Author: Joe White, 2010-05-28

13 answers

Aby wyszukać treść commit (tj. rzeczywiste linie źródłowe, w przeciwieństwie do komunikatów commit i tym podobnych), musisz zrobić:

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

Aktualizacje: git rev-list --all | xargs git grep expression będzie działać, jeśli napotkasz błąd "lista argumentów za długa"

Jeśli chcesz ograniczyć wyszukiwanie do jakiegoś podzbioru (na przykład "lib / util"), musisz przekazać to do rev-list oraz grep:

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

To przejrzy cały Twój tekst commit dla regexp.

Powodem przekazania ścieżki w obu komend jest to, że rev-list zwróci listę revisions, w której zaszły wszystkie zmiany do lib/util, ale musisz również przekazać ją do grep, aby wyszukiwała tylko na lib/util.

Wyobraź sobie następujący scenariusz: grep może znaleźć ten sam <regexp> w innych plikach, które są zawarte w tej samej rewizji zwracanej przez rev-list (nawet jeśli nie było zmian w tym pliku w tej rewizji).

Oto kilka innych przydatnych sposoby wyszukiwania źródła:

Wyszukaj drzewo robocze dla tekstu pasującego do wyrażenia regularnego regexp:

git grep <regexp>

Wyszukaj w drzewie roboczym wiersze tekstu pasujące do wyrażenia regularnego regexp1 lub regexp2:

git grep -e <regexp1> [--or] -e <regexp2>

Przeszukanie drzewa roboczego dla wierszy tekstu pasujących do wyrażenia regularnego regexp1 i regexp2, raportowanie tylko ścieżek plików:

git grep -e <regexp1> --and -e <regexp2>

Wyszukiwanie w drzewie roboczym plików, które mają wiersze tekstu pasujące do wyrażenia regularnego regexp1 i wiersze tekstu pasujące do wyrażenia regularnego wyrażenie regexp2:

git grep -l --all-match -e <regexp1> -e <regexp2>

Wyszukaj drzewo robocze dla zmienionych linii tekstu pasującego do wzorca:

git diff --unified=0 | grep <pattern>

Przeszukaj wszystkie wersje dla tekstu pasującego do wyrażenia regularnego regexp:

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

Przeszukaj wszystkie wersje między rev1 i rev2, aby znaleźć tekst pasujący do wyrażenia regularnego regexp:

git grep <regexp> $(git rev-list <rev1>..<rev2>)
 1528
Author: Jeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-09 13:55:22

Powinieneś użyć kilofa (-S) opcja git log

Aby wyszukać Foo:

git log -SFoo -- path_containing_change 
git log -SFoo --since=2009.1.1 --until=2010.1.1 -- path_containing_change

Zobacz Git history-znajdź zagubioną linię według słowa kluczowego aby dowiedzieć się więcej.


Jako Jakub Narębski skomentował (a):

  • Ten szuka różnic, które wprowadzają lub usuwają instancję <string>.
    Zwykle oznacza "zmiany, w których dodano lub usunięto wiersz z 'Foo'".

  • Opcja --pickaxe-regex pozwala na użyj rozszerzonego wyrażenia regularnego POSIX zamiast wyszukiwania ciągu znaków.


Jak skomentował Rob, wyszukiwanie uwzględnia wielkość liter - otworzył kolejne pytanie na temat tego, jak przeszukiwać wielkość liter.

 451
Author: VonC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-02 15:19:05

Moim ulubionym sposobem na to jest opcja git log ' S -G (dodana w wersji 1.7.4).

-G<regex>
       Look for differences whose added or removed line matches the given <regex>.

Istnieje subtelna różnica między sposobem, w jaki opcje -G i -S określają, czy commit pasuje:

  • opcja -S zasadniczo liczy liczbę dopasowań wyszukiwania w pliku przed i po zatwierdzeniu. Commit jest pokazywany w dzienniku, jeśli licznik przed i po jest inny. Nie będzie to na przykład pokazywać commitów, w których linia pasująca do wyszukiwania został przeniesiony.
  • z opcją -G, zatwierdzenie jest wyświetlane w dzienniku, jeśli wyszukiwanie pasuje do dowolnej linii, która została dodana, usunięta lub zmieniona.

Weźmy ten commit jako przykład:

diff --git a/test b/test
index dddc242..60a8ba6 100644
--- a/test
+++ b/test
@@ -1 +1 @@
-hello hello
+hello goodbye hello

Ponieważ liczba wystąpień" hello " w pliku jest taka sama przed i po tym zatwierdzeniu, nie będzie pasować przy użyciu -Shello. Jednakże, ponieważ nastąpiła zmiana dopasowania linii hello, commit zostanie pokazany za pomocą -Ghello.

 213
Author: Tyler Holien,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-20 16:43:21

Jeśli chcesz przeglądać zmiany w kodzie (zobacz co faktycznie zostało zmienione z podanym słowem w całej historii) przejdź do trybu patch - znalazłem bardzo przydatną kombinację robienia:

git log -p
# hit '/' for search mode
# type in the word you are searching
# if the first search is not relevant hit 'n' for next (like in vim ;) )
 35
Author: Bartek Skwira,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-17 08:17:38

Wziąłem @odpowiedź Jeeta i dodałem ją do Windows (dzięki Ta odpowiedź):

FOR /F %x IN ('"git rev-list --all"') DO @git grep <regex> %x > out.txt

Zauważ, że dla mnie, z jakiegoś powodu, rzeczywisty commit, który usunął ten regex, nie pojawił się na wyjściu polecenia, ale raczej jeden commit przed nim.

 22
Author: ripper234,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:04

git log może być bardziej efektywnym 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 wypisują commity, które dodają lub usuwają dany ciąg wyszukiwania/regex, (ogólnie) nowszy jako pierwszy. Opcja -p powoduje wyświetlenie odpowiedniego rozróżnienia, gdzie wzór został dodany lub usunięty, dzięki czemu można go zobaczyć w kontekście.

Po znalezieniu odpowiedniego commita, który dodaje tekst szukałeś (np. 8beeff00d), znajdź gałęzie zawierające commit:

git branch -a --contains 8beeff00d
 13
Author: Edward Anderson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-23 00:38:58

Szukaj w dowolnej wersji, dowolnych plikach :

git rev-list --all | xargs git grep <regexp>

Wyszukiwanie tylko w niektórych podanych plikach, na przykład w plikach xml:

git rev-list --all | xargs -I{} git grep <regexp> {} -- "*.xml"

Linie wynikowe powinny wyglądać tak: 6988bec26b1503d45eb0b2e8a4364afb87dde7af:bla.xml: tekst znalezionej linii...

Możesz uzyskać więcej informacji takich jak autor, data, różnica używając git show:

git show 6988bec26b1503d45eb0b2e8a4364afb87dde7af
 10
Author: Christophe Roussy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-19 08:14:54

Dla każdego, kto próbuje to zrobić w SourceTree, nie ma bezpośredniego polecenia w interfejsie użytkownika (od wersji 1.6.21.0). Możesz jednak użyć poleceń podanych w zaakceptowanej odpowiedzi, otwierając okno Terminal (przycisk dostępny w głównym pasku narzędzi) i kopiując/wklejając je w nim.

Uwaga: widok SourceTree Search może częściowo przeszukiwać tekst. Naciśnij Ctrl + 3 aby przejść do widoku wyszukiwania (lub kliknąć zakładkę Szukaj dostępną w dno). Od prawej strony Ustaw typ Wyszukiwania na File Changes, a następnie wpisz szukany ciąg znaków. Ta metoda ma następujące ograniczenia w porównaniu z powyższym poleceniem:

  1. SourceTree pokazuje tylko commity , które zawierają wyszukiwane słowo w jednym ze zmienionych plików. Znalezienie dokładnego pliku zawierającego szukany tekst jest ponownie zadaniem ręcznym.
  2. RegEx nie jest obsługiwany.
 5
Author: dotNET,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-01 05:51:21

Dla uproszczenia, sugerowałbym użycie GUI: gitk-przeglądarka repozytorium Git , dość elastyczna

  1. aby wyszukać kod: Tutaj wpisz opis obrazka
  2. aby wyszukać plik: Tutaj wpisz opis obrazka
  3. of cause it also supports regex: Tutaj wpisz opis obrazka

I możesz nawigować po wynikach za pomocą strzałki w górę / w dół

 3
Author: watashiSHUN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-07 07:35:46

Więc próbujesz przejrzeć starsze wersje kodu, aby zobaczyć, gdzie coś ostatnio istnieje?

Gdybym to robił, prawdopodobnie użyłbym git bisect. Używając bisect, możesz określić znaną dobrą wersję, znaną złą wersję i prosty skrypt, który sprawdza, czy wersja jest dobra czy zła (w tym przypadku grep, aby sprawdzić, czy kod, którego szukasz, jest obecny). Uruchomienie tego spowoduje, że kod zostanie usunięty.

 2
Author: Rob Di Marco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-28 11:52:32

Odpowiedź @ Jeet działa w PowerShell.

git grep -n <regex> $(git rev-list --all)

Poniżej wyświetlane są wszystkie pliki w zatwierdzeniu, które zawierają password.

# store intermediate result
$result = git grep -n "password" $(git rev-list --all)

# display unique file names
$result | select -unique { $_ -replace "(^.*?:)|(:.*)", "" }
 2
Author: Shaun Luttin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-16 02:17:29
git rev-list --all | xargs -n 5 git grep EXPRESSION

Jest modyfikacją rozwiązania @Jeet, dzięki czemu wyświetla wyniki podczas wyszukiwania, a nie tylko na końcu (co może zająć dużo czasu w przypadku dużego repo).

 1
Author: laktak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-19 18:59:34

W moim przypadku musiałem wyszukać Krótki Commit i wymienione rozwiązania niestety nie działały.

Udało mi się to zrobić za pomocą: (zamieńregex token)

for commit in $(git rev-list --all --abbrev-commit)
do
    if [[ $commit =~ __REGEX__ ]]; then 
        git --no-pager show -s --format='%h %an - %s' $commit
    fi
done
 0
Author: xyz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-31 22:44:08