Kiedy użyjesz różnych strategii scalania git?

429

Na stronie podręcznika git-merge dostępnych jest wiele strategii scalania.

  • resolver - To może rozwiązać tylko dwie głowy (tj. bieżącą gałąź i inną gałąź, z której wyciągnąłeś) przy użyciu 3-kierunkowego algorytmu scalania. Próbuje ostrożnie wykrywać niejednoznaczności łączenia krzyżowego i jest ogólnie uważany za bezpieczny i szybki.

  • rekurencyjny - To może rozwiązać tylko dwie głowy za pomocą 3-kierunkowego algorytmu scalania. Jeśli istnieje więcej niż jeden wspólny przodek, którego można użyć do łączenia 3-kierunkowego, tworzy ono połączone drzewo wspólnych przodków i używa go jako drzewa referencyjnego dla łączenia 3-kierunkowego. Zgłoszono, że powoduje to mniej konfliktów scalania bez powodowania błędnego łączenia przez testy wykonane na rzeczywistych zatwierdzeniach scalania pobranych z historii rozwoju jądra Linux 2.6. Dodatkowo może to wykrywać i obsługiwać połączenia obejmujące zmiany nazw. Jest to domyślna strategia scalania podczas ciągnięcia lub łączenia jednej gałęzi.

  • ośmiornica - rozwiązuje więcej niż dwie głowy, ale odmawia wykonania skomplikowanego scalania, które wymaga ręcznego rozwiązania. Jest przeznaczony przede wszystkim do łączenia ze sobą głów oddziałów tematycznych. Jest to domyślna strategia scalania podczas ciągnięcia lub łączenia więcej niż jednej gałęzi.

  • nasz - To rozwiązuje dowolną liczbę głów, ale wynikiem scalania jest zawsze bieżąca głowa główki. Ma on służyć do zastąpienia starej historii rozwoju bocznych gałęzi.

  • poddrzewo - jest to zmodyfikowana strategia rekurencyjna. Podczas łączenia drzew A i B, jeśli B odpowiada poddrzewowi A, B jest najpierw dostosowywane do struktury drzewa A, zamiast odczytywania drzew na tym samym poziomie. Korekta ta jest również wykonywana dla wspólnego drzewa przodków.

Kiedy powinienem podać coś innego niż domyślny? Dla jakich scenariuszy każdy jest najlepszy?

Otto
źródło

Odpowiedzi:

305

Nie znam determinacji, ale użyłem innych:

Rekurencyjne

Rekursywne jest ustawieniem domyślnym dla połączeń nie do szybkiego przewijania. Wszyscy go znamy.

Ośmiornica

Użyłem ośmiornicy, kiedy miałem kilka drzew, które musiały zostać połączone. Widać to w większych projektach, w których wiele oddziałów miało niezależny rozwój i wszystko jest gotowe do połączenia w jedną całość.

Gałąź ośmiornicy łączy wiele głów w jednym zatwierdzeniu, o ile może to zrobić czysto.

Na przykład wyobraź sobie, że masz projekt, który ma wzorzec, a następnie trzy gałęzie do połączenia (nazwij je a, b i c).

Seria połączeń rekurencyjnych wyglądałaby tak (zwróć uwagę, że pierwsze scalenie było przewijaniem do przodu, ponieważ nie wymuszałem rekurencji):

seria połączeń rekurencyjnych

Jednak pojedyncze scalenie ośmiornicy wyglądałoby tak:

commit ae632e99ba0ccd0e9e06d09e8647659220d043b9
Merge: f51262e... c9ce629... aa0f25d...

połączenie ośmiornicy

Nasz

Nasz == Chcę wciągnąć kolejną głowę, ale wyrzucę wszystkie zmiany, które wprowadza głowa.

Utrzymuje to historię oddziału bez żadnych efektów oddziału.

(Przeczytaj: Nie analizuje się nawet zmian między tymi gałęziami. Gałęzie są po prostu scalone i nic się nie dzieje z plikami. Jeśli chcesz scalić się z drugą gałęzią i za każdym razem pojawia się pytanie „nasza wersja pliku lub ich wersja ”, której możesz użyć git merge -X ours)

Poddrzewo

Poddrzewo jest przydatne, gdy chcesz scalić inny projekt z podkatalogiem bieżącego projektu. Przydatne, gdy masz bibliotekę, której nie chcesz uwzględniać jako submoduł.

Dustin
źródło
1
Więc jedyną prawdziwą zaletą Ocotopus jest zmniejszenie liczby zatwierdzeń scalania w drzewie?
Otto,
60
Nie musisz określać strategii scalania ośmiornicy : jest ona używana automatycznie, jeśli scalisz więcej niż dwie gałęzie ( git merge A B ...).
Jakub Narębski,
Przepraszam, że wychodzę z tematu, ale z jakiego narzędzia wykonałeś te zrzuty ekranu? Wygląda jak naprawdę świetna / ładna wizualizacja historii oddziału ...
Bernd Haug
4
gitg dla tych w środowisku Linux.
Akash Agrawal
2
Ta wskazówka -X oursjest niesamowita, właśnie zaoszczędziła mi godzinę pracy.
Michael
49

Właściwie jedyne dwie strategie, które chciałbyś wybrać, są nasze, jeśli chcesz porzucić zmiany wprowadzone przez gałąź, ale zachowaj gałąź w historii i poddaj się, jeśli łączysz niezależny projekt w podkatalogu superprojektu (np. „Git-gui” w „ repozytorium git).

Scalanie ośmiornicy jest używane automatycznie podczas łączenia więcej niż dwóch gałęzi. Rozwiązanie jest tutaj głównie z powodów historycznych, a także w przypadku, gdy trafiają Cię przypadki narożników strategii scalania rekurencyjnego .

Jakub Narębski
źródło
Musiałem wybrać „rozwiązywanie” zamiast domyślnego „rekurencyjnego” dla scalania dwóch głowic, które miały fatalne błędy drzewa git-write-tree. Strategia „Resolve” połączyła się czysto. Być może miało to związek z przenoszeniem wielu plików w łączonym oddziale.
thaddeusmt
@thaddeusmt: Ciekawe. Czy możesz, jeśli to w ogóle możliwe, opublikować raport o błędzie dotyczący niepowodzenia strategii rekurencyjnej łączenia z listą dyskusyjną? Z góry dziękuję.
Jakub Narębski
@ JakubNarębski Nie jestem pewien, jak zebrałbym wystarczającą ilość informacji, aby złożyć znaczący raport o błędzie, jestem n00b z Git, przepraszam. Jak wspomniałem w mojej odpowiedzi tutaj ( stackoverflow.com/a/10636464/164439 ), zgaduję, że miało to związek ze mną, powielaniem zmian w obu gałęziach, a „rozwiązanie” lepiej pomija zduplikowane zmiany.
thaddeusmt
@ JakubNarębski do tej pory możesz także wybrać ich , co jest zgodne z instrukcją „przeciwną do naszej . Ich nie jest wybierana automatycznie dla Ciebie.
Obyś
3
@SebTu: nie ma theirsstrategii scalania (to znaczy --strategy=theirs), ale istnieje theirsopcja domyślnej recursivestrategii scalania (to znaczy --strategy=recursive --strategy-option=theirslub po prostu -Xtheirs).
Jakub Narębski
23

Strategia scalania „Resolve” vs „Recursive”

Rekursywna jest obecnie domyślną strategią dwóch głowic, ale po kilku poszukiwaniach w końcu znalazłem informacje o strategii scalania „rozstrzygnij”.

Zaczerpnięte z książki O'Reilly Kontrola wersji z Git ( Amazon ) (parafraza):

Pierwotnie „rozdzielczość” była domyślną strategią łączenia Git.

W sytuacjach łączenia krzyżowego, gdy istnieje więcej niż jedna możliwa podstawa scalania, strategia rozstrzygania działa w ten sposób: wybierz jedną z możliwych baz scalania i miej nadzieję na najlepsze. To nie jest tak złe, jak się wydaje. Często okazuje się, że użytkownicy pracowali nad różnymi częściami kodu. W takim przypadku Git wykrywa, że ​​remerguje niektóre zmiany, które już są na miejscu i pomija zduplikowane zmiany, unikając konfliktu. Lub, jeśli są to niewielkie zmiany, które powodują konflikt, przynajmniej konflikt powinien być łatwy do rozwiązania dla programisty.

Pomyślnie scaliłem drzewa przy użyciu „rozwiązania”, które nie powiodło się przy domyślnej strategii rekurencyjnej. Otrzymywałem fatal: git write-tree failed to write a treebłędy i dzięki temu wpisowi na blogu ( kopia lustrzana ) próbowałem „-s rozwiązać”, który zadziałał. Nadal nie jestem do końca pewien, dlaczego ... ale myślę, że było tak, ponieważ miałem zduplikowane zmiany w obu drzewach i rozwiązałem je poprawnie.

thaddeusmt
źródło
Używam 3-kierunkowego scalania (p4merge) i miałem konflikty zapisane do pliku .BASE, gdy scalanie rekurencyjne nie powiodło się. W tym przypadku pomógł powrót do strategii rozwiązywania.
mrzl
-2

Ponieważ powyższe odpowiedzi nie pokazują wszystkich szczegółów strategii. Na przykład, niektóre odpowiedź brakuje szczegółów dotyczących importu resolveopcji i recursivektóry ma wiele opcji jako podrzędne ours, theirs, patience, renormalize, itd.

Dlatego polecam odwiedzić oficjalną gitdokumentację, która wyjaśnia wszystkie możliwe funkcje:

https://git-scm.com/docs/merge-strategies

Rene B.
źródło