Jaka jest różnica między git merge
i git rebase
?
Jaka jest różnica między git merge
i git rebase
?
Odpowiedzi:
Załóżmy, że pierwotnie było 3 commity, A
, B
, C
:
Następnie programista Dan stworzył zatwierdzenie D
, a programista Ed stworzył zatwierdzenie E
:
Oczywiście ten konflikt należy jakoś rozwiązać. W tym celu istnieją 2 sposoby:
POŁĄCZENIE :
Oba zatwierdzenia D
i E
wciąż tu są, ale tworzymy zatwierdzenie scalania, M
które dziedziczy zmiany po obu D
i E
. Tworzy to jednak kształt rombu , co dla wielu osób jest bardzo mylące.
REBASE :
Tworzymy zatwierdzenie R
, którego rzeczywista zawartość pliku jest identyczna z treścią zatwierdzenia scalania M
powyżej. Ale pozbywamy się zatwierdzenia E
, jakby nigdy nie istniało (oznaczone kropkami - znikającą linią). Z powodu tego zatarcia E
powinien 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!
git merge
nie przeplata zatwierdzeń (ale może się tak wydawać, patrząc na git log
). Zamiast tego git merge
zachowuje nienaruszone obie historie rozwoju autorstwa Dana i Eda, jak widać z każdego punktu widzenia na raz. git rebase
sprawia, ż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.
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
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:
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.
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 master
oddziału.
( Uwaga: jestem autorem postu „10 rzeczy, których nienawidzę w Git”, o którym mowa w innej odpowiedzi )
Chociaż zaakceptowana i najbardziej pozytywnie oceniana odpowiedź jest świetna, dodatkowo uznaję ją za przydatną próbę wyjaśnienia różnicy tylko słowami:
łączyć
rebase
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)
Baza Git jest bliższa scaleniu. Różnica w bazach wynosi:
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ć.
Znalazłem jeden naprawdę interesujący artykuł na temat git rebase vs merge , pomyślałem o udostępnieniu go tutaj