Git od podstaw: jak działa kontrola wersji

Szymon Ptak
3 min read
Git od podstaw: jak działa kontrola wersji

Wprowadzenie

Zaczynamy nową serię wpisów o Git — od absolutnych podstaw, przez automatyzację, aż po zaawansowane pipeline’y w Azure DevOps. Zanim jednak przejdziemy do triggerów i YAML-a, warto ustawić wspólny fundament: czym właściwie jest Git, jak wygląda commit, branch i merge, i dlaczego bez tego trudno wyobrazić sobie dziś pracę nad jakimkolwiek kodem — solo czy w zespole.

Czym jest Git?

Git to rozproszony system kontroli wersji — narzędzie, które zapisuje historię zmian w projekcie i pozwala do niej wracać. Słowo „rozproszony" jest tu kluczowe: każdy, kto sklonował repozytorium, ma na swoim dysku pełną historię projektu, a nie tylko jego aktualny stan. Nie potrzeba stałego połączenia z serwerem, żeby zobaczyć, co się działo miesiąc temu.

W praktyce Git odpowiada na pytania, które prędzej czy później zadaje sobie każdy programista:

  • Co się zmieniło w tym pliku od wczoraj?
  • Kto i kiedy wprowadził tę zmianę?
  • Jak cofnąć błędną poprawkę bez ruszania reszty kodu?
  • Jak dwie osoby mogą pracować nad tym samym projektem równolegle, nie nadpisując sobie nawzajem pracy?

Repozytorium i commit

Repozytorium to folder projektu, w którym Git śledzi zmiany — zwykle utworzone przez git init (nowy projekt) albo git clone (kopia istniejącego, np. z Azure Repos).

Commit to zapisany „migawkowy" stan projektu wraz z opisem, co i dlaczego się zmieniło:

1
2
git add plik.py            # zaznacz zmiany do zapisania
git commit -m "Dodaj walidację formularza"

Dobrej jakości commit ma dwie cechy: obejmuje jedną, spójną zmianę i ma opis tłumaczący dlaczego, a nie tylko co (samo „co" widać w diffie). Historia commitów to później najlepsza dokumentacja projektu — pokazuje, jak i dlaczego kod doszedł do obecnego kształtu.

Branch — praca równoległa bez kolizji

Branch (gałąź) to niezależna linia rozwoju projektu. Domyślna gałąź (najczęściej main) trzyma stabilny kod, a każda nowa funkcja czy poprawka powstaje na osobnym branchu:

1
2
3
git checkout -b feature/logowanie-oauth
# praca, commity...
git push origin feature/logowanie-oauth

Dzięki temu kilka osób może pracować równolegle nad różnymi rzeczami, nie blokując się nawzajem, a niedokończona funkcja nie trafia przypadkiem na produkcję.

Merge — łączenie pracy w jedną całość

Gdy praca na branchu jest gotowa, trzeba ją połączyć z główną gałęzią — to właśnie merge:

1
2
git checkout main
git merge feature/logowanie-oauth

W Azure DevOps ten krok niemal zawsze odbywa się przez Pull Request — nie ręczne git merge na własnym komputerze, tylko żądanie połączenia gałęzi widoczne dla całego zespołu, z miejscem na code review, komentarze i automatyczne testy, zanim zmiana trafi do main. To temat, do którego wrócimy w kolejnym wpisie o automatyzacji.

Czasem dwie gałęzie zmieniają te same linie tego samego pliku — wtedy Git zgłasza konflikt i prosi o ręczną decyzję, która wersja (albo jaka kombinacja obu) ma zostać. To nie błąd, tylko normalna część pracy zespołowej — Git tylko pilnuje, żeby żadna zmiana nie zniknęła po cichu.

Podsumowanie

Repozytorium, commit, branch, merge — to cztery pojęcia, na których opiera się cała reszta pracy z Git. W kolejnym wpisie przejdziemy do tego, jak te same mechanizmy zamieniają się w automatyzację: jak push czy Pull Request w Azure DevOps mogą same uruchamiać budowanie, testy i wdrożenie, bez ręcznego klikania czegokolwiek.