Opisywane przez nas do tej pory scenariusze scalania kodu były stosunkowo proste, gdyż właściwie nie wymagały od nas podejmowania żadnych decyzji.
Musieliśmy jedynie wykonywać kolejne komendy w zależności od zaistniałej sytuacji. Teraz przyszedł czas na to, aby zająć się nieco bardziej skomplikowanym
przypadkiem polegającym na rozwiązywaniu konfliktu występującego w trakcie merge'a.
Manualne mergowanie
Przeanalizujmy scenariusz, w którym mamy dwóch programistów pracujących nad tym samym kodem. Załóżmy, że programista numer 1 to nasz kolega pracujący w zespole, a
programistą numer 2 jesteśmy my.
-
Programista 1 tworzy nowego brancha (np. feature/Change-list-to-set) po to by zmodyfikować typ zwracanej wartości w metodzie read w pliku UserService.java.
Jak pamiętamy z rozdziału Git - Tworzenie gałęzi (branchy) metoda zwracała listę. Teraz ma zwracać Seta.
-
Programista 2 tworzy nowego brancha (np. feature/Change-list-to-sorted-set) również po to by zmodyfikować typ zwracanej wartości w metodzie read w pliku UserService.java.
Też chciałby zwracać tutaj zbiór, ale dodatkowo uznał, że lepiej by ten zbiór był posortowany. Tak więc od teraz, według kodu tego brancha, metoda będzie zwracać SortedSet.
-
Programista 1 merguje swoje zmiany do lokalnego brancha master, a następnie pushuje te zmiany do zdalnego repozytorium.
Tym samym obecnie na zdalnym branchu master metoda read zwraca interfejs Set.
-
Programista 2 przełącza się na lokalnego brancha master i pobiera zmiany z jego zdalnego odpowiednika, po czym uruchamia komendę merge.
W tym momencie okazuje się, że zamiast oczekiwanego scalenia w postaci recursive merge programista otrzymuje informację o konflikcie:
-
Programista 2 musi się więc dowiedzieć co jest przyczyną jego problemów. W tym celu uruchamia komendę:
W rezultacie otrzymuje informacje o plikach, których nie udało się automatycznie zmergować:
W takim przypadku programista musi wyedytować taki problematyczny plik i zmienić go ręcznie. Wchodząc do pliku można łatwo
odnaleźć miejsca, w których nie powiodło się wykonanie automatycznego merge'a. Wygląda to tak:
W pliku programista znajduje charakterystycznie oznaczone bloki kodu. Pierwszy z nich należy do programisty 2 (tego, który teraz próbuje mergować), a drugi do programisty 1 (tego, który zmergował już wcześniej).
Rozwiązanie konfliktu polega na podjęciu decyzji, która wersja kodu ma pozostać (w naszym przypadku jest to tylko jedna linia kodu, ale zmiana może dotyczyć także wielu linii) oraz na
manualnym usunięciu kodu, który według wiedzy programisty 2 jest starszy i już nieaktualny.
Tak więc programista numer 2 wybiera swoje zmiany jako te finalne gdyż wie, że obecne wymagania są takie, iż metoda read
ma nie tylko zwracać zbiór zamiast listy, ale też że ten zbiór ma być dodatkowo posortowany.
Programista usuwa też dodatkowe oznaczenia <<<...,>>>... itp.
- Programista 2 komituje zmiany bez podawania dodatkowych informacji o komicie. Git sam przygotuje stosowny komunikat, który będzie zawierał
dane o konfliktach oraz o tym, że zostały one rozwiązane.
Komunikat ten zostanie wyświetlony w domyślnym edytorze.
Na tym etapie, jeśli w dalszym ciągu programista chce coś zmienić w przygotowanej informacji, nadal może to zrobić.
Wystarczy, ze wyedytuje zawartość wyświetlonej informacji.
Na końcu, niezależnie od tego czy coś zmieniał czy nie, plik musi zostać zapisany, tak aby cały proces zakończył się sukcesem.
- Programista 2 wypycha zmiany do zdalnego repozytorium, które od teraz zawiera manualnie zmergowany przez niego kod.
Autor: Jarek Klimas
Data: 03 stycznia 2024
Labele: Backend, Podstawowy, Java
Czy informacje, które otrzymałeś, były pomocne?
Jeśli tak, zapraszam Cię do podarowania mi kawy.