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

499

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

Daniel Peñalba
źródło
14
ponieważ moja odpowiedź została usunięta, odwiedź ten link, aby uzyskać właściwą odpowiedź na to pytanie: git-scm.com/book/en/Git-Branching-Rebasing#The-Basic-Rebase
HiB
6
Przy okazji dodam tę stronę. Wszystko, co musisz wiedzieć o git learn, grając: pcottle.github.io/learnGitBranching
Rollyng
Przeczytaj najpierw: git-scm.com/book/en/v2/... Następnie: git-scm.com/book/en/v2/Git-Branching-Rebasing Naprawdę zrozumiesz.
Liber

Odpowiedzi:

867

Załóżmy, że pierwotnie było 3 commity, A, B, C:

ABC

Następnie programista Dan stworzył zatwierdzenie D, a programista Ed stworzył zatwierdzenie E:

ABCDE

Oczywiście ten konflikt należy jakoś rozwiązać. W tym celu istnieją 2 sposoby:

POŁĄCZENIE :

ABCDEM

Oba zatwierdzenia Di Ewciąż tu są, ale tworzymy zatwierdzenie scalania, Mktóre dziedziczy zmiany po obu Di E. Tworzy to jednak kształt rombu , co dla wielu osób jest bardzo mylące.

REBASE :

ABCDER

Tworzymy zatwierdzenie R, którego rzeczywista zawartość pliku jest identyczna z treścią zatwierdzenia scalania Mpowyżej. Ale pozbywamy się zatwierdzenia E, jakby nigdy nie istniało (oznaczone kropkami - znikającą linią). Z powodu tego zatarcia Epowinien być lokalny dla programisty Ed i nigdy nie powinien być wypychany do żadnego innego repozytorium. Zaletą bazy jest to, że unika się kształtu diamentu , a historia pozostaje przyjemną linią prostą - większość programistów to uwielbia!

mvp
źródło
53
Ładne ilustracje. Jednak nie do końca zgadzam się z pozytywnym tonem, że obsługiwany jest rebase. Zarówno podczas scalania, jak i zmiany bazy mogą wystąpić konflikty wymagające ręcznego rozwiązania. I jak zawsze, gdy w grę zaangażowani są programiści, istnieje niezaprzeczalna szansa na błędy, czyli błędy. Jeśli wystąpi błąd scalania, cały zespół lub społeczność może zobaczyć scalenie i sprawdzić, czy został tam wprowadzony błąd. Historia rebase pozostaje w repozytorium 1 dewelopera i nawet tam ma ograniczony czas życia w reflogu. Może to wyglądać ładniej, ale nikt inny nie widzi tak łatwo, co poszło nie tak.
Uwe Geuder,
> „To jednak tworzy kształt rombu, co dla wielu osób jest bardzo mylące”. Um ... możesz opracować?
Greg Maletic
@GregMaletic: Kształt diamentu to historia nieliniowa. Nie wiem o tobie, ale ogólnie nie lubię rzeczy nieliniowych. To powiedziawszy, możesz używać scalania z diamentami, jeśli naprawdę wolisz - nikt cię nie zmusza.
mvp
1
Chociaż ta odpowiedź jest niezwykle pomocna, lepiej byłoby dodać rzeczywiste polecenia git z prostymi plikami foo.txt, aby odtworzyć je lokalnie. Jak powiedział ostatni użytkownik, nie jest oczywiste, kto robi bazy.
Vortex
1
@pferrel: Nie sądzę, że masz to poprawnie. git mergenie przeplata zatwierdzeń (ale może się tak wydawać, patrząc na git log). Zamiast tego git mergezachowuje nienaruszone obie historie rozwoju autorstwa Dana i Eda, jak widać z każdego punktu widzenia na raz. git rebasesprawia, że ​​wygląda na to, że Dan najpierw nad tym pracował, a Ed poszedł za nim. W obu przypadkach (scalanie i rebase) rzeczywiste wynikowe drzewo plików jest absolutnie identyczne.
mvp
158

Bardzo podoba mi się ten fragment z 10 rzeczy, których nienawidzę w git (w drugim przykładzie podaje krótkie wyjaśnienie dotyczące bazy zwrotnej):

3. Nędzna dokumentacja

Strony podręcznika są jednym wszechmocnym „kurwa ty” 1 . Opisują polecenia z perspektywy informatyka, a nie użytkownika. Przykładem:

git-push – Update remote refs along with associated objects

Oto opis dla ludzi:

git-push – Upload changes from your local repository into a remote repository

Aktualizacja, inny przykład: (dzięki cgd)

git-rebase – Forward-port local commits to the updated upstream head

Tłumaczenie:

git-rebase – Sequentially regenerate a series of commits so they can be 
             applied directly to the head node

A potem mamy

git-merge - Join two or more development histories together

co jest dobrym opisem.


1. bez cenzury w oryginale

mvw
źródło
Problemem nie jest język ani to, czy użytkownik jest informatykiem, czy nie. Przeredagowanie go w inny sposób pomaga wyjaśnić cele (tj. Co się dzieje), ale nie wyjaśnia sposobów (jak to się dzieje). Git wymaga zrozumienia środków, aby zrozumieć cele. To właśnie zrozumienie środków sprawia, że ​​Git jest tak trudny. Jako narzędzie, coś, co upraszcza lub zmniejsza wysiłek wymagany w zadaniu, Git kończy się strasznie. Niestety, zbyt wielu deweloperów nie zdaje sobie z tego sprawy.
ATL_DEV
128

Osobiście nie uważam, aby standardowa technika diagramowania była bardzo pomocna - strzałki zawsze wydają mi się niewłaściwe. (Zazwyczaj wskazują na „rodzica” każdego zatwierdzenia, co kończy się cofnięciem w czasie, co jest dziwne).

Aby to wyjaśnić słowami:

  • Kiedy ponownie ustawiasz gałąź na jej gałęzi, mówisz Gitowi, aby wyglądało to tak, jakbyś dokładnie sprawdził ich gałąź, a potem wykonał całą pracę od tego momentu. To tworzy czysty, koncepcyjnie prosty pakiet zmian, który ktoś może sprawdzić. Możesz powtórzyć ten proces ponownie, gdy pojawią się nowe zmiany w ich gałęzi i zawsze skończysz z czystym zestawem zmian „na końcu” ich gałęzi.
  • Kiedy scalisz ich gałąź z gałęzią, w tym momencie łączymy dwie historie gałęzi. Jeśli zrobisz to ponownie później, wprowadzając więcej zmian, zaczniesz tworzyć przeplatany wątek historii: niektóre z nich, niektóre z moich zmian, niektóre z nich. Niektórzy uważają to za niechlujne lub niepożądane.

Z powodów, których nie rozumiem, narzędzia GUI dla Git nigdy nie poczyniły wiele wysiłku, aby bardziej przejrzysto przedstawić historie scalania, wyodrębniając poszczególne połączenia. Więc jeśli chcesz mieć „czystą historię”, musisz użyć bazy.

Wydaje mi się, że pamiętam, że przeczytałem posty na blogach od programistów, którzy używają tylko bazy danych i innych, którzy nigdy nie używają bazy danych.

Przykład

Spróbuję wyjaśnić to na przykładzie słów. Powiedzmy, że inne osoby w twoim projekcie pracują nad interfejsem użytkownika, a ty piszesz dokumentację. Bez bazy Twoja historia może wyglądać mniej więcej tak:

Write tutorial
Merge remote-tracking branch 'origin/master' into fixdocs
Bigger buttons
Drop down list
Extend README
Merge remote-tracking branch 'origin/master' into fixdocs
Make window larger
Fix a mistake in howto.md

Oznacza to, że scala i zatwierdza interfejs użytkownika w środku zatwierdzeń dokumentacji.

Jeśli zmieniłeś kod na master zamiast scalić go, wyglądałoby to tak:

Write tutorial
Extend README
Fix a mistake in howto.md
Bigger buttons
Drop down list
Make window larger

Wszystkie twoje commity znajdują się na górze (najnowsze), a następnie reszta masteroddziału.

( Uwaga: jestem autorem postu „10 rzeczy, których nienawidzę w Git”, o którym mowa w innej odpowiedzi )

Steve Bennett
źródło
42

Chociaż zaakceptowana i najbardziej pozytywnie oceniana odpowiedź jest świetna, dodatkowo uznaję ją za przydatną próbę wyjaśnienia różnicy tylko słowami:

łączyć

  • „OK, mamy dwa różnie rozwinięte stany naszego repozytorium. Połączmy je razem. Dwoje rodziców, jedno dziecko wynikające ”.

rebase

  • „Daj zmiany głównej gałęzi (niezależnie od jej nazwy) mojej gałęzi funkcji. Zrób to, udając, że moja praca nad funkcjami rozpoczęła się później, w rzeczywistości w obecnym stanie głównego oddziału. ”
  • „Przepisz historię moich zmian, aby to odzwierciedlić”. (trzeba je wymusić, bo w wersjonowaniu chodzi o to, by nie manipulować przy danej historii)
  • „Prawdopodobnie - jeśli zmiany, które zgarnąłem, nie mają wiele wspólnego z moją pracą - historia nie zmieni się zbyt wiele, jeśli spojrzę na moje commity diff by diff (możesz również pomyśleć o„ łatach ”).”

Podsumowanie: Gdy to możliwe, rebase jest prawie zawsze lepszy. Ułatwienie ponownej integracji z głównym oddziałem.

Ponieważ? Work twoja praca fabularna może być prezentowana jako jeden duży „plik łatki” (inaczej diff) w odniesieniu do głównej gałęzi, bez konieczności „wyjaśniania” wielu rodziców: co najmniej dwóch, pochodzących z jednego scalenia, ale prawdopodobnie o wiele więcej, jeśli istnieje było kilka fuzji. W przeciwieństwie do scalania, wiele baz nie sumuje się. (kolejny duży plus)

Frank Nocke
źródło
18

Baza Git jest bliższa scaleniu. Różnica w bazach wynosi:

  • lokalne zatwierdzenia są tymczasowo usuwane z oddziału.
  • uruchom git pull
  • wstaw ponownie wszystkie lokalne zatwierdzenia.

Oznacza to, że wszystkie lokalne zatwierdzenia są przenoszone na koniec, po wszystkich zdalnych zatwierdzeniach. Jeśli masz konflikt scalania, musisz go również rozwiązać.

Willem Franco
źródło
7

Dla łatwego zrozumienia można zobaczyć moją figurę.

Rebase zmieni hash zatwierdzenia, więc jeśli chcesz uniknąć wielu konfliktów, po prostu użyj rebase, gdy gałąź jest ukończona / ukończona jako stabilna.

wprowadź opis zdjęcia tutaj

Nhan Cao
źródło
0

Znalazłem jeden naprawdę interesujący artykuł na temat git rebase vs merge , pomyślałem o udostępnieniu go tutaj

  • Jeśli chcesz zobaczyć historię tak samo, jak to się stało, powinieneś użyć scalania. Scalanie zachowuje historię, a rebase przepisuje ją.
  • Scalanie dodaje nowe zatwierdzenie do Twojej historii
  • Rebasing jest lepszy, aby usprawnić złożoną historię, możesz zmienić historię zatwierdzania przez interaktywny rebase.
nagendra547
źródło