Git merge vs rebase: różnice, przykłady i kiedy czego używać

  1. Strona główna
  2. Blog
  3. Tworzenie oprogramowania
Tworzenie oprogramowania

Git merge vs rebase: różnice, przykłady i kiedy czego używać

Wybór między Git merge a rebase decyduje o tym, jak wygląda historia projektu. Zobacz oba na tym samym przykładzie z prawdziwym wynikiem logu, poznaj jedną zasadę, która zapobiega katastrofom, i skopiuj bezpieczny proces pracy zespołu.

7 min czytania
Git merge vs rebase: różnice, przykłady i kiedy czego używać
Najważniejsze
  • Merge łączy dwie gałęzie nowym commitem scalającym i zachowuje historię dokładnie taką, jaka była.
  • Rebase odtwarza Twoje commity na wierzchu innej gałęzi, dając prostą linię, ale nowe hashe.
  • Nigdy nie rób rebase commitów, które inni już pobrali.
  • Rób rebase własnej gałęzi funkcji przed pull requestem, a przy włączaniu jej do głównej gałęzi używaj merge.

Twoja gałąź funkcji jest za main, a potrzebujesz nowej pracy. Git merge vs rebase to wybór między dwoma sposobami, by ją zdobyć, i oba są poprawne. Różnią się tym, jak wygląda historia potem.

Zbudowaliśmy malutkie repozytorium, uruchomiliśmy oba polecenia i wkleiliśmy prawdziwy wynik poniżej, żebyś porównał rezultat, zamiast go sobie wyobrażać. Dopiero zaczynasz z Gitem? Zacznij od naszego kursu Gita dla początkujących (po angielsku).

Co robią git merge i git rebase

git merge bierze końcówki dwóch gałęzi i je łączy. Jeśli obie mają nowe commity, Git tworzy commit scalający z dwoma rodzicami. Nic, co już istnieje, nie jest zmieniane.

git rebase bierze commity unikalne dla Twojej gałęzi, odkłada je na bok, przenosi gałąź na koniec drugiej, a potem odtwarza Twoje commity jeden po drugim. Odtworzone commity są nowymi commitami z nowymi hashami, choć ich zmiany są te same.

Git merge w praktyce

Nasz punkt wyjścia: commit A na main, dwa commity (F1, F2) na feature i jeszcze jeden commit (M1) dodany później do main. Teraz robimy merge main do feature.

git switch feature
git merge main
git log --oneline --graph

*   f507aab Merge main into feature
|\
| * 8842fb5 M1
* | 082cc6a F2
* | 5a71e3c F1
|/
* 8766865 A

Wykres pokazuje prawdziwą historię: dwie linie pracy, które się połączyły. Oryginalne commity F1 i F2 zachowują swoje hashe. Ceną jest dodatkowy commit scalający, a w ruchliwym projekcie wykres zamienia się w pajęczynę.

Git rebase w praktyce

Ten sam punkt wyjścia, ale tym razem robimy rebase feature na main.

git switch feature
git rebase main
git log --oneline --graph

* 1ff474b F2
* bf9149e F1
* 8842fb5 M1
* 8766865 A

Historia to jedna prosta linia, jakbyś zaczął pracę po M1. Spójrz na hashe: F1 miał 5a71e3c, a teraz ma bf9149e, F2 zmienił się z 082cc6a na 1ff474b. Git je przepisał i dlatego rebase wymaga ostrożności.

Merge i rebase obok siebie

AspektMergeRebase
Kształt historiiRozgałęziony wykres z commitami scalającymiJedna prosta linia
Istniejące commityBez zmianPrzepisane z nowymi hashami
KonfliktyRozwiązywane raz, w commicie scalającymMogą wymagać poprawy przy każdym odtwarzanym commicie
Bezpieczne na wspólnych gałęziachTakNie
Najlepsze doWłączania gotowej pracy do mainAktualizacji własnej gałęzi przed review

Wskazówka: jeśli nie możesz się zdecydować, zapytaj, kto jeszcze ma Twoją gałąź. Jeśli nikt, rebase jest bezpieczny. Jeśli kolega ją pobrał, użyj merge.

Złota zasada rebase

Nie rób rebase commitów, które istnieją poza Twoim repozytorium. Po rebase Twoja gałąź nie zgadza się już z kopią na serwerze, więc wypchnięcie wymaga wymuszenia. Jeśli kolega zbudował pracę na starych commitach, jego historia rozjeżdża się teraz z Twoją, a uporządkowanie tego jest bolesne.

Rebase własnej, prywatnej gałęzi funkcji jest w porządku. Rebase main lub dowolnej gałęzi używanej przez innych — nie.

Bezpieczny proces pracy zespołu

Ta rutyna utrzymuje czystą historię i nikogo nie zaskakuje. Większość zespołów stosuje ją przed swoim potokiem CI, takim jak ten z naszego poradnika GitHub Actions CI/CD (po angielsku).

git switch feature
git fetch origin
git rebase origin/main        # or: git pull --rebase
# fix conflicts, then: git add <file> && git rebase --continue
git push --force-with-lease   # only on your own branch

--force-with-lease odmawia nadpisania gałęzi na serwerze, jeśli ktoś wypchnął zmiany od Twojego ostatniego fetch, co zwykłe --force po cichu by zniszczyło. Gdy pull request zostanie zatwierdzony, zrób jego merge do main.

Jak cofnąć nieudany rebase

Rebase wygląda destrukcyjnie, ale stare commity przez jakiś czas zostają w reflog Gita, więc możesz wrócić.

git reflog                    # find the commit before the rebase
git reset --hard HEAD@{5}     # example position, check reflog first

Utwórz gałąź zapasową poleceniem git branch backup przed każdym ryzykownym rebase, a odzyskanie sprowadzi się do jednego polecenia. Uruchamiasz bazę danych lub narzędzia w kontenerach? Zajrzyj do naszego kursu Dockera dla początkujących (po angielsku).

Podsumowanie

Merge zachowuje prawdę, rebase utrzymuje ją w porządku. Używaj rebase, by odświeżyć własną gałąź, merge, by ją dostarczyć, i nigdy nie przepisuj historii, od której zależą inni.

Najczęściej zadawane pytania

Jaka jest różnica między git merge a git rebase?

Merge łączy dwie gałęzie commitem scalającym i zachowuje wszystkie istniejące commity. Rebase przenosi Twoje commity na wierzch innej gałęzi i je przepisuje, co daje liniową historię.

Używać merge czy rebase?

Rób rebase własnej gałęzi funkcji, by była aktualna, a merge przy dostarczaniu jej do wspólnej gałęzi takiej jak main. Używaj merge zawsze, gdy gałąź współdzielą inni.

Czy git rebase jest niebezpieczny?

Na gałęziach prywatnych jest bezpieczny, na wspólnych ryzykowny, bo przepisuje hashe commitów. Użyj gałęzi zapasowej i reflogu, by odzyskać stan, gdy coś pójdzie nie tak.

Co robi force-with-lease?

Wymusza push tylko wtedy, gdy zdalna gałąź jest wciąż tam, gdzie ostatnio ją widziałeś, więc nie nadpiszesz przypadkiem nowych commitów kolegi.

Czy rebase usuwa moje commity?

Nie. Tworzy nowe commity z tymi samymi zmianami, a stare zostają w reflogu, dopóki Git ich nie wyczyści.

Ucz się dalej (artykuły po angielsku)

Współpracuj ze Stack Quora

Potrzebujesz pomocy w testowaniu, WordPressie lub SEO?

Pomagamy zespołom dostarczać lepsze oprogramowanie i rozwijać ich strony. Opowiedz, nad czym pracujesz, a zaproponujemy jasny następny krok.

Czytaj dalej

Więcej poradników na testowanie, sztuczna inteligencja i nowoczesny rozwój

Podobał Ci się ten artykuł? Wybierz temat i przejdź bezpośrednio do naszych najnowszych tutoriali.

Sztuczna inteligencja

Wyjaśnienie halucynacji AI: dlaczego modele językowe tworzą rzeczy i jak je zmniejszyć

Wyjaśniono halucynacje AI: czym są, dlaczego powstają w modelach językowych, typowe typy, jak je zredukować za pomocą uziemień i podpowiedzi oraz pr…

Przeczytaj artykuł →
DevOps

Wyjaśnienie zmiennych środowiskowych: pliki .env, sekrety i konfiguracja wykonana prawidłowo

Zmienne środowiskowe wyjaśnione na przykładach Pythona, które przeprowadziliśmy: ich odczytywanie i ustawianie, dlaczego każda wartość jest ciągiem …

Przeczytaj artykuł →
Tworzenie oprogramowania

Wyjaśnienie ograniczenia szybkości interfejsu API: algorytmy, nagłówki i obsługa błędów 429

Ograniczanie szybkości API wyjaśnione za pomocą przeprowadzonej przez nas symulacji: zasobnik tokenów, stałe okno, przesuwane okno, 429 odpowiedzi, …

Przeczytaj artykuł →
Automatyzacja testów

Wyśmiewanie w Pythonie: unittest.mock, patch i błędy, które sprawiają, że testy kłamią

Wyśmiewanie w Pythonie za pomocą unittest.mock, przetestowane: Mock i zwracana wartość, efekt uboczny, łatanie tam, gdzie używana jest nazwa, specyf…

Przeczytaj artykuł →
Testowanie oprogramowania

Wyjaśnienie zasięgu kodu: pokrycie linii i oddziału oraz co naprawdę oznacza 100%

Wyjaśnienie pokrycia kodu za pomocą prawdziwego pliku cover.py: pokrycie linii, gałęzi i warunków, przeczytanie raportu, dlaczego 100% pokrycia może…

Przeczytaj artykuł →
Bazy danych i SQL

DELETE vs TRUNCATE vs DROP w SQL: różnice, wycofywanie i kiedy używać każdego z nich

DELETE vs TRUNCATE vs DROP wyjaśnione za pomocą przetestowanego SQL: co każdy usuwa, wycofywanie, wyzwalacze, resetowanie tożsamości, prędkość i czy…

Przeczytaj artykuł →
Bazy danych i SQL

Wyjaśnienie widoków SQL: tworzenie, używanie i unikanie pułapek wraz z przykładami

Widoki SQL wyjaśnione za pomocą zapytań, które uruchomiliśmy: tworzenie widoku, wyniki na żywo, ukrywanie kolumn, wydajność, widoki z możliwością ak…

Przeczytaj artykuł →
Tworzenie oprogramowania

Interfejs TypeScript a typ: rzeczywiste różnice, testowane za pomocą kompilatora

Interfejs TypeScript a typ, sprawdzony z prawdziwym kompilatorem: co oba mogą zrobić, co tylko jeden, łączenie deklaracji, rozszerzenia a przecięcia…

Przeczytaj artykuł →
Tworzenie oprogramowania

Python *args i **kwargs wyjaśnione: elastyczne funkcje z przejrzystymi przykładami

Python *args i **kwargs wyjaśnione za pomocą uruchomionego przez nas kodu: pakowanie i rozpakowywanie, kolejność parametrów, argumenty zawierające t…

Przeczytaj artykuł →
Tworzenie oprogramowania

Funkcje Lambda w Pythonie: składnia, rzeczywiste zastosowania i kiedy ich nie używać

Funkcje lambda w Pythonie wyjaśnione za pomocą uruchomionego przez nas kodu: składnia, sortowanie za pomocą klucza, mapa i filtr, domknięcia, pułapk…

Przeczytaj artykuł →
Sztuczna inteligencja

Kim są agenci AI? Jak one działają, dzięki prostej pętli agenta, którą możesz uruchomić

Kim są agenci AI? Prosty przewodnik po pętli agenta, narzędziach, pamięci i poręczach, z małą pętlą w Pythonie, którą uruchomiliśmy, prawdziwymi zag…

Przeczytaj artykuł →
DevOps

Monitorowanie a obserwowalność: prawdziwa różnica z logami, wskaźnikami i śladami

Wyjaśnienie monitorowania a obserwowalności: znane i nieznane awarie, dzienniki, metryki i ślady, opis incydentu przy kasie, złote sygnały, OpenTele…

Przeczytaj artykuł →
DevOps

Woluminy platformy Docker a mocowania powiązań: utrwalanie danych kontenera we właściwy sposób

Wyjaśniono woluminy Dockera a montowanie powiązań: dlaczego dane kontenera znikają, nazwane woluminy, montowanie powiązań, tmpfs, przykłady tworzeni…

Przeczytaj artykuł →
Automatyzacja testów

TDD vs BDD: kluczowe różnice, jedna funkcja zbudowana w obie strony i kiedy używać każdej z nich

TDD vs BDD wyjaśnione za pomocą jednej funkcji rabatowej zbudowanej w obie strony: refaktoryzacja czerwono-zielona z uruchomionym przez nas kodem, s…

Przeczytaj artykuł →
Tworzenie oprogramowania

Git merge vs rebase: różnice, przykłady i kiedy czego używać

Git merge vs rebase wyjaśnione na prawdziwym wyniku logu, z tabelą porównawczą, złotą zasadą rebase i bezpiecznym procesem pracy zespołu.

Przeczytaj artykuł →
Tworzenie oprogramowania

Python list comprehension: składnia, przykłady i kiedy jej unikać

Python list comprehension wyjaśnione: składnia, filtrowanie, if-else, zagnieżdżone pętle, zmierzone czasy i sytuacje, w których zwykła pętla for jes…

Przeczytaj artykuł →
Bazy danych i SQL

SQL JOIN – wyjaśnienie z przykładami (Inner, Left, Right, Full)

Zrozum złączenia SQL krok po kroku na przykładowych tabelach i zapytaniach: INNER, LEFT, RIGHT, FULL, CROSS i SELF, plus typowe błędy i wskazówki wy…

Przeczytaj artykuł →