Dzisiaj odpoczniemy trochę od kodu i skupimy się na innym narzędziu, jakim jest Git. Mam nadzieję, że w swojej pracy korzystasz z Gita, ponieważ to wspaniałe narzędzie do kontroli wersji naszej aplikacji, ale i nie tylko.

Sam Git ma o wiele więcej korzyści niż robienie commit i push. Można w nim robić naprawdę przydatne rzeczy pod kątem analiz zmian kodu. My jednak dzisiaj skupimy się na Git Hooks, a dokładniej na jednej rzecz, ktora pozwoli uprościć nam pracę — zniwelować ilość powtarzalnej roboty.

Studium przypadku — sytuacja projektowa

Załóżmy, że w naszym projekcie istnieje wymaganie, według którego każda wiadomość commitu musi zawierać numer zadania. Nie chcielibyśmy ciągle dołączać tego ręcznie do każdego komunikatu, ponieważ łatwo o pomyłkę, a także jest po prosty to żmudne. Jak możemy sobie pomóc, korzystając z Git Hooks?

W sytuacji implementowania zadania pewnie musimy dokonać jakichś zmian w kodzie. Na pewno dobrze byłoby też utworzyć branch, który będzie odpowiadał zadaniu, jakie wykonujemy. Konwencją będzie niech np. XY-1234, czyli dwie literki, myślnik i cyfry. Teraz wykonujemy commit i musimy podać commit message, więc żmudnie klepiemy “XY-1234 | Added file”… I tak za każdym razem, przy każdy commit. Jednak jak możemy to zautomatyzować?

Git Hooks w akcji

Jednym z Git Hooks jest commit-msg, który uruchamia się przed aktywacją edytora wiadomości commit, ale po stworzeniu domyślnej wiadomości. Żeby z niego skorzystać, należy wejść do katalogu .git/hooks w lokalnym repozytorium Gita, zmienić nazwę pliku commit-msg.sample na commit-msg i usunąć jego zawartość. Następnie można umieścić treść skryptu w tym pliku.

1
2
3
4
5
6
7
8
9
#!/bin/sh

branch_name=$(git rev-parse --abbrev-ref HEAD)

prefix=$(echo "$branch_name" | grep -oE '^[A-Z]+-[0-9]+')

if [ -n "$prefix" ] && [ -f "$1" ]; then
    sed -i '' "1s/^/$prefix | /" "$1"
fi

Jeśli nazwa naszego brancha jest np. XY-1234-sth-to-do to w pierwszej linice przypiszemy tą nazwę do zmiennej branch_name. Następnie przy pomocy wyrabżenia regularnego wyodrębnimy XY-1234 i dodamy do wiadomości, aby miała format XY-1234 | {message}. Więc piszą wiadomość w edytorze Added file commit message będzie miał wartość XY-1234 | Added file.

Jednak takie podejście nie rozwiązuje jednego problemu, który teraz ma miejsce.

Rozwiązanie drugiego problemu

Załóżmy, że popełniliśmy błąd w commit message i zamiast Added file powinno być Added some files. Z tego powodu wykonujemy git commit --amend. W aktualnej sytuacji nazwa całego commit message będzie przeniesiona do edytora - XY-1234 | Added file. Zmieniając tylko Added file i zapisując zmiany w efekcie dostaniemy XY-1234 | XY-1234 | Added some files. Więc wypadałoby ręcznie usuwać dodawany prefiks, a nie o to nam chodzi. Na pomoc przychodzi kolejny hook, jakim jest pre-commit-msg. Sytuacja “instalacji” wygląda podobnie jak w przypadku commit-msg. Z tym, że skrypt będzie wyglądał następująco.

1
2
3
4
5
6
7
8
#!/bin/sh

COMMIT_MSG_FILE=$1
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")

CLEANED_MSG=$(echo "$COMMIT_MSG" | sed -E 's/^[A-Z]+-[0-9]+ \| //1')

echo "$CLEANED_MSG"> "$COMMIT_MSG_FILE"

W tym miejscu odwracamy sytuację. Dzięki wyrażeniu regularnemu usuwamy prefix składający się z np. XY-1234 | i możemy cieszyć się brakiem potrzeby wycinania tego ręcznie przy każdej zmianie commit message.

Podsumowanie

Mam nadzieję, że to było dla Ciebie przydatne. Jeśli nie do końca na razie czujesz potrzebę korzystania z tego narzędzia, to mam nadzieję, że będziesz przynajmniej świadomy istnienia czegoś takiego jak Git Hooks.