GitMergeRebase

Git – Łączenie gałęzi, merge & rebase

Git daje nam możliwość tworzenia gałęzi, możemy mieć ich wiele i na każdej inną część kodu tworzącą całość po złączeniu. Git merge oraz git rebase, bo o nich będzie mowa, mechanizm pozwalający scalać, łączyć dwie gałęzie w jedną. Zapraszam do lektury 🙂

Git merge big picture

Tworząc rewizję jedną za drugą, uzyskamy historię liniową. Gdy dodajemy nowy branch wychodzący z komita X oraz drugi branch również wychodzący z tego samego komita to mamy sytuacje jak na obrazku (rys 1)
ExampleTwoBrnachesFromOne

Teraz poznamy mechanizm pozwalający łączyć dwie rozbieżne gałęzie w jedną rewizję (rys 2)

MergeTwobranchesIntoOneSchema

Dwa przypadki łączenia gałęzi

Łącząc gałęzie, możemy wyróżnić dwa przypadki:

  • Przewijanie do przodu (ang. fast forward)
  • Łączenie gałęzi rozłącznych

Uwaga

Podczas łączenia dwóch gałęzi w jeden komit, mogą powstać tak zwane konflikty. W tym wpisie przedstawię sytuację bez konfliktów. Konflikty zademonstruje w przyszłych wpisach tej serii.

Przewijanie do przodu (ang. fast forward)

Przewijanie do przodu, oznacza, że podczas wykonywania operacji łączenia dwóch gałęzi, jedna jest zawarta w drugiej. Gdzie gałąź BranchA jest zawarta w gałęzi BranchB. Przykład (rys 3)
FastForwardExample
W tej sytuacji możemy mówić o dołączeniu gałęzi BranchB do gałęzi BranchA.

Przejdźmy do przykładu w kodzie:

Polecenie git merge BranchB powoduje łączenie do aktualnej gałęzi(czyli BranchA), gałęzi o nazwie BranchB. Po wykonaniu tej komendy, gałąź BranchA wskazuje na tę samą rewizję co gałąź BranchB.
Zobrazuje powyższy merge(rys 4):
schemaMergedTwoBranches
Jeżeli chcielibyśmy wykonać powyższą operację na odwrót

Wykonując polecenia w konsoli, dostaniemy komunikat Already up-to-date.
Komunikat informuje o tym, że nie zostały wykonane żadne zmiany w repozytorium, ponieważ gałąź BranchB zawiera wszystkie rewizje gałęzi BranchA.

Łączenie gałęzi rozłącznych

Poniżej przedstawiam obraz struktury repozytorium, który będziemy chcieli połączyć (rys 5):
disjointBranches
Przechodzimy na gałąź BranchA poleceniem git checkout branchA a następnie wykonujemy polecenie git merge BranchB. Powstanie nam taka struktura (rys 6):
MergeDiffrentBranches
Po wykonaniu operacji merge warto zwrócić uwagę, że na naszej ostatniej rewizji pojawi się komunikat: Merge branch ‚BranchB’ into BranchA. Oczywiście, to jaki jest komunikat zależy tylko od nas, możemy zaakceptować domyślny lub podać własny.

Łączenie gałęzi rozłącznych — praktyka

Teraz zademonstruje praktyczny przykład z komendami, które możesz uruchomić u siebie na środowisku, żeby lepiej zrozumieć działanie merge 🙂

W skrócie co robimy:

  • Inicjalizujemy nowe repo
  • Dodajemy nowy plik a.txt, dodajemy go do staging area, komitujemy
  • Sprawdzamy historie rewizji oraz podglądamy stan fizycznych plików w naszym working directory. Mamy jeden komit a oraz pliki a.txt
  • W miejscu rewizji a tworzymy nowy branch BranchB
  • Dodajemy nowy plik c.txt(cały czas na gałęzi master), dodajemy go do staging area, komitujemy
  • Sprawdzamy historie rewizji oraz podglądamy stan fizycznych plików w naszym working directory. Mamy dwa komity a i c oraz pliki a.txt i c.txt
  • Przechodzimy na gałąź BranchB. Teraz w tej gałęzi mamy tylko jeden komit i jeden plik.
  • Dodajemy nowy plik b.txt, dodajemy go do staging area, komitujemy
  • Sprawdzamy historie rewizji oraz podglądamy stan fizycznych plików w naszym working directory. Mamy dwa komity a i b oraz pliki a.txt i b.txt
  • Przechodzimy na gałąź master
  • Wykonujemy łączenie gałęzi git merge BranchB
  • Sprawdzamy historie rewizji oraz sprawdzamy stan fizyczyny plików. Mamy trzy komity a, b, c oraz pliki a.txt, b.txt i c.txt

Wycofanie operacji merge

Nasz ostatni komit możemy wycofać i wrócić do stanu sprzed merga

Przykład

Obecnie nasze rewizje wyglądają następująco:

Jeżeli nasza ostatnia rewizja jest mergem i chcemy wycofać nasz merge, ponieważ uznaliśmy, że coś poszło nie tak, to musimy wykonać następujące kroki (a raczej krok :))

Po wykonaniu polecenia git reset hard HEAD~

będąc na gałęzi master, nasza historia rewizji przyjmuje postać sprzed merge’a.

Git rebase

Przykładowe repozytorium dla git rebase (rys 1)
schemaRepoGitRebase

Teraz będziemy chcieli połączyć dwie gałęzie, w wyniku czego uzyskamy obraz historii liniowej. Aby tego dokonać, należy:

  • Przejść na gałąź BranchB używając polecenia git checkout BranchB
  • Wydamy polecenie połączenia gałęzi git rebase BranchC

Po wydaniu polecenia git rebase BranchC naszym oczom ukaże się komunikat:

Zmiany, jakie nastąpiły po zastosowaniu git rebase używając polecenia git checkout BranchB, możemy interpretować jako zastosowanie zmian w rewizjach BranchB używając polecenia b1,b2,b3 do repozytorium będącego w stanie rewizji c2.

W wyniku uzyskamy repo tak jak na (rys 2)
gitRebaseLineHistory
Zwróć uwagę komity(z apostrofem pojedynczym) b1′,b2′,b3′ posiadają takie same pliki, modyfikacje, zmiany itp. Nie są to jednak te same rewizje w rozumieniu SHA-1 względem komitów(bez apostrofu) b1,b2,b3, mówiąc inaczej SHA-1 rewizji b1 i b1′ będą inne. Z punktu widzenia projektu, synchronizacji będą to nowe komity dodane do naszej historii. W przypadku git rebase należy pamiętać, że te operacje można stosować, wtedy i tylko wtedy, gdy rewizje b1,b2,b3 nie zostały wypchnięte do repo, ‚pushniętę’, udostępnionę.

Jeżeli zaś mamy sytuację jak na (rys 3)
rebaseSimilarMerge
Gdzie gałąź bieżąca jest zawarta w gałęzi dołączonej, to uzyskamy taki sam efekt co przy użyciu git merge.

Podsumowanie

Mechanizm łączenia dwóch gałęzi to kwintesencja systemu kontroli wersji, jaką jest GIT. W tym wpisie pokazałem jedną z prostszych sytuacji, kiedy możemy stosować łączenie gałęzi.

Wspomniałem, że podczas łączenia gałęzi mogą powstać konflikty, czyli jeżeli dwie osoby dokonują zmiany w tym samym miejscu danego pliku, to wtedy musimy ręcznie ustalić, jak ma wyglądać połączenie danego elementu, ale o tym będę jeszcze pisać 🙂 Na obecną chwilę należy pamiętać, że możemy łączyć gałęzie w gicie, nie tracąc przy tym danych 🙂

Jeżeli masz jakieś problemy albo coś jest niezrozumiałe, to daj mi znać, zrobię wszystko, co w mojej mocy, aby rozwiać Twoje wątpliwości 🙂

 

 

 
Pozdro 🙂
 

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

*