Git — to rozproszony system kontroli wersji z otwartym kodem źródłowym, stworzony przez Linusa Torvaldsa w 2005 roku do rozwoju jądra Linux. W przeciwieństwie do scentralizowanych systemów takich jak SVN, Git przechowuje pełną kopię repozytorium na każdym urządzeniu programisty, co pozwala pracować bez stałego połączenia z serwerem. Według danych Git SCM, 2024, Git jest używany w ponad 90% wszystkich komercyjnych projektów tworzenia oprogramowania.
Najważniejsze
Git — to rozproszony system kontroli wersji (VCS), który śledzi zmiany w plikach i pozwala wielu programistom pracować nad jednym projektem jednocześnie. W przeciwieństwie do scentralizowanych systemów, w Git każdy programista ma pełną kopię repozytorium, włączając całą historię zmian, co czyni system odpornym na utratę danych i nie wymaga stałego połączenia z centralnym serwerem.
Historia Git rozpoczęła się w 2005 roku, kiedy Linus Torvalds stworzył nowy VCS po tym, jak firma BitKeeper cofnęła darmową licencję na swój system dla programistów jądra Linux. Celami były: szybkość, prostota architektury, obsługa nieliniowego rozwoju przez gałęzie i pełna rozproszoność. W ciągu 3 miesięcy Torvalds napisał rdzeń Git, a już po roku projekt przeszedł na samodzielne utrzymanie pod kierownictwem Junio Hamano.
Według danych ankiety Stack Overflow (2024), Git używa 93,9% profesjonalnych programistów, co czyni go dominującym systemem kontroli wersji w branży. Najbliższy konkurent — Subversion (SVN) — jest używany jedynie w 5,2% projektów, głównie w dużych środowiskach korporacyjnych ze scentralizowanymi procesami.
Repozytorium Git — to katalog, w którym Git śledzi zmiany wszystkich plików. Wewnątrz katalogu znajduje się ukryty folder .git, gdzie przechowywane są wszystkie obiekty systemu: commity, drzewa, bloby i referencje. Gdy programista tworzy commit, Git nie kopiuje plików w całości — tworzy migawkę stanu (snapshot) i zapisuje do niej referencję.
Każdy commit zawiera: unikalny skrót SHA-1 (40 znaków), referencję do poprzedniego commita (parent), autora, datę, wiadomość commita i referencję do drzewa (tree), które opisuje stan plików w momencie commita. Łańcuch commitów tworzy skierowany graf acykliczny, gdzie każdy commit wskazuje na jednego lub kilku rodziców.
# Inicjalizacja repozytorium
git init my-project
cd my-project
# Tworzenie commitu
echo "Hello, Git" > README.md
git add README.md
git commit -m "Initial commit"
# Wyświetlanie historii
git log --oneline --graph --all
Git używa trzech głównych obszarów: working directory (pliki na dysku), staging area (indeks, gdzie trafiają przygotowane pliki) i repository (historia commitów). Polecenie git add przenosi zmiany z katalogu roboczego do staging, a git commit zatwierdza zawartość staging w repozytorium. To rozdzielenie pozwala programiście zebrać sensowny commit z zestawu zmian, bez zatwierdzania każdej poprawki osobno.
Podstawowe polecenia Git pokrywają 90% codziennych operacji programisty. Polecenie git clone tworzy lokalną kopię zdalnego repozytorium, git pull pobiera zmiany z serwera i scala je z bieżącą gałęzią, a git push wysyła lokalne commity na serwer. Te trzy polecenia tworzą podstawowy cykl pracy z Git.
Do przeglądania stanu używa się git status — pokazuje ona, które pliki zostały zmienione, które dodano do staging, a które nie są śledzone. git diff wyświetla konkretne zmiany w plikach przed dodaniem do staging. Poniżej znajduje się tabela z najczęściej używanymi poleceniami:
| Polecenie | Działanie | Przykład |
|---|---|---|
| git clone | Kopiuje zdalne repozytorium | git clone https://example.com/repo |
| git add | Dodaje pliki do staging | git add src/main.kt |
| git commit | Zatwierdza zmiany w historii | git commit -m "Fix login bug" |
| git push | Wysyła commity na serwer | git push origin main |
| git pull | Pobiera zmiany z serwera | git pull origin feature |
Do cofania zmian Git oferuje kilka opcji. git reset przesuwa wskaźnik gałęzi na zadany commit i może zresetować staging lub katalog roboczy. git revert tworzy nowy commit, który cofa zmiany wskazanego commita — to bezpieczny sposób cofania dla wspólnych gałęzi, ponieważ historia nie jest przepisywana.
Gałęzie w Git — to lekkie przesuwalne wskaźniki na określony commit. Utworzenie nowej gałęzi nie kopiuje plików, a jedynie tworzy nowy wskaźnik, co czyni rozgałęzianie praktycznie natychmiastowym. Gałąź main (wcześciej master) — główna gałąź projektu, która zawiera stabilny, gotowy do wydania kod.
Standardową praktyką jest używanie Git Flow lub GitHub Flow. W Git Flow używa się gałęzi: main (kod wydaniowy), develop (gałąź integracyjna), feature/* (nowe funkcje), release/* (przygotowanie wydań) i hotfix/* (pilne poprawki). GitHub Flow jest prostszy: tylko main i gałęzie feature, a wszystkie zmiany dostarczane są przez Pull Request.
# Tworzenie i przełączanie gałęzi
git branch feature-auth
git checkout feature-auth
# lub jednym poleceniem:
git checkout -b feature-auth
# Lista gałęzi
git branch --list
git branch -a # wszystkie gałęzie, w tym zdalne
# Usuwanie gałęzi
git branch -d feature-auth
Ważną właściwością gałęzi w Git jest możliwość cherry-pick: przeniesienie pojedynczego commita z jednej gałęzi do drugiej za pomocą polecenia git cherry-pick <hash>. Jest to przydatne, gdy trzeba przenieść poprawkę błędu z gałęzi feature do release bez scalania całej gałęzi. Git obsługuje również prze bazowanie (rebase) i interaktywne prze bazowanie (git rebase -i) do sklejania, zmiany kolejności i edycji commitów.
Merge (scalanie) tworzy specjalny merge-commit, który ma dwoje rodziców. Ten commit rejestruje fakt połączenia dwóch gałęzi i zachowuje pełną historię — widać, gdzie i kiedy nastąpiło scalenie. Merge zachowuje historię w takiej postaci, w jakiej została utworzona, co upraszcza audyt, ale czyni graf commitów bardziej złożonym.
Rebase (prze bazowanie) zamiast tworzenia merge-commita przenosi commity bieżącej gałęzi na szczyt gałęzi docelowej. Historia staje się liniowa — powstaje wrażenie, że rozwój odbywał się sekwencyjnie. Jednak rebase przepisuje historię, zmieniając skróty SHA-1 commitów, co czyni go niebezpiecznym dla wspólnych gałęzi, do których mają dostęp inni programiści.
Zalecenie dotyczące wyboru: używaj merge dla publicznych gałęzi, gdzie historię widzą inni programiści (feature → develop), i rebase do lokalnej pracy, gdy potrzebujesz zastosować świeże zmiany z main w swojej gałęzi feature przed utworzeniem Pull Request. Zasada jest prosta: jeśli commit został już wysłany na serwer — nie prze bazowuj go.
Konflikt scalania powstaje, gdy Git nie może automatycznie połączyć zmian w jednym pliku. Git oznacza konfliktowe fragmenty w pliku specjalnymi znacznikami: <<<<<<< (nasze zmiany), ======= (separator), >>>>>>> (ich zmiany). Programista ręcznie edytuje plik, wybierając odpowiednią opcję lub łącząc obie, i kończy scalanie commitem.
Zdalne repozytorium (remote) — to kopia repozytorium Git znajdująca się na serwerze. GitHub, GitLab i Bitbucket — to najpopularniejsze platformy hostingu zdalnych repozytoriów. Oferują one interfejs webowy do przeglądania kodu, zarządzania dostępem, przeglądu kodu i integracji z systemami CI/CD.
W Git można skonfigurować kilka zdalnych repozytoriów dla jednego projektu. Domyślnie główne remote nazywa się origin. Polecenie git remote add dodaje nowe remote, git fetch pobiera zmiany bez scalania, a git pull — to skrót dla git fetch + git merge. Do pracy z kodem przez Pull Request programista tworzy fork repozytorium, klonuje je, pracuje w gałęzi feature i wysyła żądanie scalenia do oryginalnego repozytorium.
# Dodawanie zdalnego repozytorium
git remote add origin https://github.com/user/repo.git
# Wyświetlanie zdalnych repozytoriów
git remote -v
# Wysyłanie gałęzi na serwer
git push -u origin feature-auth
# Pobieranie zmian ze zdalnej gałęzi
git pull origin main
Zdalne repozytoria obsługują tagowanie do oznaczania wersji wydaniowych. Tagi mogą być lekkie (po prostu wskaźnik na commit) i adnotowane (zawierają metadane: autora, datę, wiadomość). Tagi adnotowane zaleca się używać do wersji wydaniowych, ponieważ przekazują pełną informację o wersji i mogą być podpisane kluczem GPG do weryfikacji autorstwa.
Git Worktree pozwala jednocześnie pracować z wieloma gałęziami w różnych katalogach bez przełączania między nimi. Polecenie git worktree add ../feature-auth feature-auth tworzy nowy katalog roboczy feature-auth, gdzie można pisać kod bez przełączania gałęzi w głównym katalogu. Worktree jest przydatny do szybkich poprawek w gałęzi release, gdy główny katalog jest zajęty długotrwałym rozwojem.
Git Submodules — mechanizm dołączania jednego repozytorium Git do drugiego. Submodule przechowuje referencję do ustalonego commita zewnętrznego repozytorium, co gwarantuje odtwarzalność kompilacji. Polecenie git submodule add https://github.com/example/lib.git dodaje zewnętrzną bibliotekę jako podmoduł. Przy klonowaniu projektu z podmodułami należy wykonać git submodule update --init --recursive aby pobrać wszystkie zależności.
Często zadawane pytania
Git — rozproszony VCS z lokalną historią i możliwością pracy offline. SVN — scentralizowany system wymagający stałego połączenia z serwerem do wszelkich operacji poza przeglądaniem plików.
Użyj git revert HEAD do bezpiecznego cofnięcia (tworzony jest nowy commit). Jeśli commit nie został jeszcze wysłany na serwer, możesz użyć git reset --soft HEAD~1.
.gitignore — plik, w którym wymienione są wzorce plików i katalogów, które Git powinien ignorować. Służy do wykluczania plików tymczasowych, kompilacji i konfiguracji IDE z repozytorium.
git fetch pobiera zmiany z serwera, ale nie scala ich z bieżącą gałęzią. git pull wykonuje fetch i od razu merge. Dla kontroli użyj fetch + przeglądanie diff, a następnie ręczny merge.
Użyj git commit --amend — to polecenie otwiera edytor do zmiany wiadomości commita. Jeśli commit jest już na serwerze, wymagane będzie git push --force, co jest niebezpieczne dla wspólnych gałęzi.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również