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.
- 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
| Aspekt | Merge | Rebase |
|---|---|---|
| Kształt historii | Rozgałęziony wykres z commitami scalającymi | Jedna prosta linia |
| Istniejące commity | Bez zmian | Przepisane z nowymi hashami |
| Konflikty | Rozwiązywane raz, w commicie scalającym | Mogą wymagać poprawy przy każdym odtwarzanym commicie |
| Bezpieczne na wspólnych gałęziach | Tak | Nie |
| Najlepsze do | Włączania gotowej pracy do main | Aktualizacji 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)
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.
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.
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ł →DevOpsWyjaś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 oprogramowaniaWyjaś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ówWyś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 oprogramowaniaWyjaś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 SQLDELETE 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 SQLWyjaś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 oprogramowaniaInterfejs 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 oprogramowaniaPython *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 oprogramowaniaFunkcje 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 inteligencjaKim 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ł →DevOpsMonitorowanie 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ł →DevOpsWoluminy 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ówTDD 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 oprogramowaniaGit 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 oprogramowaniaPython 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 SQLSQL 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ł →