Łączenie (merge) — co to jest, jak działa merge i strategie scalania

Autor: IT Sectr Opublikowano: 2026-08-01 Czas czytania: 9 min

Merge — to operacja scalania gałęzi w Git, która łączy zmiany z dwóch różnych linii rozwoju w jedną docelową gałąź. W przeciwieństwie do rebase, merge zachowuje pełną historię rozgałęzień, tworząc specjalny commit scalania z dwoma rodzicami. Według oficjalnej dokumentacji Git (2026), merge jest najbezpieczniejszym sposobem łączenia gałęzi, ponieważ nie nadpisuje historii i pozwala śledzić, kiedy i które gałęzie zostały scalone. Jest to standardowy wybór do scalania w publicznych gałęziach, takich jak main, develop i release.

Najważniejsze

  • Merge — scalanie gałęzi z utworzeniem commita scalania, zachowującego historię obu gałęzi.
  • Commit scalania — specjalny commit z dwoma rodzicami, utrwalający fakt scalenia.
  • Strategie scalania — recursive, octopus, ours, squash — każda odpowiednia do różnych scenariuszy.
  • Konflikty — powstają przy jednoczesnej zmianie tych samych wierszy w obu gałęziach i wymagają ręcznego rozwiązania.
  • Bezpieczeństwo — merge nie zmienia istniejących commitów, dlatego jest bezpieczny dla publicznych gałęzi.

Co to jest merge w Git

Merge — to komenda git merge, która łączy zmiany z określonej gałęzi do bieżącej. Git znajduje wspólnego przodka (wspólny commit bazowy), oblicza diff każdej gałęzi względem przodka i tworzy commit scalania zawierający połączony zestaw zmian. Rezultat — gałąź docelowa zostaje uzupełniona wszystkimi zmianami ze scalanej gałęzi.

Składnia: będąc w gałęzi docelowej (np. main), wykonaj git merge feature. Git automatycznie tworzy commit scalania, jeśli nie ma konfliktów. W domyślnej wiadomości commita scalania podawane jest: „Merge branch 'feature' into main". Wiadomość można zmienić przez flagę -m lub edytować w otwartym edytorze.

Merge to operacja nieniszcząca. W przeciwieństwie do rebase, merge nie rusza istniejących commitów: pozostają one z tymi samymi hashami, autorami i datami. To czyni merge jedynym bezpiecznym sposobem scalania dla gałęzi, nad którymi jednocześnie pracuje wielu programistów. Jeśli coś pójdzie nie tak, merge można anulować komendą git merge --abort.

bash
# Przełącz na gałąź docelową
git checkout main

# Scal gałąź funkcji
git merge feature

# Wynik — commit scalania z dwoma rodzicami
git log --oneline --graph

# Scal z własną wiadomością
git merge feature -m "feat: integrate authentication module"

Rodzaje merge: regular, squash, fast-forward

Git obsługuje trzy tryby scalania, które wybiera się w zależności od pożądanego rezultatu. Regular merge (domyślny) tworzy commit scalania. Squash merge łączy wszystkie commity gałęzi funkcji w jeden. Fast-forward — przesuwa wskaźnik gałęzi bez tworzenia commita, jeśli to możliwe. Wybór trybu zależy od workflow zespołu i zasad historii.

Regular merge (--no-ff) — tworzy commit scalania nawet jeśli scalenie można wykonać jako fast-forward. Zalecany dla gałęzi main: commit scalania wyraźnie oznacza moment integracji funkcji i pozwala łatwo wycofać wszystkie zmiany gałęzi funkcji przez jeden revert commita scalania. GitHub domyślnie używa tego trybu przy scalaniu PR przez przycisk Merge.

Squash merge (--squash) — zbiera wszystkie commity gałęzi funkcji w jeden commit w gałęzi docelowej. Przydatny, gdy brudna historia gałęzi funkcji nie powinna trafić do main. Wadą jest utrata połączenia z oryginalnymi commitami — nie można zobaczyć, jak funkcja była rozwijana krok po kroku. GitHub używa tego trybu przy wyborze „Squash and merge" w PR.

Fast-forward (--ff) — jeśli gałąź docelowa nie ma nowych commitów po odgałęzieniu funkcji, Git po prostu przesuwa wskaźnik do przodu, bez tworzenia commita scalania. Historia pozostaje liniowa. Flaga --no-ff wymusza utworzenie commita scalania, --ff-only zakończy się błędem, jeśli fast-forward nie jest możliwy.

bash
# Wymuś commit scalania (zalecane dla main)
git merge --no-ff feature

# Scalenie squash — wszystkie commity w jeden
git merge --squash feature
git commit -m "feat: add authentication"

# Fast-forward tylko jeśli możliwe
git merge --ff-only feature

# Przerwij skonfliktowane scalenie
git merge --abort

Strategie scalania Git

Strategie scalania określają algorytm, którego Git używa do łączenia zmian. Każda strategia jest odpowiednia do różnych scenariuszy. Git automatycznie wybiera odpowiednią strategię, ale programista może wskazać ją jawnie przez flagę --strategy. Zrozumienie strategii pomaga przewidzieć zachowanie Git przy złożonych scaleniach.

Recursive — domyślna strategia do scalania dwóch gałęzi. Git znajduje wspólnego przodka, oblicza zmiany w każdej gałęzi i łączy je. Jeśli wspólny przodek został znaleziony, recursive poprawnie obsługuje zmiany nazw plików i dodawanie nowych. Przy konfliktach recursive może używać dodatkowych opcji: ours (automatycznie wybiera naszą wersję) i theirs (wybiera ich wersję).

Octopus — do jednoczesnego scalania więcej niż dwóch gałęzi: git merge feature1 feature2 feature3. Octopus nie obsługuje rozwiązywania konfliktów — wszystkie konflikty muszą być rozwiązane przed wywołaniem komendy. Używany rzadko, głównie do łączenia kilku niezależnych gałęzi, które gwarantowanie nie kolidują (np. różne moduły).

StrategiaLiczba gałęziRozwiązywanie konfliktów
Recursive2Automatyczne + opcje ours/theirs
Octopus3+Nie — wszystkie konflikty muszą być rozwiązane z góry
OursDowolnaZawsze wybiera naszą wersję, obce zmiany są ignorowane
Subtree2Do scalania poddrzew (subtree merge)

Ours — szczególna strategia, która całkowicie ignoruje zmiany ze scalanej gałęzi i zachowuje bieżącą zawartość gałęzi docelowej. Commit scalania jest tworzony, ale zawartość pozostaje bez zmian. Przydatna, gdy trzeba utrwalić w historii fakt scalenia, ale faktycznie odrzucić wszystkie zmiany z obcej gałęzi.

Rozwiązywanie konfliktów merge

Konflikt merge powstaje, gdy te same wiersze pliku zostały zmienione w obu gałęziach w różny sposób. Git nie może automatycznie określić, która wersja jest poprawna, i wstrzymuje merge. Konflikt może również powstać przy zmianie nazwy pliku w jednej gałęzi i jego modyfikacji w drugiej, lub przy jednoczesnym usunięciu i modyfikacji tego samego pliku.

Proces rozwiązywania: Git oznacza konfliktowe pliki markerami. W pliku pojawiają się fragmenty z <<<<<<< HEAD (nasza wersja), ======= (separator) i >>>>>>> feature (ich wersja). Programista ręcznie edytuje konfliktowy fragment, wybierając potrzebne wiersze z obu wersji, usuwa markery, zapisuje plik i dodaje go do indeksu przez git add.

Do wizualnego rozwiązywania konfliktów Git obsługuje mergetool — zewnętrzne narzędzie porównawcze. Popularne narzędzia mergetool: Meld, KDiff3, Beyond Compare, VS Code (wbudowany edytor konfliktów). Mergetool wyświetla trzy panele: naszą wersję, ich wersję i wynik. Programista wizualnie wybiera bloki kodu do włączenia do pliku końcowego.

bash
# Rozpocznij scalanie i wykryj konflikt
git merge feature
# KONFLIKT (treść): Konflikt scalania w src/main.swift

# Sprawdź skonfliktowane pliki
git status

# Otwórz wizualne narzędzie scalania
git mergetool

# Po rozwiązaniu — dodaj i zatwierdź
git add src/main.swift
git commit

# Przerwij scalanie
git merge --abort

Kiedy wybrać merge zamiast rebase

Merge jest preferowany nad rebase w kilku kluczowych sytuacjach. Pierwsza: podczas pracy z publicznymi gałęziami dostępnymi dla innych programistów. Merge nie nadpisuje historii, a współpracownicy mogą bezpiecznie synchronizować się. Rebase w publicznej gałęzi stworzy rozbieżną historię i konflikty u wszystkich, którzy już otrzymali stare commity.

Druga sytuacja: przy kończeniu gałęzi funkcji. Większość zespołów preferuje merge (z flagą --no-ff) do main, aby utrwalić moment integracji funkcji. Upraszcza to nawigację po historii i pozwala łatwo wycofać całą funkcję jednym git revert commita scalania. GitHub Flow domyślnie oferuje trzy opcje merge: prosty merge, squash merge i rebase merge.

Trzecia sytuacja: przy pracy z pull requestem, który przeszedł przegląd. GitHub i GitLab oferują przycisk merge z różnymi opcjami. Merge (Create a merge commit) — pełna historia z commitem scalania. Squash and merge — czysta historia bez szczegółów rozwoju. Rebase and merge — liniowa historia bez commita scalania, ale z nadpisaniem commitów. Wybór zależy od zasad zespołu.

  • Gałęzie publiczne (main, develop) — tylko merge, nigdy rebase.
  • Kończenie PR — merge z --no-ff dla utrwalenia momentu integracji.
  • Gałęzie z cudzymi commitami — merge nie nadpisuje cudzej pracy.
  • Przed wydaniem — merge jest bezpieczniejszy, ponieważ wiąże się z mniejszym ryzykiem.
  • Wspólna gałąź — jeśli nad gałęzią pracuje kilku programistów, merge jest obowiązkowy.

Najlepsze praktyki scalania gałęzi

Pierwsza zasada: zawsze być na aktualnej wersji gałęzi docelowej przed merge. Wykonaj git checkout main && git pull zanim scalisz funkcję. Minimalizuje to konflikty i gwarantuje, że commit scalania będzie zawierał wszystkie aktualne zmiany. Jeśli gałąź docelowa znacznie wyprzedziła, najpierw wykonaj git merge main w gałęzi funkcji, aby rozwiązać konflikty w jej kontekście.

Druga zasada: testować kod po merge. Merge może zmienić zachowanie, nawet jeśli nie było konfliktów. Pipeline CI/CD powinien przeprowadzić testy na commicie scalania przed wysłaniem do produkcji. Niektóre zespoły używają merge gates — obowiązkowych sprawdzeń, które blokują merge do czasu ich przejścia.

Trzecia zasada: dokumentować commity scalania. Standardowa wiadomość „Merge branch 'feature' into main" jest mało przydatna. Zaleca się dodawanie opisu tego, co zostało scalone: „Merge authentication module: login, registration, password recovery". Upraszcza to analizę historii i wyszukiwanie regresji. W dużych projektach commity scalania są automatycznie generowane z nazwy PR.

  • Aktualność — przed merge upewnij się, że gałąź docelowa jest zaktualizowana (git pull).
  • Testowanie — CI/CD powinien przeprowadzić testy na wynikowym commicie scalania.
  • Opisowe wiadomości — podawaj w commicie scalania, jaka funkcja została scalona.
  • Częstotliwość — scalaj gałęzie funkcji tak wcześnie i często, jak to możliwe (maksymalnie tydzień).
  • Anulowanie — git revert commita scalania cofa całą funkcję w całości.

Często zadawane pytania

Co znaczy łączyć (merge) gałęzie w Git?

Łączyć (merge) — wykonać git merge w celu połączenia zmian z jednej gałęzi do drugiej. Rezultatem jest commit scalania, który utrwala fakt scalenia i zawiera zmiany z obu gałęzi. Jest to podstawowy sposób integracji gałęzi funkcji z main, develop lub release w Git Flow.

Czym squash merge różni się od zwykłego merge?

Squash merge łączy wszystkie commity gałęzi funkcji w jeden commit w gałęzi docelowej, tracąc pośrednią historię rozwoju. Zwykły merge tworzy commit scalania, zachowując wszystkie commity gałęzi funkcji. Squash merge daje czystą historię, ale nie pozwala śledzić krokowego rozwoju funkcji.

Jak rozwiązać konflikt merge w Git?

Otwórz konfliktowy plik, znajdź fragmenty z markerami <<<<<<< HEAD i >>>>>>>. Edytuj treść, zostawiając potrzebne wiersze z obu wersji, usuń markery. Zapisz plik, wykonaj git add i git commit. Możesz użyć git mergetool do wizualnego rozwiązywania.

Kiedy używać merge zamiast rebase?

Merge jest zawsze używany dla publicznych gałęzi (main, develop, release), ponieważ nie nadpisuje historii. Rebase stosuje się w prywatnych gałęziach funkcji przed ich publikacją. Po tym, jak gałąź stała się częścią wspólnego repozytorium i inni programiści się do niej odwołali, dozwolony jest tylko merge.

Jak anulować merge w Git?

Przed zakończeniem merge (podczas konfliktu) — git merge --abort anuluje scalanie całkowicie. Po zakończeniu — git revert <merge-commit-hash> -m 1 tworzy commit cofający. Flaga -m 1 wskazuje, którą gałąź nadrzędną zachować (docelową). Git revert jest bezpieczniejszy niż git reset dla opublikowanych gałęzi.

Podsumowanie

  • Merge — bezpieczne scalanie gałęzi z zachowaniem historii i utworzeniem commita scalania z dwoma rodzicami.
  • Tryby scalania — regular (--no-ff), squash (--squash) i fast-forward (--ff) do różnych celów.
  • Strategie — recursive (domyślna), octopus (3+ gałęzie), ours (ignorowanie obcych zmian).
  • Konflikty — rozwiązywane ręcznie przez edycję oznaczonych fragmentów lub mergetool.
  • Bezpieczeństwo — merge nie zmienia istniejących commitów, dlatego jest bezpieczny dla publicznych gałęzi.
  • Squash merge — łączy wszystkie commity w jeden, tracąc pośrednią historię rozwoju.
  • Anulowanie merge — git revert commita scalania z flagą -m 1 do bezpiecznego cofnięcia opublikowanych zmian.

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.

Omów projekt

Przeczytaj również