Zaawansowany dziennik Git
Celem każdego systemu kontroli wersji jest rejestrowanie zmian w kodzie. To daje możliwość cofania się w historii projektu celem sprawdzenia wkładu poszczególnych osób, ustalenia momentu wprowadzenia błędów oraz cofnięcia problematycznych zmian. Jednakże dostęp do całej tej historii jest bezużyteczny, jeśli się nie wie jak się nią posługiwać. Tu właśnie przydaje się polecenie git log.
Na tym etapie podstawowe polecenie git log służące do wyświetlania commitów powinno już być Ci znane. Możesz jednak wpłynąć na jego efekt końcowy za pomocą wielu różnych parametrów.
Zaawansowane funkcje git log można podzielić na dwie kategorie: formatowanie sposobu wyświetlania poszczególnych commitów oraz filtrowanie, które z commitów zostaną uwzględnione w danych wyjściowych. Połączenie tych dwóch funkcji daje Ci możliwość wglądu w historię projektu i znalezienia wszelkich niezbędnych informacji.
Formatowanie danych wyjściowych dziennika
Przede wszystkim przyjrzyjmy się licznym sposobom formatowania danych wyjściowych git log
. Większość ma postać flag, które pozwalają określić zakres informacji otrzymywanych za pomocą polecenia git log
.
Jeśli nie pasuje Ci domyślny format git log
, możesz użyć funkcji aliasowania git config
, aby stworzyć skrót do dowolnej z opcji formatowania omówionych poniżej. Informacje o tym, jak ustawić alias, znajdziesz w sekcji Polecenie git config.
Oneline
Flaga --oneline
skraca każdy commit do pojedynczego wiersza. Domyślnie wyświetla tylko identyfikator commitu oraz pierwszy wiersz jego komunikatu. Typowy wynik polecenia git log --oneline
będzie wyglądał mniej więcej następująco:
0e25143 Merge branch 'feature'
ad8621a Fix a bug in the feature
16b36c6 Add a new feature
23ad9ad Add the initial code base
Jest to bardzo przydatne do uzyskania ogólnego obrazu projektu.
materiały pokrewne
Jak przenieść pełne repozytorium Git
POZNAJ ROZWIĄZANIE
Poznaj środowisko Git z rozwiązaniem Bitbucket Cloud
Decorating
Czasami warto wiedzieć, z jakimi gałęziami lub tagami związany jest dany commit. Flaga --decorate
sprawia, że git log
wyświetla wszystkie odniesienia (gałęzie, tagi itp.), które wskazują na dany commit.
Można to połączyć z innymi opcjami konfiguracyjnymi. Przykładowo uruchomienie polecenia git log --oneline --decorate
sformatuje historię commitów w następujący sposób:
0e25143 (HEAD, main) Merge branch 'feature'
ad8621a (feature) Fix a bug in the feature
16b36c6 Add a new feature
23ad9ad (tag: v0.9) Add the initial code base
Dzięki temu wiesz, że górny commit (oznaczony jako HEAD
) został wyewidencjonowany i że jest to również końcówka gałęzi main
. Na drugi commit wskazuje kolejna gałąź o nazwie feature
, a czwarty commit jest otagowany jako v0.9
.
Gałęzie, tagi, oznaczenie HEAD
i historia commitów to niemal wszystkie informacje zawarte w repozytorium Git, zatem daje Ci to w miarę pełny obraz jego logicznej struktury.
Diffs
Polecenie git log
obejmuje wiele opcji wyświetlania wykazu różnic dla każdego commitu. Do najczęściej używanych należą --stat
i -p
.
Opcja --stat
pozwala wyświetlić liczbę wstawień i usunięć w każdym pliku zmodyfikowanym przez dany commit (zauważ, że edycja wiersza jest przedstawiana jako 1 wstawienie oraz 1 usunięcie). Jest to przydatne, gdy chce się uzyskać krótkie podsumowanie zmian wprowadzonych przez dany commit. Przykładowo następujący commit dodał 67 wierszy w pliku hello.py
i usunął z tego pliku 38 wierszy:
commit f2a238924e89ca1d4947662928218a06d39068c3
Author: John <john@example.com>
Date: Fri Jun 25 17:30:28 2014 -0500
Add a new feature
hello.py | 105 ++++++++++++++++++++++++-----------------
1 file changed, 67 insertion(+), 38 deletions(-)
Liczba znaków +
i -
obok nazwy pliku wskazuje względną liczbę zmian w każdym pliku zmodyfikowanym przez commit. To daje nam jakieś rozeznanie, gdzie można znaleźć zmiany związane z danym commitem.
Jeśli chcesz zobaczyć faktyczne zmiany wprowadzone przez każdy commit, możesz rozszerzyć polecenie git log
o opcję -p
. To skutkuje wyświetleniem całej poprawki odpowiadającej danemu commitowi:
commit 16b36c697eb2d24302f89aa22d9170dfe609855b
Author: Mary <mary@example.com>
Date: Fri Jun 25 17:31:57 2014 -0500
Fix a bug in the feature
diff --git a/hello.py b/hello.py
index 18ca709..c673b40 100644
--- a/hello.py
+++ b/hello.py
@@ -13,14 +13,14 @@ B
-print("Hello, World!")
+print("Hello, Git!")
W przypadku commitów wprowadzających dużą liczbę zmian wynik może być dość długi i zagmatwany. Zazwyczaj, gdy wyświetlasz pełną poprawkę, szukasz jednej konkretnej zmiany. W tym celu możesz użyć opcji „kilof” (pickaxe).
Shortlog
Polecenie git shortlog
jest specjalną wersją git log
przeznaczoną do tworzenia ogłoszeń o wydaniach. Grupuje ono każdy commit według autora i wyświetla pierwszy wiersz komunikatu każdego commitu. To prosty sposób na sprawdzenie kto nad czym pracował.
Jeśli na przykład dwoje programistów wykonało 5 commitów w projekcie, wynik git shortlog
może wyglądać następująco:
Mary (2):
Fix a bug in the feature
Fix a serious security hole in our framework
John (3):
Add the initial code base
Add a new feature
Merge branch 'feature'
Domyślnie git shortlog
sortuje dane wyjściowe według nazw autorów, ale możesz też przekazać opcję -n
celem sortowania według liczby commitów na autora.
wykresy
Opcja --graph
służy do wyświetlenia wykresu w formacie ASCII przedstawiającego strukturę gałęzi w historii commitów. Opcja ta jest powszechnie stosowana w połączeniu z --oneline
i --decorate
, aby ułatwić określenie, który commit należy do której gałęzi:
git log --graph --oneline --decorate
W przypadku prostego repozytorium z tylko 2 gałęziami efekt będzie następujący:
* 0e25143 (HEAD, main) Merge branch 'feature'
|\
| * 16b36c6 Fix a bug in the new feature
| * 23ad9ad Start a new feature
* | ad8621a Fix a critical security issue
|/
* 400e4b7 Fix typos in the documentation
* 160e224 Add the initial code base
Gwiazdka wskazuje, na której gałęzi nastąpił commit, zatem na powyższym wykresie widzimy, że commity 23ad9ad
i 16b36c6
znajdują się w gałęzi tematycznej, a pozostałe w gałęzi main
.
Choć jest to dobra opcja w przypadku prostych repozytoriów, do mocniej rozgałęzionych projektów lepiej użyć bardziej funkcjonalnego narzędzia wizualizacyjnego, takiego jak gitk
czy Sourcetree.
Formatowanie niestandardowe
Dla wszystkich innych potrzeb związanych z formatowaniem git log
można użyć opcji --pretty=format:"
. To pozwala wyświetlić commity w wybrany przez siebie sposób, używając symboli zastępczych w stylu printf
.
Przykładowo znaki %cn
, %h
i %cd
w następującym poleceniu zostają zastąpione odpowiednio nazwą użytkownika osoby zatwierdzającej, skróconym hashem commitu oraz datą zatwierdzenia.
git log --pretty=format:"%cn committed %h on %cd"
Efektem jest następujące formatowanie każdego commitu:
John committed 400e4b7 on Fri Jun 24 12:30:04 2014 -0500 John committed 89ab2cf on Thu Jun 23 17:09:42 2014 -0500 Mary committed 180e223 on Wed Jun 22 17:21:19 2014 -0500 John committed f12ca28 on Wed Jun 22 13:50:31 2014 -0500
Pełną listę symboli zastępczych można znaleźć w sekcji Pretty Formats na stronie podręcznika dotyczącej polecenia git log
.
Oprócz ograniczania zakresu zwracanych informacji do tych faktycznie potrzebnych opcja --pretty=format:"
jest szczególnie przydatna, gdy próbujesz przekierować dane wyjściowe z git log
do innego polecenia.
Filtrowanie historii commitów
Formatowanie sposobu wyświetlania commitów to tylko połowa sukcesu w zakresie obsługi git log
Drugą połowę stanowi zrozumienie, jak poruszać się po historii commitów. W dalszej części artykułu przedstawiamy kilka zaawansowanych sposobów znajdowania konkretnych commitów w historii projektu za pomocą git log
. Wszystko to można połączyć z dowolnymi opcjami formatowania omówionymi powyżej.
Według ilości
Najbardziej podstawową opcją filtrowania git log
jest ograniczenie liczby wyświetlonych commitów. Jeśli interesują Cię tylko ostatnie commity, opcja ta pozwala Ci uniknąć wyświetlania wszystkich commitów naraz.
Możesz ograniczyć dane wyjściowe git log
za pomocą opcji -
. Przykładowo poniższe polecenie spowoduje wyświetlenie tylko 3 najnowszych commitów.
git log -3
Według daty
Jeśli szukasz commitu z określonego przedziału czasowego, możesz użyć flag --after
i --before
do przefiltrowania wyników według daty. Obie flagi dopuszczają różne formaty dat. Przykładowo poniższe polecenie spowoduje wyświetlenie wyłącznie commitów, które zostały utworzone po 1 lipca 2014 r. (włącznie):
git log --after="2014-7-1"
Można też użyć odniesień względnych, takich jak "1 week ago"
(1 tydzień temu) czy "yesterday"
(wczoraj):
git log --after="yesterday"
Aby wyszukać commity utworzone między dwiema datami, możesz podać zarówno datę przed, jak i po (odpowiednio --before
i --after
). Przykładowo, aby wyświetlić wszystkie commity dodane między 1 lipca a 4 lipca 2014 r., należy użyć polecenia:
git log --after="2014-7-1" --before="2014-7-4"
W przypadku commitów wprowadzających dużą liczbę zmian wynik może być dość długi i zagmatwany. Zazwyczaj, gdy wyświetlasz pełną poprawkę, szukasz jednej konkretnej zmiany. W tym celu możesz użyć opcji „kilof” (pickaxe).
Według autora
Jeśli szukasz wyłącznie commitów utworzonych przez konkretnego użytkownika, użyj flagi --author
. Można tu użyć wyrażenia regularnego, co spowoduje wyświetlenie wszystkich commitów, których autor pasuje do danego wzorca. Jeśli wiesz dokładnie, kogo szukasz, możesz użyć zwykłego ciągu znaków zamiast wyrażenia regularnego:
git log --author="John"
Wyświetlone zostaną wszystkie commity, których nazwa autora zawiera ciąg John. Nazwa autora nie musi być dokładnie dopasowana — musi tylko zawierać określoną frazę.
Możesz także użyć wyrażeń regularnych do tworzenia bardziej złożonych wyszukiwań. Przykładowo poniższe polecenie wyszukuje commity autorstwa Mary lub Johna.
git log --author="John\|Mary"
Pamiętaj, że do nazwy autora dołączany jest również jego adres e-mail, który też może stanowić podstawę wyszukiwania.
Jeśli Twój przepływ pracy odróżnia osoby zatwierdzające od autorów, flaga --committer
pozwala również je uwzględnić.
Według komunikatu
Aby filtrować commity według komunikatu commitu, użyj flagi --grep
. Działanie jest podobne, jak w przypadku flagi --author
omówionej powyżej. Jedyna różnica polega na tym, że przeszukiwane są komunikaty commitów zamiast autorów.
Przykładowo, jeżeli zespół umieszcza w każdym commicie powiązane numery zgłoszeń, możesz użyć następującego polecenia, aby wyszukać wszystkie commity związane z danym zgłoszeniem:
git log --grep="JRA-224:"
Można również przekazać do git log
parametr -i
powodujący ignorowanie wielkości znaków przy dopasowywaniu do wzorca.
Według pliku
Nieraz interesują nas wyłącznie zmiany, które zaszły w konkretnym pliku. Aby wyświetlić historię związaną z danym plikiem, wystarczy podać jego ścieżkę. Przykładowo poniższe polecenie zwraca wszystkie commity, które miały wpływ na plik foo.py
lub bar.py
:
git log -- foo.py bar.py
Parametr --
służy do poinformowania git log
, że kolejne argumenty są ścieżkami plików, a nie nazwami gałęzi. Jeżeli w danym wypadku pomylenie z gałęzią nie jest możliwe, znaki --
można pominąć.
Według treści
Można też wyszukiwać commity, które wprowadzają określony wiersz do kodu źródłowego lub go usuwają. Nosi to nazwę pickaxe (kilof) i przyjmuje postać -S"
. Jeśli na przykład chcesz sprawdzić, kiedy ciąg Hello, World! został dodany do dowolnego pliku w projekcie, użyj następującego polecenia:
git log -S"Hello, World!"
Jeśli chcesz wyszukiwać za pomocą wyrażenia regularnego zamiast ciągu znaków, możesz użyć flagi -G"
.
Rozwiązanie to stanowi bardzo wydajne narzędzie do debugowania, ponieważ umożliwia zlokalizowanie wszystkich commitów, które mają wpływ na dany wiersz kodu. Możemy nawet sprawdzić, kiedy dany wiersz został skopiowany lub przeniesiony do innego pliku.
Według zakresu
Możesz przekazać zakres commitów do polecenia git log
, aby wyświetlić tylko te, które się w nim zawierają. Zakres określa się za pomocą następującego formatu, gdzie
i
są odniesieniami do commitów.
git log ..
To polecenie jest szczególnie przydatne, gdy jako parametrów używamy odniesień do gałęzi. To prosty sposób na przedstawienie różnic między dwiema gałęziami. Rozważmy następujące polecenie:
git log main..feature
Zakres main..feature
zawiera wszystkie commity, które znajdują się w gałęzi feature
, ale nie w gałęzi main
. Innymi słowy: przedstawia rozwój gałęzi feature
od momentu oddzielenia od gałęzi main
. Można to zwizualizować w następujący sposób:
Należy zauważyć, że jeśli zmienimy kolejność zakresu (feature.. main
), otrzymamy wszystkie commity, które są w gałęzi main
, ale nie w gałęzi feature
. Jeśli git log
wykazuje commity dla obu wersji, oznacza to, że nastąpiło rozdzielenie historii.
Filtrowanie commitów scalenia
Domyślnie git log
w danych wyjściowych uwzględnia commity scalenia. Jeśli jednak w Twoim zespole obowiązuje zasada „zawsze scalaj” (czyli scalania zmian nadrzędnych z gałęziami tematycznymi zamiast zmieniania bazy gałęzi tematycznej na gałąź nadrzędną), w historii projektu będzie widnieć wiele nieistotnych commitów scalenia.
Można zapobiec wyświetlaniu tych commitów przez git log
poprzez przekazanie flagi --no-merges
:
git log --no-merges
Z drugiej strony jeśli interesują Cię wyłącznie commity scalenia, można użyć flagi --merges
:
git log --merges
To powoduje wyświetlenie tych commitów, które mają co najmniej dwa elementy nadrzędne.
Podsumowanie
I oto potrafisz już korzystać z zaawansowanych parametrów git log
do formatowania danych wyjściowych i wskazywania, które commity chcesz wyświetlić. Dzięki temu możesz wydobyć z historii projektu dokładnie to, czego potrzebujesz.
Te nowe umiejętności stanowią ważną część zestawu narzędzi Git, ale należy pamiętać, że z git log
często korzysta się w połączeniu z innymi poleceniami. Gdy już znajdziesz commit, którego szukasz, zazwyczaj przekazujesz go do git checkout
, git revert
lub innego narzędzia do obsługi historii commitów. Pamiętaj zatem, aby stale poszerzać wiedzę na temat zaawansowanych funkcji Git.
Udostępnij ten artykuł
Następny temat
Zalecane lektury
Dodaj te zasoby do zakładek, aby dowiedzieć się więcej na temat rodzajów zespołów DevOps lub otrzymywać aktualności na temat metodyki DevOps w Atlassian.