Korzystanie z gałęzi

Opcje i przykłady strategii scalania Git

Gdy fragment pracy jest ukończony, przetestowany i gotowy do połączenia z główną linią projektową, zespół musi dokonać wyborów koncepcyjnych. Jakie są opcje strategii łączenia? W artykule przeanalizujemy poszczególne możliwości, a następnie przedstawię kilka wskazówek, jak to robimy w firmie Atlassian. Mam nadzieję, że ułatwię w ten sposób podjęcie ostatecznej decyzji, które rozwiązanie będzie najlepsze dla zespołu.

Strategie scalania w Git

Scalenie następuje w momencie połączenia dwóch gałęzi. Git obiera co najmniej dwa wskaźniki commitów i próbuje znaleźć między nimi wspólny commit bazowy. Git dysponuje kilkoma różnymi metodami znajdowania commitu bazowego, które nazywa się „strategiami scalania”. Gdy Git znajdzie wspólny commit bazowy, tworzy nowy „commit scalenia” obejmujący połączone zmiany ze wskazanych commitów scalenia. Z technicznego punktu widzenia commit scalenia jest zwykłym commitem o dwóch commitach nadrzędnych.

Polecenie git merge automatycznie wybierze strategię scalania, jeśli nie jest ona wyraźnie określona. Poleceniom git merge i git pull można przekazać opcję -s (strategia). Opcję -s można uzupełnić o nazwę strategii scalania. Jeśli nie zostanie ona wyraźnie określona, Git wybierze najbardziej odpowiednią strategię scalania na podstawie podanych gałęzi. Poniżej przedstawiam listę dostępnych strategii scalania.

Recursive

git merge -s recursive branch1 branch2

Operuje na dwóch wskaźnikach gałęzi. „Recursive” stanowi domyślną strategię scalania w przypadku ściągania lub scalania jednej gałęzi. Dodatkowo może wykryć i obsłużyć scalanie ze zmianą nazwy, ale obecnie nie umożliwia zastosowania wykrytych kopii. To domyślna strategia scalania w przypadku ściągania lub scalania jednej gałęzi.

Rozwiąż

git merge -s resolve branch1 branch2

Pozwala jedynie rozwiązać scalanie dwóch wskaźników gałęzi za pomocą trzykierunkowego algorytmu. Ostrożnie wykrywa niejednoznaczności wynikające ze scalania krzyżowego. Strategia ta powszechnie uznawana jest za szybką i bezpieczną.

Octopus

git merge -s octopus branch1 branch2 branch3 branchN

Domyślna strategia scalania w przypadku więcej niż dwóch wskaźników HEAD. Gdy przekazywana jest więcej niż jedna gałąź, automatycznie uruchomiona zostaje strategia Octopus. Jeśli podczas scalania wystąpią konflikty wymagające ręcznego rozwiązania, Octopus odmówi próby scalania. Strategia ta służy przede wszystkim do łączenia wskaźników gałęzi funkcji o podobnych cechach.

Ours

git merge -s ours branch1 branch2 branchN

Strategia Ours działa na liczbie N gałęzi. Wyjściowym wynikiem scalania jest zawsze wynik bieżącego wskaźnika gałęzi. Termin „ours” oznacza, że preferowane jest efektywne ignorowanie wszystkich zmian z pozostałych gałęzi. Strategia ta służy do łączenia historii gałęzi funkcji o podobnych cechach.

Subtree

git merge -s subtree branchA branchB

Rozszerzenie strategii „recursive”. W przypadku scalania elementów A i B, jeśli B jest poddrzewem A, to najpierw aktualizowany jest element B, aby odzwierciedlić strukturę drzewa A. Ta aktualizacja dotyczy również wspólnego drzewa nadrzędnego współdzielonego przez A i B.

Rodzaje strategii scalania w Git

Scalanie jawne

Scalanie jawne jest domyślnym typem scalania. Element „jawności” polega na tym, że tworzony jest nowy commit scalenia. Zmienia to historię commitów i wyraźnie wskazuje, gdzie został wykonany commit scalenia. Treść commitu scalenia również jest jawna w tym sensie, że pokazuje, które commity były nadrzędne w stosunku do commitu scalenia. Niektóre zespoły unikają jawnego scalania, ponieważ rzekomo wprowadza to zamieszanie w historii projektu.

Scalanie niejawne przez zmianę bazy danych lub scalanie z przewijaniem (fast-forward)

Squashowanie przy scalaniu, zazwyczaj bez jawnego scalania

Opcje strategii scalania „recursive”

Przedstawiona powyżej strategia „recursive” dysponuje własnym podzbiorem dodatkowych opcji operacyjnych.

ours

Nie należy tego mylić ze strategią scalania Ours. Ta opcja powoduje automatyczne rozwiązywanie konfliktów w prosty sposób przez faworyzowanie wersji „naszej”. Zmiany ze strony „ichniej” są automatycznie uwzględniane, jeśli nie powodują konfliktów.

theirs

Odwrotność strategii „ours”. Opcja „theirs” faworyzuje obce drzewo w przypadku rozwiązywania konfliktów.

patience

Ta opcja poświęca dodatkowy czas na wykluczenie błędnych scaleń na nieistotnych zbieżnych wierszach. Najlepiej z niej korzystać, gdy scalane gałęzie są mocno rozbieżne.

diff-algorithim
ignore-*

    ignore-space-change
    ignore-all-space
    ignore-space-at-eol
    ignore-cr-at-eol

Zestaw opcji dotyczących znaków odstępu. Każdy wiersz pasujący do podzbioru przekazanej opcji zostaje zignorowany.

renormalize

Ta opcja powoduje wyewidencjonowanie i zaewidencjonowanie wszystkich drzew git podczas rozwiązywania trójstronnego scalania. Przeznaczona jest do stosowania przy scalaniu gałęzi o różnych stanach zaewidencjonowania/wyewidencjonowania.

no-normalize

Wyłącza opcję „renormalize”. Powoduje to zastąpienie zmiennej konfiguracyjnej merge.renormalize.

no-renames

Ta opcja umożliwia ignorowanie podczas scalania plików o zmienionej nazwie.

find-renames=n

Jest to zachowanie domyślne. Scalanie „recursive” będzie honorowało zmiany nazw plików. Za pomocą parametru n można podać próg podobieństwa zmian nazw. Domyślna wartość n to 100%.

subtree

Ta opcja czerpie ze strategii „subtree”. Podczas gdy strategia operuje na dwóch drzewach i modyfikuje sposób ich dopasowania na wspólnym elemencie nadrzędnym, ta opcja operuje na metadanych ścieżki drzewa celem ich dopasowania.

Nasza polityka scalania Git

Atlassian zdecydowanie preferuje scalanie jawne. Powód jest bardzo prosty: scalanie jawne zapewnia doskonałą identyfikowalność i dostarcza kontekst łączonych funkcji. Przed udostępnieniem gałęzi funkcji do przeglądu zalecamy wykonanie operacji zmiany bazy, aby uporządkować lokalną historię. Nie oznacza to odstępstwa od powyższych założeń. Stanowi ich rozszerzenie.

Chcesz przejść do tworzenia gałęzi?

Wypróbuj ten interaktywny samouczek.

Zacznij już teraz