Zmiana historii: rebase w GitBashu

W ostatnim wpisie opisywałam, jak używać komendy merge do łączenia zmian. Dzisiaj czas na kolejną komendę – rebase.
Początek historii będzie taki sam, jak poprzednio. Dwóch autorów (autor1, autor2) pracuje na dwóch osobnych branchach (branch1, branch2). Każdy z nich wprowadza zmiany w tym samym pliku UserController.

Autor1: zmiany na branch1

Zmiany na tym branchu polegały na zmianie nazwy parametru metody w UserController.

branch1.JPG

Autor2: zmiany na branch2

Zmiany na tym branchu polegały na dodaniu sprawdzenia, czy obiekt nie jest nullem.

branch2.JPG

Po zakończeniu wprowadzania zmian czas na rebase. Jak to wygląda?

Autor1: rebase master_xmpl

Będąc na swoim branchu branch1, musi wpisać komendę:
git rebase master_xmpl
Dzięki niej zaktualizuje się historia pochodząca z głównego brancha. Należy jednak pamietać, żeby ten branch był zgodny z aktualną wersją, która jest na serwerze!
Wynikiem takiej komendy dla autor1 jest następujący komunikat:
rebase_branch1
Jak widać, wersja brancha master_xmpl zawarta na branchu branch1 jest aktualna. Rebase nie jest potrzebny, można zrobić merge bez problemów.

Git merge –ff-only

Żeby sprawdzić, czy należy robić rebase, wystarczy (będąc na głównym branchu) wywołać komendę
git merge –ff-only branch_name
Parametr –ff-only gwarantuje, że merge nie powiedzie się, jeśli historia głównego brancha jest różna między branchami i podczas próby merge występują jakieś konflikty. Konflikty mogą być rozwiązane automatycznie (tzw. fast-forward) – wtedy nie tworzy się dodatkowy commit (przy ustawieniach domyślnych, które oczywiście mogą zostać zmienione). Ale mogą być również konflikty takie, które nie mogą one być automatycznie rozwiązane, musimy sami ingerować w kod. Po nich powstaje dodatkowy commit.

Autor1: git merge –ff-only

git_merge_1
W tym przypadku nie jest potrzebny rebase, ponieważ merge przeszedł bez żadnych konfliktów.

Autor2: git merge –ff-only

git_merge_2

Niestety autor2 nie ma już tak łatwo. Jego wersja głównego brancha różni się od tej oryginalnej. Zwykły merge nie przejdzie, ponieważ pojawią się konflikty. Konieczny jest więc rebase.

Autor2: rebase master_xmpl

Co natomiast zobaczy autor2 po wpisaniu powyższej komendy? Zakładamy, że autor1 wrzucił swoje zmiany na branch master_xmpl.

rebase_branch2.JPG
Niestety pojawił się konflikt podczas próby automatycznego merge commita.
Rebase może składać się z kilku kroków. Informację o liczbie kroków zobaczymy w konsoli.
rebase_steps
W naszym przypadku jest tylko 1 commit, więc występuje tylko 1 etap zawierający konflikty. Przy większej liczbie commitów tych etapów byłoby odpowiednio więcej.
Po rozwiązaniu konfliktów z danego etapu rebase, należy użyć komendy
git rebase –continue
w celu kontynuowania rebase i przejścia do kolejnego etapu.
W naszym przypadku po ręcznym rozwiązaniu konfliktu i wpisaniu powyższej komendy zostaną wprowadzone zmiany i otrzymamy wynik:
rebase_continue.JPG
Jeśli nie chcemy z jakiegoś powodu wprowadzić zmian z danego commita, należy użyć komendy:
git rebase –skip
Jeśli zorientujemy się, że np. coś poszło nie tak i chcemy przerwać rebase, wystarczy komenda:
git rebase –abort
Wszystkie zmiany zostają cofnięte i możemy np. zacząć rebase od nowa.

Zakończenie rebase

Gdy autor2 skończy rebase, czy wystarczy, że wrzuci zmiany serwer i już może oddać kod do review? Niekoniecznie. Etap rozwiązywania konfliktów jest bardzo podatny na błędy. Osoba robiąca rebase (w tym przypadku autor2) powinien sprawdzić, czy kod się kompiluje, czy wszystkie testy przechodzą i ewentualnie sprawdzić, czy działają zmieniane ostatnio funkcjonalności. Dopiero po tym etapie można wysłać kod do review.

Podsumowanie

Oczywiście należy pamiętać o tym, że komenda rebase nie jest lekiem na całe zło. Sprawdza się bardzo dobrze w sytuacji, którą przedstawiłam – gdy mamy PRYWATNY branch, z którego nie korzysta nikt inny i który chcemy zaktualizować do najnowszej wersji np. głównego brancha. W momencie, gdyby nasz branch byłby publiczny i współdzielony z inną osobą – jeśli zrobilibyśmy rebase, powstałby bałagan w historii i zsynchronizowanie wersji obydwu osób mogłoby zająć trochę czasu.
Należy pamiętać o tym, że rebase zmienia historię. To znaczy, że nasze commity, które zmieniły swojego parenta, zostają skopiowane jako nowe commity, z nowymi id:
history
Wcześniej commit „renamed parameter” miał id c87da2 – rebase w tym przypadku nie był potrzebny, więc id commita zostało takie samo. W przypadku drugiego commita „added check if user is null”, który miał id 7adb71 stało się inaczej. Zrobiliśmy rebase, więc został mu przyznany nowy id 72cfae.

Podoba Ci się to, co tworzę? Chcesz dostawać informacje o:
– wydarzeniach, które organizuję lub wspieram (np. konferencje, meetupy, webinary)
– inicjatywach, które organizuję lub wspieram (np. GeekWeekWro, DevAdventCalendar)
– moich prelekcjach, kursach i szkoleniach
– wyróżnionych artykułach z mojego bloga

0% SPAMu, 100% informacji! Krótko i na temat.

2 uwagi do wpisu “Zmiana historii: rebase w GitBashu

Dodaj komentarz