Git jako najpopularniejszy rozproszony system kontroli wersji – może się pochwalić rozbudowanym zbiorem funkcjonalności oraz różnego rodzaju integracji – co pozwala wykorzystać go swobodnie w wielu codziennych zadaniach.
W ramach tego materiału dowiesz się jak scalać ze sobą gałęzie (ang. git merge) oraz w jak rozwiązywać konflikty powstałe podczas scalania.
Spis treści
- 1 Git merge – wprowadzenie
- 2 Git install – instalacja Git
- 3 Git
- 4 Git merge | git merge branch – scalanie gałęzi
- 5 Git merge conflict – konflikty w trakcie łączenia gałęzi
- 6 Git abort merge – przerwanie scalania
- 7 Git revert merge – cofnięcie scalania
- 8 Git revert merge commit – cofanie commit’a ze zdalnego repozytorium
- 9 Git revert
- 10 Git merge – scalanie gałęzi – podsumowanie
- 11 20+ BONUSOWYCH materiałów z programowania
Git merge – wprowadzenie
Z tego materiału dowiesz się:
- Czym jest i jak działa git merge?
- Jak scalać gałęzie za pomocą git merge?
- Jak rozwiązywać powstałe konflikty (ang. git merge conflicts)?
Git install – instalacja Git
Jeżeli nie masz jeszcze Gita zainstalowanego lokalnie – szybko możesz to nadrobić.
W poniższym materiale znajdziesz instrukcję, jak można to zrobić.
➡ ZOBACZ 👉: Install Git – Instalacja Git, Windows, Ubuntu – Bash, GUI
Git
W ramach tego materiału zajmiemy się przede wszystkim scalaniem branch’y (git merge) oraz rozwiązywaniem powstałych konfliktów – natomiast kompletny tutorial Git i Git branch znajdziesz poniżej.
➡ ZOBACZ:
👉 Git tutorial | stash, rebase, commit, merge, checkout, push i clone
👉 Git branch | git branch create, rename, delete, checkout, merge
Git merge | git merge branch – scalanie gałęzi
Pracując na osobnych branch’ach dochodzimy do punktu, w którym chcemy złączyć nasze zmiany z resztą projektu. Wyobraź sobie pracę nad nową funkcjonalnością aplikacji. Cały kod tworzysz na specjalnie dedykowanej temu gałęzi. Jednak nie chcesz, aby twoja praca była już na zawsze wolnym elektronem. Zgadza się? Dlatego przychodzi ten ważny moment połączenia go z innym wiodącym branch’em (git merge). Nie zawsze musi być to od razu master. W zależności od potrzeb i specyfikacji projektu może to być branch o innej nazwie.
Aby zintegrować naszego branch’a z główną gałęzią musisz najpierw przejść przez następujące kroki:
1. Doprowadź przyłączaną gałąź do najaktualniejszego stanu – Git fetch
Przed scaleniem kodu z jedną z „długotrwałych” gałęzi projektu (takich jak gałąź „development” lub „master”) upewnij się, że lokalne repozytorium jest aktualne. Zarówno lokalna gałąź, jak i gałąź, do której będzie przyłączana, powinny zostać zaktualizowane o najnowsze zmiany ze zdalnego serwera. Ważne, aby to zrobić ze względu na potencjalne konflikty, które mogą powstać podczas scalania. Dzięki temu możesz ich uniknąć lub przynajmniej zmniejszyć ich liczbę. Chcąc updatować gałąź musisz skorzystać z polecenia git fetch.
Możesz upewnić się, że wszystkie branch’e są odświeżone wykonując komendę git branch -va.
W wyniku zastosowania polecenia git branch -va mogłam sprawdzić stany poszczególnych branchy zarówno lokalnych, jak i zdalnych. Przy ostatnim commicie na branch’u hotFix, możesz zauważyć dodatkową informację [ahead 1], która wskazuje na to, że gałąź ta jest o jeden commit do przodu. Commit ten nie został jeszcze wypchnięty na zdalnego branch’a. Inne oznaczenie, z jakim możesz się spotkać to [behind], które informuje o tym, że na danym branch’u brakuje zmian, znajdujących się już na zdalnym repozytorium.
2. Przełącz się na branch’a, z którym chcesz się połączyć
Chcesz przyłączyć swojego feature branch’a do gałęzi głównej master. Przełącz się zatem na gałąź master:
git checkout master.
Jeżeli chcesz się upewnić, na jakim branch’u się znajdujesz, użyj: git status.
3. Ściągnij najnowsze dane – Git pull
Czas sprawić, aby nasz lokalny master posiadał ten sam kod co zdalny. Zastosuj git pull, a stan lokalnego master’a będzie taki sam jak zdalnego.
4. Scal gałęzie – Git merge branch to master
Nadszedł moment na „główny występ”. Czas połączyć gałąź feature z master’em za pomocą:
git merge <nazwa gałęzi>.
Git merge feature
Na początek spójrzmy na branch feature. Posiada on dwie klasy TestClass oraz User.
Klasa User została stworzona na tym branch’u i na tę chwilę istnieje tylko na nim.
Poniżej mamy branch master, na którym znajduję się obecnie tylko klasa TestClass.
Spójrzmy, co się wydarzyło poniżej. Będąc na gałęzi master, ściągnęłam najnowsze dane (git pull). Ostatnim krokiem było scalenie branch’a feature do mastera (git merge feature). W efekcie czego możesz zobaczyć, że na gałęzi master pojawiła się klasa User.
Git merge conflict – konflikty w trakcie łączenia gałęzi
Powyższy scenariusz jest zdecydowanie scenariuszem pozytywnym, zakładającym bezproblemowe przejście krok po kroku aż do samego zintegrowania gałęzi. Kto nie marzy o tym, aby każde połączenie branch’y było takie proste? 🙂 Ja na pewno, ale rzeczywistość nie zawsze jest taka kolorowa i możemy podczas tego procesu napotkać konflikty.
Wyobraź sobie sytuację, w której modyfikujesz fragment kodu, który w międzyczasie został zmodyfikowany przez kogoś innego na masterze. W momencie, kiedy spróbujesz połączyć te dwie gałęzie, na których została zmieniona ta sama część pliku, Git nie będzie w stanie określić, której wersji użyć. Gdy wystąpi taka sytuacja, Git zatrzyma się tuż przed zatwierdzeniem scalania, dzięki czemu będziemy mogli ręcznie rozwiązać konflikty.
Wspaniałą częścią procesu scalania w Git jest to, że w dość przejrzysty sposób prezentuje powstałe konflikty, co ułatwia ich szybkie rozwiązanie. Gdy napotkasz konflikt podczas merge, uruchomienie polecenia git status pokaże, które pliki wymagają rozwiązania konfliktu.
Na poniższym przykładzie na branch’u feature do klasy User dodałam zmienną sex.
Jednocześnie na branch’u master w tym samym miejscu w klasie User dodałam pole email.
Polecenie git status pokazało, że ten sam plik – User, był zmodyfikowany na dwóch branch’ach (ang. both modified).
W trakcie próby przyłączenia branch’a feature do mastera Git uniemożliwia ten proces, informując nas o konflikcie.
Gdy Git napotka konflikt podczas scalania, edytuje zawartość plików, których to dotyczy, za pomocą wizualnych wskaźników, które oznaczają obie strony konfliktu.
Znaczniki, które napotkasz podczas powstania konfliktów to:
- <<<<<<<,
- =======,
- >>>>>>>.
Pomocne jest przeszukanie projektu pod kątem tych wskaźników podczas łączenia branch’y, ponieważ wskazują miejsca, w których należy rozwiązać konflikty.
Poniższy przykład pokazuje część znajdującą się na masterze oraz tę pochodzącą z branch’a feature.
Ogólnie zawartość przed znacznikiem ======= jest gałęzią odbiorczą w tym przypadku master, a część po jest gałęzią scalającą (feature).
Po zidentyfikowaniu sprzecznych fragmentów można wejść i naprawić merge według własnych upodobań. Kiedy naprawisz już wszystkie konflikty i będziesz gotowy na zakończenie przyłączenia gałęzi, wystarczy uruchomić git add na plikach, które są w konflikcie, aby poinformować Git, że zostały rozwiązane. Następnie zatwierdzasz zmiany za pomocą git commit, aby wygenerować zatwierdzenie połączenia branch’y (ang. merge commit).
Git abort merge – przerwanie scalania
Czasami możesz znaleźć się w sytuacji, w której wykonując scalenie, mogą pojawić się konflikty. Kiedy tak się stanie, możesz je rozwiązać, ale możesz też chcieć cofnąć proces mergowania. Będziesz do tego potrzebować sposobu, który przywróci główną gałąź do poprzedniego stanu. Oczywiście nie tylko konflikty mogą być powodem przerwania scalania. Możesz mieć jakikolwiek inny powód, aby anulować przyłączanie gałęzi.
Jeśli nadal byłeś w procesie scalania, możesz uruchomić git merge –abort, aby anulować scalenie – Git ładnie wszystko cofnie i skończysz w stanie, w jakim była Twoja główna gałąź przed procesem scalania.
git merge --abort
Git revert merge – cofnięcie scalania
Wyobraź sobie sytuację, w której zmiany scalone z głównym branch’em sprawiają, że aplikacja rzuca błędami i nie działa, tak jakbyśmy tego chcieli. Całe szczęście, że Git umożliwia nam wycofanie takiego przyłączenia.
W trakcie mergowania branch’y powstaje tzw. merge commit.
W przeciwieństwie do innych commit’ów – merge commit jest commit’em, który ma przynajmniej dwóch rodziców.
Na przykład, gdy gałąź feature jest mergowana z gałęzią master, nowy commit jest tworzony na gałęzi master, i ma on dwóch rodziców: poprzedniego head’a gałęzi master i head’a gałęzi feature.
Oznacza to, że oprócz naszych zmian w merge commicie znajdują się zmiany kogoś innego.
Można cofnąć zmiany zarówno nasze, jak i drugiej osoby.
Cofając zmiany, należy wskazać ścieżkę, z której zmiany mają pozostać:
- -m 1 – zostają zmiany, które druga osoba zrobiła na masterze, natomiast Twoje zmiany zostaną wycofane
git revert -m 1 2b5ed10e
- -m 2 – Twoje zmiany pozostają, a zmiany drugiej osoby zostaną wycofane
git revert -m 2 2b5ed10e
Chcąc sprawdzić hashe commit’ów „rodziców”, możesz to zrobić, wykonując komendę: git show HEAD (Można również pominąć HEAD, ponieważ jest to domyślny parametr).
git show HEAD Merge: 1c7ed20e 2d7fd11e
Od lewej jest hash commit’a m1 (ang. parent side of the merge), a następnie m2.
Git revert merge commit – cofanie commit’a ze zdalnego repozytorium
W przypadku, gdy niechciane zmiany „wysłaliśmy” (ang. git push) już na zdalne repozytorium, należy wycofać zmianę za pomocą komendy: git revert -m 1 <merge commit hash> – jak opisałam we wcześniejszym akapicie.
Następnie zmiany wypychamy na zdalne repozytorium, używając komendy: git push.
Git revert
W ramach tego materiału zajęliśmy się przede wszystkim scalaniem branch’y (git merge) oraz rozwiązywaniem powstałych konfliktów – natomiast jeżeli chcesz bliżej poznać polecenie git revert, sprawdź poniższy tutorial.
➡ ZOBACZ 👉: Git revert| git revert, revert last commit
Git merge – scalanie gałęzi – podsumowanie
W ramach tego materiału przećwiczyliśmy scalanie gałęzi oraz rozwiązywanie konfliktów powstałych podczas łączenia branch’y.
Jeżeli chcesz kontynuować swoją przygodę z gitem – to zapraszam do dodatkowych materiałów:
➡ ZOBACZ 👉: Git tutorial | stash, rebase, commit, merge, checkout, push i clone
20+ BONUSOWYCH materiałów z programowania
e-book – „8 rzeczy, które musisz wiedzieć, żeby dostać pracę jako programista”,
e-book – „Java Cheat Sheet”,
checklista – „Pytania rekrutacyjne”
i wiele, wiele wiecej!