Po co w ogóle Git? Problemy, które rozwiązuje kontrola wersji
Codzienny ból bez systemu kontroli wersji
Każdy, kto choć raz rozwijał większy projekt bez Gita, przerabiał ten sam scenariusz: katalog z plikami o nazwach typu final_v3_ostateczny_ostatni_POPRAWIONY, kopiowanie całych folderów na pendrive’a, wysyłanie zipów mailem, gubienie „tej dobrej wersji”. Przy małym skrypcie to jeszcze uchodzi. Przy większej aplikacji albo pracy zespołowej zamienia się w chaos.
Bez systemu kontroli wersji trudno odpowiedzieć na proste pytania: kto wprowadził daną zmianę, kiedy to zrobił, co dokładnie się zmieniło, do jakiej stabilnej wersji można bezpiecznie wrócić. Każda większa refaktoryzacja jest ryzykiem – jeśli coś popsujesz, musisz ręcznie przywracać pliki z kopii, często nie pamiętając, co dokładnie było wcześniej.
Git rozwiązuje ten problem, wprowadzając historię zmian. Zamiast dziesięciu kopii katalogu masz jedno repozytorium, w którym widać krok po kroku rozwój projektu. Możesz śmiało eksperymentować, bo zawsze istnieje konkretne miejsce w historii, do którego da się wrócić jednym poleceniem.
Czym jest system kontroli wersji i co zapisuje Git
System kontroli wersji (VCS) to narzędzie, które śledzi kolejne wersje plików w projekcie. W Git każdy zapis historii to tzw. commit – pakiet zmian opatrzony:
- unikalnym identyfikatorem (hash),
- autorem zmiany (imię, email),
- datą i godziną,
- krótkim opisem tego, co zostało zrobione,
- prawdziwym stanem plików w danym momencie.
Ważne: Git nie jest wielkim systemem do przechowywania binarnych backupów. Jego największa siła to śledzenie tego, co zmieniło się w plikach tekstowych (kod, konfiguracje, dokumentacja). Dzięki temu możesz porównywać wersje linia po linii, łatwo szukać „kiedy to się popsuło” i kto dodał daną linijkę.
Mit bywa prosty: „Git to takie lepsze kopiuj-wklej folderu”. Rzeczywistość jest inna: Git przechowuje strukturę historii, gałęzie, punktu kontrolne, łączy zmiany wielu osób, a także pozwala zautomatyzować recenzje kodu i wdrożenia. Zwykły backup tego nie potrafi.
Git kontra GitHub – narzędzie vs platforma
Git to program działający lokalnie na Twoim komputerze. Jest rozproszonym systemem kontroli wersji: całe repozytorium z historią mieszkają w jednym ukrytym katalogu .git w Twoim projekcie. Możesz z Gita korzystać bez Internetu, bez konta na żadnym serwisie i bez logowania.
GitHub natomiast to platforma hostingowa dla repozytoriów Git. Oferuje:
- zdalne repozytoria (backup + współdzielenie),
- interfejs www do przeglądania historii,
- pull requesty, recenzje kodu, zgłoszenia błędów (issues),
- automatyzacje CI/CD, integracje z innymi usługami.
Git można porównać do silnika, a GitHub do garażu z pełnym zapleczem, gdzie ten silnik wykorzystujesz z innymi osobami. Ta granica bywa mylona: część początkujących sądzi, że „GitHub to Git”, tymczasem Git jest standardem, a GitHub jedną z implementacji zdalnego hostingu (obok GitLab, Bitbucket i wielu innych).
Czy Git jest tylko dla dużych zespołów?
Częsty mit: „Git ma sens dopiero, gdy jest kilku programistów, ja piszę solo, więc mi niepotrzebny”. Rzeczywistość: solo programista korzysta na Git równie mocno, jak zespół. Nawet przy małym projekcie:
- masz czystą historię tego, co robiłeś każdego dnia,
- możesz bez bólu wrócić do stabilnej wersji sprzed większych eksperymentów,
- łatwiej przenieść projekt między komputerami,
- masz gotowe portfolio kodu na GitHubie.
Co więcej, Git pomaga wyrabiać dobre nawyki inżynierskie: częste, małe commity, sensowne opisy zmian, praca na branchach. Jeśli kiedyś dołączysz do zespołu lub do projektu open source, będziesz już znał ten sposób pracy – a to dziś standard nie tylko w świecie programistów, ale też w administracji systemami, DevOps czy nawet w analizie danych.
Instalacja i pierwsza konfiguracja Gita krok po kroku
Skąd pobrać Git i jak go poprawnie zainstalować
Bezpiecznym źródłem Gita jest oficjalna strona git-scm.com. System sam wykryje, czy używasz Windows, macOS, czy Linuxa i zaproponuje odpowiednią paczkę.
Na Windows instalator „Git for Windows” zawiera:
- Git (wersja konsolowa),
- Git Bash – terminal zbliżony do Linuksa,
- opcjonalne powiązanie Gita z menu kontekstowym Eksploratora.
Podczas instalacji na Windows warto:
- zostawić domyślny wybór powłoki (Git Bash lub Command Prompt – Git Bash bywa wygodniejszy),
- nie kombinować z dziwnymi opcjami CRLF/line endings na początku – domyślne ustawienia są dla większości ok.
Na macOS można:
- zainstalować Git przez Homebrew:
brew install git, - lub skorzystać z instalatora ze strony git-scm.com.
Na Linuxie Git najczęściej jest w repozytoriach dystrybucji:
- Debian/Ubuntu:
sudo apt install git, - Fedora:
sudo dnf install git, - Arch:
sudo pacman -S git.
Sprawdzenie instalacji i konfiguracja podstawowych danych
Pierwszy krok po instalacji to upewnienie się, że Git działa:
git --version
Jeśli pojawi się numer wersji, wszystko w porządku. Następnie ustaw podstawowe dane użytkownika, które będą widoczne przy każdym commicie:
git config --global user.name "Twoje Imię"
git config --global user.email "twoj.email@example.com"
Flaga --global oznacza, że te ustawienia będą domyślne dla wszystkich repozytoriów na Twoim koncie użytkownika. Możesz je nadpisać lokalnie w jednym projekcie, jeśli zajdzie potrzeba (np. inne dane służbowe i prywatne).
Przydaje się też ustawienie domyślnego edytora, którego Git użyje np. przy pisaniu wiadomości commita, gdy jej nie podasz w linii komend:
- dla VS Code:
git config --global core.editor "code --wait", - dla nano:
git config --global core.editor "nano".
HTTPS czy SSH do GitHuba – kiedy co wybrać
Do komunikacji z GitHubem (i innymi zdalnymi repozytoriami) są dwa główne sposoby:
- HTTPS – korzystasz z adresu zaczynającego się od
https://, logujesz się hasłem lub tokenem, - SSH – korzystasz z adresu
git@github.com:..., logowanie odbywa się kluczem kryptograficznym.
Dla początkujących HTTPS jest prostszy na start, ale SSH szybko staje się wygodniejszy, bo nie trzeba ciągle wpisywać hasła. Konfiguracja SSH w skrócie:
- Generowanie klucza:
ssh-keygen -t ed25519 -C "twoj.email@example.com" - Odczyt klucza publicznego, np.
cat ~/.ssh/id_ed25519.pub - Skopiowanie zawartości i dodanie jej w GitHubie: Settings → SSH and GPG keys → New SSH key.
Po takim ustawieniu możesz używać adresów SSH repozytoriów bez podawania hasła przy każdym git push i git pull. W większych projektach to standard.
Gdzie Git trzyma ustawienia: global vs lokal
Git przechowuje konfigurację w kilku plikach:
~/.gitconfig– ustawienia globalne użytkownika (np.user.name,user.email),.git/configw katalogu repozytorium – ustawienia lokalne tylko dla tego projektu,/etc/gitconfig– systemowe ustawienia (zazwyczaj nie trzeba ich dotykać).
Do podglądu konfiguracji służy:
git config --list --show-origin
Przy pierwszych próbach najłatwiej „popsuć” ustawienia wpisując np. błędny email albo nazwę użytkownika. Efekt nie jest dramatyczny, ale historie commitów będą miały złe dane. Jeśli to się zdarzy, popraw user.name i user.email, a w krytycznych przypadkach można zedytować historię, choć to temat na późniejszy etap nauki.
Podstawowe pojęcia Gita bez żargonu
Repozytorium, commit, branch – obrazowo, bez teorii
Najbardziej przyjazne wyobrażenie działania Gita to gra z punktami kontrolnymi. Repozytorium jest jak cały zapis stanu gry dla konkretnego projektu. Commit to punkt kontrolny – bezpieczne miejsce, do którego zawsze można się cofnąć.
Branch (gałąź) to alternatywna ścieżka rozwoju gry. Tworzysz nową gałąź, aby testować inną strategi ę, nie psując głównego zapisu. Gdy jesteś zadowolony z rezultatu, łączysz tę ścieżkę z główną.
HEAD to wskaźnik, który mówi: „tu teraz jesteś w historii”. Najczęściej HEAD wskazuje na najnowszy commit danej gałęzi. Gdy się przełączasz między branchami, HEAD przeskakuje na inny fragment historii.
Snapshot zamiast przechowywania różnic
Często powtarzana opowieść mówi, że Git przechowuje głównie „różnice” między wersjami plików. Technicznie jest to półprawda. Z punktu widzenia użytkownika commit to pełny obraz (snapshot) wszystkich śledzonych plików w danym momencie, a nie tylko różnica względem poprzedniego punktu.
Git wewnętrznie optymalizuje sposób, w jaki plasuje te dane, ale dla Ciebie ważne jest jedno: w każdej chwili możesz przywrócić stan projektu dokładnie taki, jak w danym commicie. Nie musisz ręcznie składać zmian z wielu kroków – Git odczyta pełen snapshot.
Working directory, staging area i historia
Podczas pracy nad projektem pliki przechodzą przez trzy „warstwy”:
- Working directory – pliki na dysku, które edytujesz w edytorze/IDE.
- Staging area (indeks) – miejsce, do którego odkładasz zmiany przygotowane do commita.
- Historia (commity) – zapisane, utrwalone snapshoty projektu.
Standardowy przepływ wygląda tak:
- Edytujesz plik – zmiana pojawia się w working directory.
- Dodajesz go do indeksu:
git add plik. - Zapisujesz commit:
git commit -m "opis zmiany".
Dlaczego staging area jest przydatna? Bo pozwala decydować, które zmiany wejdą do konkretnego commita. Możesz mieć 10 zmodyfikowanych plików, ale przygotować commit tylko z dwoma, które są logicznie powiązane – resztę zapiszesz później w osobnym punkcie.
Mit: „Git to tylko backup na wypadek awarii dysku”. Backup zabezpiecza przed utratą plików, ale rzadko daje klarowną historię krok po kroku i możliwość łatwego rozgałęziania dram prac rozwojowych. Git jest narzędziem do zarządzania ewolucją kodu, a kopia zapasowa jest jedynie jednym z ubocznych efektów jego używania (szczególnie gdy masz repozytorium na zdalnym serwerze).
Tworzenie pierwszego repozytorium lokalnego i praca w terminalu
Zakładanie katalogu projektu i git init
Najprostszy start z Gitem to mały, własny projekt. Załóżmy, że chcesz śledzić zmiany skryptu w Pythonie. Wybierasz katalog:
- Tworzysz folder:
mkdir moj-projekt - Wchodzisz do niego:
cd moj-projekt - Inicjujesz repozytorium:
git init
Pierwsze pliki i pierwszy commit krok po kroku
Po git init w katalogu pojawi się ukryty folder .git. To tam Git trzyma całą historię i konfigurację repozytorium. Plików projektu na razie nie ma – tworzysz je samodzielnie.
Świetnie widać to, gdy równolegle zaczynasz przygodę z innymi narzędziami jak Docker czy wirtualizacja. Dla wielu osób naturalne jest połączenie nauki Gita z tematami takimi jak Informatyka, Nowe technologie, AI, bo w praktycznych projektach te światy spotykają się bardzo szybko.
- Utwórz plik, np.
main.pyz prostą zawartością:
print("Hello, Git!")- Sprawdź status repozytorium:
git statusZobaczysz coś w stylu:
Untracked files:
(use "git add <file>..." to include in what will be committed)
main.pyGit „widzi” plik w katalogu, ale jeszcze go nie śledzi. Trzeba go dodać do indeksu:
git add main.pyI ponownie status:
git status
Teraz main.py będzie w sekcji Changes to be committed. Ostatni krok – utworzenie commita:
git commit -m "Pierwszy commit: prosty skrypt powitalny"Mit: „pierwszy commit musi mieć jakąś szczególną wiadomość typu ‘Initial commit’, bo tak wszyscy robią”. Rzeczywistość: Gitowi jest wszystko jedno, opis ma być użyteczny dla ludzi. Jeśli „Initial commit” coś dla Ciebie znaczy – użyj. Jeśli wolisz konkretny opis – jeszcze lepiej.
Podgląd historii i szczegółów zmian
Po kilku commitach naturalne staje się pytanie: co właściwie zostało zrobione i kiedy. Do prostego podglądu historii służy:
git logWynik zawiera listę commitów od najnowszego: skrót identyfikatora, autora, datę i wiadomość. Dla bardziej skondensowanego widoku:
git log --onelineKiedy potrzebny jest szczegółowy podgląd zmian w plikach, użyjesz:
git diffTen wariant pokazuje różnice między working directory a staging area. Aby zobaczyć, co trafi do następnego commita:
git diff --cachedDo szybkiej analizy bywa przydatne porównanie z wybraną wersją z historii:
git diff <id_commita>..HEAD
W praktycznym scenariuszu: zmieniasz kilka funkcji, po godzinie nie pamiętasz szczegółów i zastanawiasz się, czy wszystko jest spójne. git diff działa wtedy jak bardzo szczegółowy notatnik, który „nie zapomina”, co dokładnie ruszyłeś.
Cofanie zmian lokalnych bez dramatów
Czasem edytujesz plik, testujesz coś i dochodzisz do wniosku, że chcesz wrócić do ostatniej zapisanej wersji. Jeśli plik jest zmodyfikowany tylko w working directory, a nie dodany do indeksu:
git restore main.pyZastąpi zawartość pliku wersją z ostatniego commita. Gdy chcesz wycofać wszystkie lokalne zmiany w katalogu roboczym:
git restore .
Jeśli plik został już dodany do indeksu (przez git add), ale jeszcze nie zrobiono commita, możesz wycofać to „dodanie”:
git restore --staged main.pyMit: „każdy błąd w Gicie jest nieodwracalny i kończy się katastrofą”. W codziennej pracy większość wpadek da się wyprostować kilkoma prostymi komendami, dopóki nie zaczynasz agresywnie przepisywać historii publicznego repozytorium.

Od lokalnego repo do GitHuba: pierwsze zdalne repozytorium
Tworzenie pustego repozytorium na GitHubie
Zanim połączysz lokalny projekt z GitHubem, potrzebne jest zdalne „miejsce docelowe”. Po zalogowaniu się na GitHubie:
- kliknij „New” przy liście repozytoriów,
- ustaw nazwę, np.
moj-projekt, - ustaw widoczność (Public lub Private),
- nie dodawaj na razie README, .gitignore ani licencji – chcesz pusty szkielet repozytorium.
Na stronie nowego repozytorium pojawią się instrukcje z sekcją „…or push an existing repository from the command line”. To dokładnie to, czego szukasz.
Podpięcie lokalnego repo do GitHuba: git remote
W terminalu, w katalogu projektu, dodajesz zdalne repo jako origin. Dla HTTPS będzie to wyglądało np. tak:
git remote add origin https://github.com/twoj-login/moj-projekt.gitDla SSH adres będzie w rodzaju:
git remote add origin git@github.com:twoj-login/moj-projekt.gitSprawdzenie, czy zdalne repo zostało poprawnie skonfigurowane:
git remote -v
Zobaczysz adresy dla fetch i push. Od tego momentu Git wie, dokąd wysyłać i skąd pobierać historię.
Pierwsze wypchnięcie zmian: git push
Jeśli masz już co najmniej jeden commit, możesz przesłać historię na GitHuba:
git push -u origin main
Zakładając, że główna gałąź nazywa się main (w nowych repozytoriach to domyślna nazwa). Przełącznik -u ustawia powiązanie lokalnej gałęzi z gałęzią zdalną – od teraz wystarczy zwykle:
git push
bez podawania origin main.
Zdarza się, że lokalna gałąź nadal nazywa się master. Wtedy masz dwie opcje:
- przemianować ją lokalnie:
git branch -m master main git push -u origin main - lub użyć starej nazwy także na GitHubie (mniej polecane w nowych projektach).
Mit: „jak coś trafi na GitHuba, to już nie da się tego usunąć”. Prawda jest taka, że możesz nadpisywać historię, usuwać commity, a nawet całe repozytoria – tylko trzeba wiedzieć, kiedy to bezpieczne. Jeśli repozytorium jest publiczne i ma już forków oraz klonów, ślady i tak mogą pozostać.
Klonowanie istniejącego repozytorium jako alternatywny start
Często będziesz zaczynać nie od git init, ale od pobrania już istniejącego projektu:
git clone https://github.com/twoj-login/moj-projekt.gitlub przez SSH:
git clone git@github.com:twoj-login/moj-projekt.gitTa komenda:
- tworzy nowy katalog z nazwą repozytorium,
- ściąga całą historię,
- ustawia
origini domyślną gałąź.
Jeśli więc projekt już istnieje na GitHubie, nie inicjujesz lokalnie własnego repozytorium – po prostu go klonujesz i od razu pracujesz na tej samej historii, co reszta zespołu.
Podstawowy workflow na co dzień: status, add, commit, push, pull
Cykliczna pętla pracy z Gitem
Codzienna praca w Gicie kręci się wokół kilku komend. Pętla jest prosta:
- pobierasz najnowsze zmiany ze zdalnego repozytorium (
git pull), - modyfikujesz pliki w edytorze,
- sprawdzasz, co się zmieniło (
git status,git diff), - dodajesz konkretne pliki do indeksu (
git add), - tworzysz commit (
git commit), - wysyłasz swoje commity na serwer (
git push).
Brzmi banalnie, ale właśnie ta powtarzalność sprawia, że po kilku dniach ręce same wpisują te komendy.
git status jako „radar” podczas pracy
git status to podstawowe narzędzie kontrolne. Pokazuje:
- na jakiej gałęzi jesteś,
- czy Twoja gałąź jest zsynchronizowana ze zdalną,
- jakie pliki są zmodyfikowane, dodane, usunięte, ale jeszcze nie zacommitowane,
- które zmiany trafiły już do staging area.
Dobry nawyk: odpalać git status przy każdej większej zmianie, przed commitem i po nim. Traktuj to jak szybkie spojrzenie w lusterko przed manewrem.
Świadome używanie git add
Do indeksu możesz dodawać:
- konkretny plik:
git add main.py - wszystkie zmodyfikowane pliki w katalogu:
git add . - lub pliki spełniające wzorzec:
git add *.py
Zbyt częste używanie git add . bywa zgubne – bardzo łatwo dorzucić przypadkowe pliki (np. logi, tymczasowe notatki, buildy). Bezpieczniej jest nazywać rzeczy po imieniu i dodawać dokładnie to, co ma wejść do commita.
Jeżeli chcesz przygotować naprawdę „czysty” commit, pomocna bywa interaktywna wersja:
git add -pPozwala dodać do indeksu tylko fragmenty zmian w pliku (tzw. hunks). W praktyce wykorzystasz to, gdy w jednym pliku przypadkiem zrobiłeś kilka niepowiązanych ze sobą modyfikacji i chcesz je rozbić na osobne commity.
Dobre wiadomości commitów – krótkie i konkretne
Podstawowy commit wygląda tak:
git commit -m "Opis zmiany"Zamiast ogólników typu „poprawki”, „zmiany” lepiej używać opisów, które odpowiedzą przyszłemu „ja” na pytanie: co tu się wydarzyło. Przykłady:
Dodaj funkcję logowania błędów do plikuRefaktoryzacja: wydziel walidację danych do osobnego modułuNapraw błąd #12 – obsługa pustego wejścia
Mit: „commit musi być perfekcyjnie opisany, inaczej cała historia jest bezużyteczna”. Rzeczywistość jest łagodniejsza – lepiej zrobić przyzwoity commit z krótkim, ale sensownym opisem niż w nieskończoność odkładać zapisanie pracy w pogoni za ideałem.
git push i git pull – synchronizacja z GitHubem
Po kilku commitach chcesz wysłać swoje zmiany na serwer:
git push
Jeśli wcześniej użyłeś git push -u origin main, Git zna domyślny cel i nie wymaga dodatkowych parametrów. Gdy pracujesz w zespole, przed rozpoczęciem dnia lub przed rozpoczęciem nowej funkcji opłaca się pobrać aktualny stan:
git pullTa komenda robi dwie rzeczy:
- ściąga nowe commity ze zdalnego repozytorium (
git fetch), - łączy je z Twoją lokalną gałęzią (domyślnie
git merge).
Jeżeli wolisz mieć większą kontrolę, można rozdzielić te kroki:
git fetch
git log HEAD..origin/main
git merge origin/mainDzięki temu najpierw sprawdzasz, co przyszło z serwera, a dopiero potem łączysz to ze swoimi zmianami.
Branchowanie i łączenie zmian: gałęzie bez straszenia
Po co w ogóle gałęzie w małym projekcie
W małych, jednoosobowych projektach pokusa bywa prosta: „i tak wszystko robię sam, po co mi branchowanie”. W praktyce nawet w pojedynkę gałęzie pomagają:
Jeśli interesują Cię konkrety i przykłady, rzuć okiem na: Docker dla początkujących: uruchom pierwszą aplikację w kontenerze.
- oddzielić duży eksperyment od stabilnej wersji,
- pracować nad kilkoma zadaniami równolegle,
- utrzymać główną gałąź w stanie nadającym się do publikacji/produkcji.
Przykład: przygotowujesz większy refaktoring, który może trwać kilka dni. Na gałęzi main trzymasz działającą wersję dla klienta, a wszystkie niepewne zmiany prowadzisz w oddzielnej gałęzi, np. refaktoryzacja-logiki.
Tworzenie nowej gałęzi i przełączanie się
Podstawowe operacje na gałęziach:
- lista gałęzi:
git branch - utworzenie nowej gałęzi z aktualnego commita:
git branch nowa-funkcja - przełączenie na inną gałąź:
git switch nowa-funkcjalub starsza składnia:
git checkout nowa-funkcja
Skrót, który wykorzystasz najczęściej:
Tworzenie i przełączanie w jednym kroku
Najwygodniejszy wariant to utworzenie gałęzi i od razu skok na nią:
git switch -c nowa-funkcjalub w starszej wersji Gita:
git checkout -b nowa-funkcja
Taka gałąź powstanie na bazie commita, na którym aktualnie stoisz (zwykle będzie to ostatni commit na main). Dlatego przed odgałęzieniem często robisz szybkie:
git switch main
git pulli dopiero wtedy:
git switch -c feature/koszykNazywanie gałęzi, żeby nie zwariować
Nazwy gałęzi nie są dla Gita, tylko dla ludzi. Dobrze, jeśli po dwóch tygodniach da się zgadnąć, o co chodziło autorowi. Kilka typowych konwencji:
feature/nazwa-funkcji– nowe funkcjebugfix/opis-błędu– poprawki błędówhotfix/krytyczny-problem– pilne, krytyczne zmianyrefactor/co-jest-porządkowane– duże porządki w kodzie
Mit: „musi istnieć jedna słuszna konwencja nazewnictwa gałęzi”. Rzeczywistość: ważna jest spójność w projekcie, a nie to, czy używasz feature/ czy feat/. Ustalcie prostą regułę i się jej trzymajcie.
Wysyłanie gałęzi na GitHuba i usuwanie po pracy
Nowo utworzonej lokalnie gałęzi GitHub jeszcze nie zna. Trzeba ją pierwszy raz wypchnąć:
git push -u origin nowa-funkcja
Od tej pory zwykłe git push wystarczy. Kiedy praca w gałęzi jest zakończona i połączona z main, można ją posprzątać:
git branch -d nowa-funkcja
Ta komenda usuwa gałąź lokalnie, jeśli jej zmiany są już w innej gałęzi (np. w main). Gdy naprawdę chcesz ją skasować mimo niepołączonych commitów:
git branch -D nowa-funkcjaNa GitHubie usuwasz gałąź np. z poziomu interfejsu WWW po zaakceptowaniu pull requesta, albo w terminalu:
git push origin --delete nowa-funkcjaŁączenie gałęzi lokalnie: git merge
Załóżmy, że masz dwie gałęzie: stabilną main i roboczą feature/logowanie. Po zakończonej pracy chcesz scalić zmiany z funkcjonalnej gałęzi do głównej:
git switch main
git pull
git merge feature/logowanieJeśli nikt w międzyczasie nie zmieniał tych samych fragmentów plików, Git połączy historię automatycznie. Powstanie tzw. commit scalający (merge commit), który będzie miał dwóch rodziców.
Jeżeli wykonujesz merge lokalnie, a potem wypychasz:
git pushGitHub zobaczy gotowy wynik scalenia. W małych projektach to prostsze niż budowanie osobnego workflow z pull requestami, chociaż obie metody można łączyć.
Scenariusz: szybka poprawka na mainie i gałąź poboczna
Częsty przypadek: pracujesz na gałęzi feature/panel-admina, a nagle trzeba poprawić literówkę na stronie głównej, którą serwuje main. Typowa sekwencja:
- zapisujesz aktualny stan w roboczej gałęzi:
git status git add . git commit -m "WIP: panel admina – przygotowanie widoków" - przełączasz się na
main:git switch main git pull - wprowadzasz poprawkę, commitujesz i wypychasz:
git commit -am "Popraw literówkę w nagłówku strony głównej" git push - wracasz do swojej gałęzi i aktualizujesz ją:
git switch feature/panel-admina git merge main
W efekcie robocza gałąź ma w sobie zarówno Twoją wcześniejszą pracę, jak i świeżą poprawkę z main.
Rebase zamiast merge – kiedy ma sens
Oprócz merge istnieje też rebase, które „przepisuje” historię tak, jakby praca w gałęzi zaczęła się później, na nowszym commicie. Dla przykładu:
git switch feature/panel-admina
git fetch
git rebase origin/main
Twoje commity zostaną przeniesione „na wierzch” aktualnej historii z main. Historia wygląda wtedy bardziej liniowo. W małych projektach to często kwestia gustu – prostsze bywa zwykłe merge.
Mit: „rebase jest niebezpieczny i trzeba go unikać”. Problemem nie jest samo narzędzie, ale używanie go do publicznej historii, na której pracują inni. Do porządkowania własnej, lokalnej historii przed wypchnięciem na serwer rebase jest bardzo przydatny.
Konflikty merge w praktyce: jak je rozpoznać i rozwiązać bez paniki
Kiedy powstaje konflikt
Konflikt pojawia się wtedy, gdy Git nie wie, którą wersję fragmentu pliku wybrać. Najczęściej dzieje się tak, gdy:
- Ty zmieniłeś ten sam wiersz, który zmienił ktoś inny,
- ktoś usunął plik, który Ty edytowałeś (lub odwrotnie),
- różne gałęzie zmodyfikowały ten sam fragment w sprzeczny sposób.
Przykład: dodajesz nowy tekst w stopce strony, kolega też zmienia stopkę i wypycha swoją wersję szybciej. Gdy robisz git pull albo merge jego gałęzi, Git nie jest w stanie zgadnąć, który tekst jest „prawidłowy”.
Jak wygląda konflikt w kodzie
Po nieudanym merge lub rebase zobaczysz komunikat w terminalu i status:
git status
pokaże pliki z dopiskiem unmerged. W pliku pojawią się specjalne znaczniki:
<<<<<<< HEAD
twoja wersja
=======
wersja z innej gałęzi
>>>>>>> feature/logowanie
Część między <<<<<<< HEAD a ======= to Twoje zmiany (z gałęzi, na której jesteś). Fragment między ======= a >>>>>>> pochodzi z gałęzi scalanej.
Rozwiązywanie konfliktu krok po kroku
Proces sprowadza się do trzech ruchów:
- Otwierasz pliki z konfliktem w edytorze albo IDE.
- Decydujesz, co ma zostać: Twoja wersja, druga wersja, albo jakaś kombinacja.
- Usuwasz znaczniki konfliktu i zapisujesz docelową treść pliku.
Następnie oznaczasz konflikty jako rozwiązane:
Jeśli chcesz pójść krok dalej, pomocny może być też wpis: Pierwsza wirtualna maszyna w VirtualBox: instalacja i ustawienia dla początkujących.
git add zmieniony-plik.exti kończysz operację:
- dla
merge:git commit - dla
rebase:git rebase --continue
Wsparcie narzędzi: IDE, edytory, mergetool
Zamiast ręcznie przekopywać się przez znaczniki, można wykorzystać wbudowane narzędzia:
- w Visual Studio Code – panel Source Control i przyciski Accept Current, Accept Incoming, Accept Both,
- w JetBrains (IntelliJ, PyCharm itd.) – Merge Conflicts z trzema panelami (baza, Twoje zmiany, zmiany z gałęzi scalanej),
- w terminalu – zdefiniowany
git mergetool(np.meld,kdiff3).
Aktywacja domyślnego narzędzia:
git mergetoolTo prostsze niż ręczne wycinanie fragmentów między znacznikami, szczególnie w dużych plikach.
Kiedy przerwać merge lub rebase
Zdarza się, że podczas scalenia orientujesz się, że to był zły moment (za dużo zmian, zła gałąź, pomyłka w poleceniu). Zamiast brnąć, lepiej wycofać całą operację:
- przerwanie trwającego merge:
git merge --abort - przerwanie trwającego rebase:
git rebase --abort
Po tym wracasz do stanu sprzed scalania. Dobre wyjście awaryjne, gdy konfliktów jest nagle kilkadziesiąt, bo ktoś równolegle przeorał połowę projektu.
Minimalizowanie konfliktów na co dzień
Spora część konfliktów jest do uniknięcia. Kilka prostych zasad pracy zmniejsza ich liczbę:
- często
git pullna roboczej gałęzi, zamiast trzymać ją tygodniami bez aktualizacji, - mniejsze, częstsze commity – łatwiej je scalić niż jedną ogromną paczkę zmian,
- dzielenie plików na mniejsze moduły, aby kilka osób rzadziej modyfikowało ten sam plik,
- ustalenie prostych reguł: np. kto dotyka którego fragmentu projektu przy większych refaktoringach.
Mit: „konflikty to znak, że zespół źle używa Gita”. W praktyce przy równoległej pracy nad tym samym kodem konflikty są naturalne – ważne, by szybko je rozpoznawać i sprawnie rozwiązywać, a nie uznawać je za katastrofę.
Pliki, których nie chcesz w repo: .gitignore i dobre nawyki
Po co w ogóle .gitignore
Git z definicji śledzi wszystko, co mu „podrzucisz”. Bez kontroli w repo lądują:
- pliki konfiguracyjne specyficzne dla jednego komputera,
- pliki generowane (buildy, artefakty, logi),
- tajne dane (hasła, klucze, tokeny API),
- śmieci edytorów:
.idea/,.vscode/, pliki tymczasowe.
Plik .gitignore pozwala wskazać, czego Git ma nie śledzić. Dzięki temu historia repozytorium jest czystsza, a ryzyko przypadkowego wypchnięcia wrażliwych danych – mniejsze.
Tworzenie i podstawowe wzorce w .gitignore
W katalogu głównym repozytorium tworzysz plik:
.gitignorea w nim linia po linii wpisujesz ścieżki lub wzorce:
# katalogi z buildem
dist/
build/
# pliki tymczasowe
*.log
*.tmp
# katalogi środowiska wirtualnego Pythona
venv/
.env/
# ustawienia IDE
.vscode/
.idea/Kilka zasad:
nazwa/– ignoruje katalog o tej nazwie,*.log– ignoruje wszystkie pliki kończące się na.log,!ważny.log– wyjątek: wymusza śledzenie pliku mimo poprzedniego wzorca.
.gitignore a pliki już śledzone
Dodanie wzorca do .gitignore nie usuwa z historii plików, które już są śledzone. Jeśli chcesz przestać śledzić plik, który wcześniej trafił do repo:
git rm --cached sekrety.json
git commit -m "Przestań śledzić sekrety.json"
--cached usuwa plik z indeksu, ale zostawia go fizycznie na dysku. Od tej pory, jeśli plik jest na liście .gitignore, Git będzie go pomijał.
Gotowe szablony .gitignore dla różnych technologii
Nie trzeba wymyślać wszystkiego samodzielnie. GitHub utrzymuje repozytorium z gotowymi .gitignore dla różnych języków i środowisk (Python, Node, Java, Unity itd.). Łatwo znaleźć je, tworząc nowe repozytorium na GitHubie – w formularzu pojawia się opcja wyboru szablonu.
Przykład fragmentu dla Node.js:
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
Mit: „jak dodam node_modules do repo, będzie wygodniej osobom, które klonują projekt”. W praktyce to głównie kłopot: ogromne repo, konflikty w zależnościach i śmieci w historii. Zależności odtwarza się z package.json, nie z repozytorium.
.gitignore globalne – ignorowanie śmieci z całego systemu
Najczęściej zadawane pytania (FAQ)
Po co mi Git, skoro mogę robić kopie plików w folderach?
Ręczne kopiowanie folderów działa tylko przy małych, prostych projektach. Gdy plików i zmian przybywa, szybko kończysz z katalogiem „final_v3_ostateczny_ostatni_POPRAWIONY” i brakiem pewności, która wersja jest „tą dobrą”. Git zamiast wielu kopii katalogów trzyma historię w jednym repozytorium i dokładnie wie, co zmieniło się w każdym kroku.
Mit brzmi: „Git to takie lepsze kopiuj-wklej”. W praktyce Git zapisuje strukturę historii, autora, datę i opis zmian, pozwala porównywać wersje linia po linii, cofać się do stabilnych punktów kontrolnych i łączyć pracę wielu osób. Tego zwykły folder z kopiami po prostu nie ogarnia.
Czym dokładnie różni się Git od GitHuba?
Git to program instalowany lokalnie – silnik do kontroli wersji. Działa w twoim katalogu projektu, trzyma historię zmian w ukrytym folderze .git i w ogóle nie potrzebuje internetu. Możesz tworzyć commity, branche i cofać się w historii nawet na komputerze odłączonym od sieci.
GitHub to z kolei platforma w chmurze, która przechowuje zdalne repozytoria Git i dodaje do nich „otoczkę”: interfejs WWW, pull requesty, recenzje kodu, zgłoszenia błędów, automatyczne testy. Mit: „GitHub to Git”. Rzeczywistość: Git jest standardem narzędzia, a GitHub tylko jednym z serwisów, który ten standard wykorzystuje (obok GitLaba, Bitbucketa itd.).
Czy Git ma sens, jeśli pracuję sam nad małym projektem?
Tak. Solo programista korzysta z Gita tak samo mocno jak zespół. Nawet przy małym projekcie masz historię swojej pracy dzień po dniu, możesz bez stresu eksperymentować na osobnych gałęziach i w każdej chwili wrócić do stabilnego commita sprzed większej refaktoryzacji.
Do tego Git ułatwia przenoszenie projektu między komputerami i buduje twoje portfolio – wrzucasz repozytorium na GitHuba i od razu masz coś konkretnego do pokazania. Mit, że „Git jest tylko dla dużych firm”, bierze się głównie stąd, że wiele osób poznaje go dopiero w pracy zespołowej.
Jak sprawdzić, czy Git jest poprawnie zainstalowany?
Po instalacji Gita otwórz terminal (na Windows może to być Git Bash) i wpisz:
git --version
Jeśli zobaczysz numer wersji, instalacja się udała. Dobrym kolejnym krokiem jest ustawienie swoich danych użytkownika, które trafią do każdego commita: git config --global user.name "Twoje Imię" oraz git config --global user.email "twoj.email@example.com". Zdarza się, że ktoś to pominie, a potem w historii ma anonimowe lub błędne dane – lepiej załatwić to od razu.
Co to jest commit w Git i co dokładnie zapisuje?
Commit to zapisany „punkt kontrolny” projektu. Git utrwala w nim zestaw zmian w plikach razem z unikalnym identyfikatorem (hashem), autorem, datą i krótkim opisem. W efekcie możesz później sprawdzić, kto co zmienił, kiedy to zrobił i jak dokładnie wyglądała różnica między wersjami.
Git jest szczególnie mocny dla plików tekstowych: kodu, konfiguracji, dokumentacji. Pozwala porównywać wersje linia po linii i szybko znaleźć moment, w którym „coś się popsuło”. Mit: „commit to tylko zapis pliku”. W rzeczywistości commit to migawka całego projektu w danym momencie, a nie pojedynczego pliku.
Czy Git zastępuje backup projektu?
Git częściowo pomaga w backupie, ale nie jest klasycznym systemem kopii zapasowych. Chroni przed utratą historii zmian, pozwala cofać się do dowolnego commita i odtworzyć konkretny stan kodu. Jeśli dodatkowo wypchniesz repozytorium na GitHuba czy GitLaba, masz kopię w chmurze, co jest realnym zabezpieczeniem przed awarią dysku.
Trzeba jednak pamiętać, że Git świetnie radzi sobie z tekstem, ale nie jest stworzony do przechowywania dużych binarnych plików czy snapshotów środowiska. Klasyczne backupy (np. całego systemu lub baz danych) dalej mają swoje miejsce – Git ich nie zastępuje, tylko uzupełnia.
Co wybrać do GitHuba: HTTPS czy SSH i dlaczego?
Na start HTTPS jest prostszy – używasz adresu repozytorium zaczynającego się od https:// i logujesz się hasłem lub tokenem. To wystarcza, jeśli dopiero testujesz Gita i GitHuba albo rzadko wysyłasz zmiany.
Przy częstszej pracy wygodniejsze jest SSH. Łączysz się wtedy przez adres git@github.com:..., a uwierzytelnianie odbywa się kluczem, więc nie wpisujesz hasła przy każdym git push. Krótko mówiąc: HTTPS jest „bez konfiguracji, ale więcej klikania”, SSH wymaga jednorazowej konfiguracji klucza, za to potem działa bez tarcia i jest standardem w poważniejszych projektach.
Co warto zapamiętać
- Git porządkuje chaos wersji plików, zastępując dziesiątki katalogów „final_v3_ostateczny” jedną, czytelną historią zmian, do której można wrócić jednym poleceniem.
- Każdy commit w Git to pełny pakiet informacji: kto, kiedy i co zmienił, wraz z dokładnym stanem plików – dzięki temu łatwo znaleźć moment, w którym coś się „popsuło”, i cofnąć konkretną zmianę.
- Mit, że Git to tylko „lepsze kopiuj-wklej folderu”, rozmija się z rzeczywistością – Git przechowuje całą strukturę historii, gałęzie i łączy zmiany wielu osób, czego zwykły backup nie ogarnia.
- Git i GitHub to nie to samo: Git jest lokalnym narzędziem do kontroli wersji, a GitHub platformą do hostowania repozytoriów, współpracy (pull requesty, code review, issues) i automatyzacji CI/CD.
- Przekonanie, że Git „przydaje się tylko w dużych zespołach”, jest mitem – solo programista zyskuje historię pracy, bezpieczne eksperymenty, łatwą migrację między komputerami i gotowe portfolio na GitHubie.
- Podstawowa konfiguracja po instalacji (user.name, user.email, domyślny edytor) jest kluczowa, bo te dane trafiają do każdego commita i decydują o tym, jak czytelna i użyteczna będzie historia zmian.
- Git najlepiej sprawdza się przy plikach tekstowych (kod, konfiguracje, dokumentacja); traktowanie go jak magazynu binarnych backupów marnuje jego największą zaletę – precyzyjne śledzenie różnic linia po linii.






