Niedawno stuknęło mi dwa lata doświaczenia w zawodzie programisty. Dwa lata to wystarczająco czasu aby zrozumieć, że rzeczywistość w branży IT znacząco różni się od ideałów, o których przeczytać mogłem w wielu książkach na temat programowania oraz zarządzania projektami. To działa na szczęście także w drugą stronę - pewnych zjawisk się nie spodziewałem, dopóki nie zobaczyłem ich na żywo, np. jak świetnie można się dogadywać i dzielić pracą w ramach zespołu. Na studiach z pracami w grupie bywało ciężko 😊.
Jednym z rozczarowań, które doświadczam na co dzień jest mała świadomość programistów co do pracy z gitem. Nie raz ani nie dwa byłem świadkiem sytuacji, kiedy programista zastanawiał się, czy nie popsuje niczego na serwerze modyfikując swojego lokalnego brancha albo np. że żeby wycofać zmiany z commita robi się git revert. Ostatnio miałem sytuację, kiedy to odnalazłem buga, który nie wiadomo kiedy został wprowadzony do kodu. Jak powiedziałem znajomemu, że znajdę commit w 10 minut (w zakresie commitów z około 2 miesięcy) to popatrzał się na mnie wielkimi oczyma... Jeszcze większe oczy zrobił, kiedy powiedziałem, że zrobię to za pomocą narzędzia dostępnego w gicie... To zmotywowało mnie do napisania tego wpisu.
Czym jest git bisect?
Git bisect (jak sama dokumentacja nam to wyjaśnia) jest narzędziem do znajdowania commitów, które spowodowały niepoprawne działanie aplikacji. Chociaż z reguły je tak używam, to z powodzeniem można to narzędzie wykorzystać do innych zastosowań, np. do znalezienia commita, w którym została dodana lub usunięta nowa funkcjonalność biznesowa (jeżeli nie możemy tego znaleźć np. w zadaniach na Jirze).
Jak używać git bisect?
Jak używać narzędzia pokażę na przykładzie. W moim przypadku (kod do ściągnięcia tutaj) mamy projekt aplikacji konsolowej z jedną funkcjonalnością: wypisanie na ekran Hello World. Projekt posiada 11 commitów, gdzie wiemy, że w pierwszym commicie funkcjonalność ta działa poprawnie, natomiast w ostatnim - wiemy, że na pewno nie działa (można to sprawdzić przełączając się na ostatnią rewizję i wykonując polecenie:
php -f index.php
Wynik:
Warning: file_get_contents(resources/messages.txt): failed to open stream: No such file or directory in C:\Users\bartl\bisect.example\src\Services\MessageService.php on line 11
Fatal error: Uncaught TypeError: Return value of App\Services\MessageService::getMessage() must be of the type string, boolean returned in C:\Users\bartl\bisect.example\src\Services\MessageService.php:11
Stack trace:
#0 C:\Users\bartl\bisect.example\index.php(11): App\Services\MessageService::getMessage()
#1 {main}
thrown in C:\Users\bartl\bisect.example\src\Services\MessageService.php on line 11
Jeżeli próbowalibyśmy przełączać się ręcznie na każdy commit, to dojście do problematycznej rewizji zajęło by nam przełączenie się 5 razy (zakładając, że robilibyśmy to po kolei). Zaczynamy teraz zabawę z narzędziem.
Aby rozpocząć korzystanie z narzędzia wpisujemy komendę:
git bisect start
Następnie wskazujemy commit, który wiemy że jest wadliwy oraz commit, w którym aplikacja działa na pewno dobrze:
git bisect bad 3a394652dddd121bbc72e85af1204d7f751efa0d
git bisect good cf6d975869701869f36afebca30067049b822c89
otrzymujemy w następstwie komunikat:
Bisecting: 4 revisions left to test after this (roughly 2 steps)
[b055318f5ef1c4689755c4349ce886f5212884ee] Jira-05 Read message from file
narzędzie informuje nas, że maksymalna liczba commitów do sprawdzenia to 5 (od razu została przełączona rewizja do commita o nazwie Jira-05 Read message from file). Teraz musimy sprawdzić, czy w tym commicie jest wszystko ok. W konsoli uruchamiamy skrypt za pomocą polecenia (ponownie):
php -f index.php
i sprawdzamy jaki jest wynik... nie działa! Tak więc informujemy o tym narzędzie:
git bisect bad
Ok, ale to nie daje nam jednoznacznej odpowiedzi, który commit zepsuł działanie. Narzędzie informuje nas w komunikacie, że musimy zrobić więcej przełączeń:
Bisecting: 1 revision left to test after this (roughly 1 step)
[5ea7ad8c585de7f5abf8b7ff6c141c88f2cb0311] Jira-03 Add response code
sprawdzamy działanie:
php -f index.php
Działa! Mówimy teraz narzędziu, że jest ok:
git bisect good
To jednak nie daje nadal jednoznacznej odpowiedzi na pytanie, który commit jest wadliwy (jako pierwszy):
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[d89101a6ae07801ab3163bf49f677496653043be] Jira-04 Add message.txt
sprawdzamy:
php -f index
Działa! Mówimy narzędziu, że jest ok. Dostajemy informację:
b055318f5ef1c4689755c4349ce886f5212884ee is the first bad commit
commit b055318f5ef1c4689755c4349ce886f5212884ee
Author: Bartłomiej Romanek <b.romanek@rombarte.pl>
Date: Wed Feb 5 19:21:59 2020 +0100
Jira-05 Read message from file
:100644 100644 1faf1706c4e21bb1b3eabcd5fa021525158e687d b102caef1750f3aef74f44df7ddae059d1bbdb8f M index.php
no i mamy to! Winowajcą jest commit o nazwie Jira-05 Read message from file autorstwa Bartka Romanek. Ty gałganie!
Na koniec przywracamy stan sprzed użycia narzędzia:
git bisect reset
W powyższym przypadku liczba przełączeń nie została znacząco zoptymalizowana (3 zamiast 5 przełączeń), ale im więcej rewizji, tym z reguły większy zysk. Wynika to z tego, że narzędzie opiera się o algorytm wyszukiwania binarnego. No, ale ogromną zaletą jest na pewno łatwość przełączania rewizji - wystarczy polecenie git bisect good / git bisect bad i mamy automatyczne przełączenie na inną rewizję.
To najprostszy przypadek użycia tego narzędzia. Zapraszam do jego zgłębienia i do korzystania z niego na co dzień!
Komentarze
Ten wpis nie posiada komentarzy.
Dodaj komentarz
Pola oznaczone gwiazdką (*) są wymagane. Komentarze są wstępnie moderowane i mogą nie pojawić się na stronie.