Git merge vs rebase - różnice i zastosowania

📅

Dzisiaj wrócimy do tematów związanych z kontrolą wersji. Dwa często używane polecenia - git merge i git rebase, dość często powodują problemy ze zrozumieniem ich działania. W tym wpisie porównamy je do siebie oraz omówimy ich przypadki użycia.

Git Merge

git merge to polecenie, które integruje zmiany z jednej gałęzi do drugiej (głównie z gałęzi typu feature do gałęzi master lub main). Jest to powszechna operacja łączenia kodu, zwłaszcza gdy nad projektem pracuje wiele osób.

# Przełącz się na gałąź do której chcesz scalić zmiany
git checkout master
 
# Scalenie zmian z gałęzi feature do gałęzi master
git merge feature

W powyższym scenariuszu wszystkie zmiany wprowadzone w gałęzi feature zostaną zintegrowane z gałęzią master. Git tutaj stworzy niemal zawsze nowego commita, aby połączyć zmiany z obydwu gałęzi. Ten nowy commit jest znany jako merge commit.

Merge commit zachowuje historyczne informacje o rozgałęzieniach i pokazują dokładnie, kiedy i gdzie dana gałąź odbiegła od naszej głównej gałęzi. Jest to świetne rozwiązanie do przechowywania szczegółowej historii, ale może skutkować złożoną, trudną do analizy i nieliniową historią commitów.

Git Merge przedstawiony graficznie
Źródło: https://www.atlassian.com/git/tutorials/using-branches/git-merge

Git Rebase

Z kolei git rebase to kolejny sposób na integrację zmian z jednej gałęzi do drugiej, ale działa on nieco inaczej. Zamiast tworzyć nowy merge commit, git rebase przenosi lub łączy commity, tworząc liniową historię commitów.

# Przełącz się na gałąź, którą chcesz zrebase'ować
git checkout feature
 
# Zrebase'uj zmiany z gałęzi master do gałęzi feature (czyli aktualizuj gałąź feature o najnowsze zmiany z gałęzi master)
git rebase master

W tym przykładzie zmiany z gałęzi feature są ponownie nakładane na gałąź master, a wynikowa historia wygląda tak, jakby zmiany zostały wprowadzone zaczynając od najnowszego commita gałęzi master.

Rebasing oferuje czystą, liniową historię. Jest to doskonałe rozwiązanie w sytuacjach, gdy chcesz, aby gałąź danego feature-a była aktualna z najnowszym kodem z innej gałęzi.

animacja obrazująca rebase
Źródło: https://blog.mralx.com/git-rebase/

👍 Kiedy używać merge, a kiedy rebase?

Zarówno komenda git merge, jak i git rebase służą pewnemu konkretnemu celowi. W zależności od sytuacji należy wybrać jedną z nich.

Użyj merge, gdy:

Chcesz połączyć kod z dwóch różnych gałęzi i zachować dokładny zapis historyczny. Merge są przydatne do integracji gałęzi długo żyjących (long-lived feature branch) z powrotem do głównego kodu (gałęzi master, main lub develop).

Użyj rebase, gdy:

Pracujesz nad gałęzią funkcji i musisz włączyć najnowsze zmiany z głównej gałęzi. Rebasing pomaga zachować aktualność naszej gałęzi bez zaśmiecania historii commitów niepotrzebnymi merge commitami.

👎 Kiedy NIE używać merge i rebase

Tak jak mają swoje przypadki użycia, git merge i git rebase mają również sytuacje, w których nie są najlepszym wyborem.

Unikaj merge, gdy:

Masz do czynienia z krótkotrwałą gałęzią i chcesz mieć czystą, liniową historię. Wielokrotne scalenia w krótkim odstępie czasu mogą sprawić, że historia commitów będzie trudna do zrozumienia.

Unikaj rebase, gdy:

Masz do czynienia z publiczną, współdzieloną gałęzią, na której inni mogli oprzeć swoją pracę. Rebase przepisuje historię commitów, co może powodować konflikty i problemy dla innych deweloperów.

Przydatne wskazówki

Mając za sobą jasne zrozumienie git merge i git rebase, zanurzmy się głębiej i poznajmy kilka przydatnych wskazówek, które mogą usprawnić nam pracę z tymi poleceniami.

Merge

Rebase

Najczęstsze błędy

Pamiętajmy, że jak każde narzędzie, poznane przez nas polecenia mogą przynieść niepożądane rezultaty, jeśli zostaną niewłaściwie użyte. Rzućmy okiem na kilka typowych błędów popełnianych przez deweloperów za pomocą git merge i git rebase oraz sposoby ich uniknięcia.

Merge

Rebase

Kluczem do uniknięcia błędów z git merge i git rebase jest zrozumienie działania tych poleceń i ich wpływu na historię commitów. Dzięki przemyślanemu podejściu do mergowania i rebasowania można zachować czystą historię commitów, jednocześnie minimalizując zamieszanie w zespole.

Jak zawsze nie bój się eksperymentować i popełniać błędów, ponieważ są one częścią procesu uczenia się. Pamiętaj, że każdy błąd jest okazją do nauczenia się czegoś nowego i nie myli się tylko ten, który nic nie robi 💪

Porównanie

Zbiorcze porównanie omawianych przez nas poleceń.

AspektGit MergeGit Rebase
CelŁączy commity z różnych gałęziPrzenosi lub łączy commity do nowego commita bazowego
Historia commitówZachowuje całą historię; Tworzy nowy merge commitZapewnia czystszą, liniową historię poprzez jej przepisanie
ZłożonośćOgólnie prostsze w użyciu; Mniej ryzykowneMoże być skomplikowany dla nowych użytkowników; Wymaga lepszego zrozumienia Gita.
KonfliktyKonflikty muszą być rozwiązywane tylko razKażdy ponownie zastosowany (przeniesiony) commit może potencjalnie powodować konflikt
Przypadki użyciaŚwietnie nadaje się do łączenia ukończonych dużych feature-ów lub długo żyjących branchyPrzydatne do włączania najnowszych zmian z głównej gałęzi do feature branchy
Użycie z publicznym repo.Bezpieczny w użyciuMoże powodować problemy; nie powinien być używany w gałęziach publicznych
Używaj, gdy:Gdy chcesz zachować kontekst historycznyGdy chcesz mieć czystą, liniową historię
Nie używaj, gdy:Gdy chcesz uniknąć wielu merge commitów w krótkim czasieGdy gałąź jest współdzielona, ponieważ przepisuje historię commitów

Podsumowanie

Zrozumienie git merge i git rebase jest kluczowe dla efektywnej współpracy i utrzymania czystej bazy kodu. Podczas gdy oba polecenia mogą integrować zmiany z jednej gałęzi do drugiej, robią to na różne sposoby i służą różnym celom.

Pamiętaj, że nie chodzi o to, które z nich jest lepsze — chodzi o to, które jest bardziej odpowiednie w danej sytuacji. Dzięki jasnemu zrozumieniu obu poleceń możesz teraz dokonać właściwego wyboru dla swojego projektu.