
Organizacja Git flow
Jeśli jesteś na etapie startu projektu i wspólnie z zespołem ustalacie zasady, którymi zamierzacie się kierować przy pracy z systemem kontroli wersji GIT lub czujecie, że wasze obecne flow jest nieefektywne, to ten poradnik jest właśnie dla was.
Opiszę jedną z wielu możliwych ścieżek, którą często wykorzystuję w małych i średniej wielkości projektach (i zespołach). Z tego poradnika dowiesz się jak:
- tworzyć branche
- nazywać poprawnie commity
- tworzyć Merge Requesty (MR)
- organizować środowiska
Dlaczego jasno określonego Git Flow jest bardzo ważne?
- ułatwia współpracę w zespole
- zwiększa jakość kodu
- ułatwia debugowanie
- zwiększa profesjonalizm
- oszczędza czas
Poradnik zachęcam dostosować do swoich potrzeb i specyfiki Waszego projektu, ja skupię się na dość generycznym podejściu, które sprawdza się w wielu projektach. Bez zbędnych ceregieli, zaczynajmy!
Aby mówić tym samym językiem, zacznijmy od zdefiniowania kilku pojęć i konwencji nazewniczych, które będą nam towarzyszyć w dalszej części poradnika.
Terminologia
Środowiska:
DEVELOP
- środowisko developerskie, wewnętrzne, tutaj testujemy zmiany przed mergem doSTAGE
STAGE
- środowisko testerskie (QA), wewnętrzne, tutaj trafiają release'y przed mergem doPROD
PREPROD
- środowisko przedprodukcyjne, wewnętrzne i zewnętrzne, może służyć do testów akceptacyjnych klienta, może zostać pominięte w zależności od wielkości projektu i oczekiwań klientaPROD
- środowisko produkcyjne, finalne, tutaj trafia kod, który jest gotowy do użytku, przetestowany i zatwierdzony
Branche:
main
- główny branch produkcyjny, ściśle powiązany ze środowiskiemPROD
, zawsze (przynajmniej w teorii :D) stabilnydevelop
- branch developerski, bazowy dla wszystkich ficzerów, może być chwilowo niestabilny, służy głównie do testów dla developerów przez oddaniem zadania do QA,release/XXX
- branch releasowy, wersja, która trafia na środowiskoSTAGE
i ewentualniePREPROD
, branch ten jest mergowany domain
po zakończeniu testów na środowiskuSTAGE
feature/XXX
- branch dla konkretnego ficzera, bazowy może być branchdevelop
lubmain
w zależności od potrzebbugfix/XXX
- branch dla konkretnego bugfixa, bazowy może być branchdevelop
,release/XXX
w zależności od bieżących potrzeb, po zmergowaniu bugfixa nie zapomnijmy o zmergowanie do brancha bazowego -develop
hotfix/XXX
- branch dla konkretnego hotfixa, bazowy może byc branchrelease/XXX
lubmain
, po zmergowaniu hotfixa nie zapomnijmy o zmergowaniu go z powrotem dodevelop
, aby kod był spójny
Commity:
Commity powinny być jasne, precyzyjne i zrozumiałe dla innych developerów. Warto dodać identyfikator zadania (np. "#14") na końcu wiadomości commita, co ułatwia powiązanie zmian z konkretnym zadaniem w systemie zarządzania projektami. Później można podlinkować sobie konkretne commity z systemem w których mamy zdefniowane taski, co ułatwia debugowanie i development chociażby z pomocą wtyczki Git Lens w Visual Studio Code. Jednak żeby takie commity miały sens, a nie były tylko jakimś "checkpointem" w historii naszego kodu, warto kierować się następującymi zasadami:
- powinny jasno opisywać, co zostało zrealizowane w danym commicie
- nie powinny być niejasne, nieprecyzyjne lub niedbałe
- nie powinny zawierać zbyt wielu zmian w jednym commicie
- powinny być pisane w języku angielskim, nawet jeśli projekt jest w języku polskim
- warto dodać identyfikator zadania na końcu wiadomości commita, co ułatwia powiązanie zmian z konkretnym zadaniem w systemie zarządzania projektami
- warto stosować określoną konwencję, o której więcej informacji zanjdzięcie w kolejnym paragrafie
Konwencje dla wiadomości commitów:
feat: Added hamburger menu in TopBar #17
, gdziefeat
oznacza, że dodaliśmy nowy ficzerfix: Fixed issue with login form validation #12
, gdziefix
oznacza, że naprawiliśmy jakiś bugrefactor: Refactored logic for creating orders #123
, gdzierefactor
oznacza, że zrefaktoryzowaliśmy jakąś część kodustyle: Improved styles for navbar #456
, gdziestyle
oznacza, że poprawiliśmy styletest: Added tests for getNavItems function #789
, gdzietest
oznacza, że dodaliśmy testychore: Updated dependencies #345
, gdziechore
oznacza, że zrobiliśmy coś, co nie wpłynęło bezpośrednio na kod, np. aktualizacja zależnościdocs: Updated README.md #123
, gdziedocs
oznacza, że zrobiliśmy zmiany w dokumentacjici: Updated CI/CD pipeline #123
, gdzieci
oznacza, że zrobiliśmy zmiany w pipeline CI/CDbuild: Updated build process #123
, gdziebuild
oznacza, że zrobiliśmy zmiany w procesie budowania projektuperf: Improved performance of getNavItems function #123
, gdzieperf
oznacza, że poprawiliśmy wydajnośćsecurity: Fixed security issue in login form #123
, gdziesecurity
oznacza, że naprawiliśmy problem z bezpieczeństwem
itd... pewnie można by jeszcze długo wymieniać, ale to już zależy od Was i Waszego projektu, ważne, żeby były spójne i zrozumiałe dla wszystkich w zespole.
Trzymanie się zasad zwiększa profesjonalność i jakość kodu bez dodatkowego nakładu pracy - to tylko kwestia zdefiniowania tych zasad i konsekwentnego ich przestrzegania. Warto takie zasady umieścic w README, aby deweloperzy nie musieli się długo zastanawiać jaką nazwę powinien mieć branch czy jak nazwać commita.
Dla kontrastu podam kilka przykładów jak NIE pisać treści commitów:
fix
(nie wiadomo co zostało naprawione)code review fixes
(brak konkretów)created component
(jaki komponent?)Created Toolbar component, created related ToolbarStore, integrated notifications with API
(zbyt wiele zmian w jednym commicie, ale i tak lepiej niż poprzednie przykłady :))Dodałem navbar #12
(zachowujmy spójny język - najlepiej angielski)#12 Added navbar
to już lepiej, ale jest tutaj mały szkopuł - wiadomość rozpoczyna się od#
co może byc problematyczne w niektórych narzędziach, chociażby podczas interaktywnego rebase'u (git rebase -i __COMIT_SHA__
)
Polecam już wcześniej wspomnianą wtyczkę GitLens w Visual Studio Code - powyższe reguły nabiorą jeszcze więcej sensu i praca z kodem stanie się dużo przyjemniejsza :)
Jeśli już znamy zasady pisania commitów, wiemy jak tworzyć branche, oraz jakie mamy środowiska, to możemy przejść do opisu jak wyglądać będzie nasz workflow.
Workflow dla tworzenia feature'a
- "Wychodzimy" z brancha
develop
i na jego podstawie tworzymy branch dla naszego ficzera
git checkout develop;
git pull;
git checkout -b 'feature/XXX';
- Robimy zmiany, commity, itp.
- Po zakończeniu pracy robimy Merge Request (lub jak wolicie - Pull Request) do brancha
develop
- Po zmergowaniu kod powinien się zbudować automatycznie za pomocą CI/CD pipeline
- Zmiany trafiają na środowisko
DEVELOP
i są testowane przez developerów - Po zakończeniu testów zmiany trafiają na środowisko
STAGE
i są testowane przez QA - Po zakończeniu testów na środowisku
STAGE
zmiany są mergowane do branchamain
czyli na środowisko produkcyjnePROD
Tworzenie bugfixa wygląda podobnie, z tą różnicą, że bazą jest branch develop
lub release/XXX
w zależności od potrzeb.
Workflow dla tworzenia hotfixa
Hotfix jak sama nazwa wskazuje jest "hot" czyli pilny, więc nie ma czasu na testy na środowisku STAGE
, dlatego zazwyczaj hotfixy mergujemy od razu do brancha main
i potem z powrotem do develop
.
- "Wychodzimy" z brancha
main
i na jego podstawie tworzymy branch dla naszego hotfixa
git checkout main;
git pull;
git checkout -b 'hotfix/XXX';
- Robimy zmiany, commity, itp.
- Po zakończeniu pracy robimy Merge Request do brancha
main
- Po zmergowaniu kod powinien się zbudować automatycznie za pomocą CI/CD pipeline
- I ostatni, bardzo ważny punkt! - Zmiany trafiają jeszcze na środowisko
DEVELOP
np. tworząc MR do branchadevelop
i mergując go tam, aby kod był spójny. Lub robiąc to w sposób bardziej manualny:
git checkout develop;
git pull;
git pull origin main;
Podsumowanie
W powyższym poradniku przedstawiłem jedno z wielu możliwych podejść do organizacji pracy z systemem kontroli wersji GIT. Warto zaznaczyć, że nie ma jednego, uniwersalnego rozwiązania, które sprawdzi się w każdym projekcie. Dlatego zachęcam do eksperymentowania, dostosowywania i testowania różnych rozwiązań, aby znaleźć to, które najlepiej sprawdzi się w Waszym zespole i projekcie.
Objaśnienie skrótów
- GIT - System kontroli wersji służący do zarządzania historią zmian w kodzie źródłowym
- DEVELOP - Środowisko developerskie, wewnętrzne, służące do testowania zmian przed mergem do środowiska STAGE
- STAGE - Środowisko testerskie (QA), wewnętrzne, gdzie trafiają release'y przed mergem do PROD
- PREPROD - Środowisko przedprodukcyjne, wewnętrzne i zewnętrzne, służące m.in. do testów akceptacyjnych klienta
- PROD - Środowisko produkcyjne, finalne, gdzie trafia kod gotowy do użytku, przetestowany i zatwierdzony
- QA - Quality Assurance - Zapewnienie Jakości, proces weryfikacji jakości oprogramowania
- CI/CD - Continuous Integration/Continuous Deployment - Ciągła Integracja/Ciągłe Wdrażanie, praktyki automatyzacji procesu budowania, testowania i wdrażania oprogramowania
- MR - Merge Request - żądanie scalenia zmian z jednego brancha do drugiego (w GitLab)
- PR - Pull Request - żądanie scalenia zmian z jednego brancha do drugiego (w GitHub)
- feat - Feature - nowa funkcjonalność w konwencji commitów
- fix - Naprawa błędu w konwencji commitów
- refactor - Refaktoryzacja kodu bez zmiany jego funkcjonalności w konwencji commitów
- README - Plik dokumentacji projektu zawierający podstawowe informacje o projekcie i instrukcje
Linkografia do dalszej exploracji :)
- Oryginalny artykuł o Git Flow autorstwa Vincenta Driessena
- Gitflow Workflow - przewodnik Atlassian
- Conventional Commits - specyfikacja konwencji commitów
- GitLens - rozszerzenie do VS Code ułatwiające pracę z Git
- Automatyzacja procesów CI/CD w projektach webowych
- Pro Git - darmowa książka o Git
- Code Review - najlepsze praktyki dla zespołów deweloperskich
- Różne podejścia do Git workflow według GitLab

Konrad Bysiek
Frontend Developer / Tech Lead