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 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 :
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!
Ł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
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 )
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)
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ć.
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.
Odpowiedzi:
Załóżmy, że pierwotnie było 3 commity,
A
,B
,C
:Następnie programista Dan stworzył zatwierdzenie
D
, a programista Ed stworzył zatwierdzenieE
:Oczywiście ten konflikt należy jakoś rozwiązać. W tym celu istnieją 2 sposoby:
POŁĄCZENIE :
Oba zatwierdzenia
D
iE
wciąż tu są, ale tworzymy zatwierdzenie scalania,M
które dziedziczy zmiany po obuD
iE
. 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 scalaniaM
powyżej. Ale pozbywamy się zatwierdzeniaE
, jakby nigdy nie istniało (oznaczone kropkami - znikającą linią). Z powodu tego zatarciaE
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!źródło
git merge
nie przeplata zatwierdzeń (ale może się tak wydawać, patrząc nagit log
). Zamiast tegogit 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):
A potem mamy
co jest dobrym opisem.
1. bez cenzury w oryginale
źródło
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.
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:
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:
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 )
źródło
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)
źródło
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ć.
źródło
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.
źródło
Znalazłem jeden naprawdę interesujący artykuł na temat git rebase vs merge , pomyślałem o udostępnieniu go tutaj
źródło