Git: podstawy¶
Git zapisuje historię zmian w projekcie. Możemy sprawdzić, co się zmieniło, wybrać zmiany do zapisania, a później wrócić do wcześniejszej wersji. Repozytorium Git działa lokalnie, więc do tej lekcji nie potrzebujemy GitHuba ani połączenia ze zdalnym serwerem.
Repozytorium¶
Repozytorium to katalog projektu wraz z historią zmian. Git przechowuje tę
historię w ukrytym katalogu .git/.
W katalogu projektu tworzymy repozytorium z główną gałęzią main:
git init -b main
Jeśli używana wersja Git nie obsługuje -b, wykonaj git init, a potem
zmień nazwę bieżącej gałęzi:
git branch -M main
Git musi wiedzieć, kto tworzy commity. To ustawienie można zapisać raz dla wszystkich repozytoriów:
git config --global user.name "Jan Kowalski"
git config --global user.email "jan@example.org"
Można też ustawić nazwę i adres tylko w bieżącym repozytorium, pomijając
--global. Wtedy trzeba wykonać polecenia wewnątrz repozytorium.
Trzy miejsca na zmiany¶
Git rozróżnia katalog roboczy, poczekalnię (ang. staging area lub index) i historię repozytorium:
| Miejsce | Co zawiera |
|---|---|
| katalog roboczy | bieżące pliki, które edytujemy |
| poczekalnia | zmiany wybrane do następnego commitu |
| repozytorium | zapisane commity i ich historia |
Typowa droga zmiany wygląda tak:
katalog roboczy --git add--> poczekalnia --git commit--> historia
Commit jest zapisem wybranych zmian. Zawiera autora, datę, opis i odwołanie do poprzedniego commitu. Git identyfikuje go unikalnym skrótem.
Sprawdzanie stanu¶
Najczęściej zaczynamy od git status. Pokazuje, na jakiej gałęzi pracujemy i
które pliki są nowe, zmienione albo przygotowane do commitu.
git status
Polecenie git diff pokazuje niezapisane zmiany w katalogu roboczym.
Po dodaniu pliku do poczekalni można sprawdzić, co trafi do następnego commitu:
git diff
git diff --staged
Warto uruchomić git status i obejrzeć różnice przed każdym commitem.
Dodawanie zmian i commity¶
git add dodaje plik do poczekalni. git commit zapisuje zmiany z poczekalni
jako nowy punkt w historii.
git add README.md src/main.c
git diff --staged
git commit -m "Add station status output"
Możemy dodać tylko wybrane pliki. Dzięki temu jeden commit może zawierać zmianę w dokumentacji, a kolejny niezależną zmianę w kodzie.
Opisy commitów powinny krótko mówić, co zmiana robi, np. Ignore build output
albo Add radio link status. Unikaj opisów, które nic nie wyjaśniają, takich
jak changes lub fix.
Pierwszy commit często zapisuje początkową wersję projektu:
git add README.md Makefile src/main.c config/station.conf
git commit -m "Add station monitor project"
Oglądanie historii¶
git log pokazuje historię commitów. Przydatne opcje:
git log --oneline
git log --oneline --graph --all
git show <commit>
--oneline skraca wpisy, a --graph --all pokazuje historię wszystkich
gałęzi. git show wyświetla zmiany zapisane w wybranym commicie. Można podać
jego skrót albo użyć HEAD, które oznacza bieżący commit.
Pliki, których nie chcemy śledzić¶
Programy i pliki obiektowe są generowane podczas budowania projektu. Zwykle
nie dodajemy ich do repozytorium. Lista reguł .gitignore mówi Gitowi, które
nieśledzone pliki ma pomijać:
/build/
*.o
Po zapisaniu .gitignore sprawdź:
git status
git check-ignore -v build/station
Reguła ignorowania nie przestaje śledzić pliku, który wcześniej dodano do
repozytorium. Taki plik trzeba najpierw usunąć z poczekalni z opcją
--cached, np. git rm --cached build/station.
Cofanie zmian przed commitem¶
Możemy wycofać plik z poczekalni, zachowując jego edycję w katalogu roboczym:
git restore --staged README.md
Polecenie git restore README.md przywraca plik z ostatniego commitu.
Usuwa więc niezapisane edycje tego pliku. Przed jego użyciem sprawdź nazwę
pliku i git status.
Gałęzie¶
Gałąź (ang. branch) to lekki wskaźnik na commit. Pozwala rozwijać zmianę
osobno, bez mieszania jej od razu z pracą na main.
git switch -c feature/heartbeat
# edytuj pliki, git add, git commit
git switch main
git switch -c tworzy gałąź i od razu się na nią przełącza. git branch
wyświetla gałęzie; gwiazdka oznacza bieżącą gałąź.
Łączenie gałęzi¶
Po zakończeniu pracy na gałęzi możemy połączyć ją z main:
git switch main
git merge feature/heartbeat
Jeżeli gałęzie zmieniły różne fragmenty projektu, Git zwykle połączy je
automatycznie. Po merge sprawdź git status i obejrzyj historię:
git status
git log --oneline --graph --all
Konflikty merge¶
Konflikt pojawia się podczas łączenia gałęzi, gdy obie zmieniły ten sam fragment pliku w różny sposób. Git wstawia wtedy do pliku znaczniki podobne do tych:
<<<<<<< HEAD
uplink=offline
=======
uplink=online
>>>>>>> station-update
HEAD oznacza wersję z bieżącej gałęzi, a druga część pochodzi z gałęzi,
którą łączymy. Otwórz plik, wybierz poprawną treść i usuń wszystkie znaczniki.
Następnie dodaj rozwiązany plik do poczekalni i zakończ merge commitem:
git add config/station.conf
git commit
Po rozwiązaniu konfliktu sprawdź, czy w git status nie ma już nierozwiązanych
plików i czy wynikowa treść jest poprawna. Konflikt nie oznacza, że commit się
nie udał — dwa osobne commity mogą powstać bez problemu; konflikt jest
zgłaszany przy ich łączeniu.
Typowy cykl pracy¶
git status
# edytuj plik
git diff
git add <plik>
git diff --staged
git commit -m "Describe the change"
git status
Przed commitem sprawdzamy, co dodamy. Po nim sprawdzamy, czy katalog roboczy jest w oczekiwanym stanie.