1. Co to są gałęzie i po co one są?
Praca z branches w Git — to jeden z kluczowych aspektów zarządzania wersjami, który pozwala równolegle prowadzić kilka linii rozwoju w jednym repozytorium. Gałęzie czynią Git potężnym narzędziem do współpracy, eksperymentów i zarządzania różnymi wersjami projektu.
gitGraph
commit id: "Initial setup"
commit id: "Add base features"
branch feature/new-idea
checkout feature/new-idea
commit id: "Implement new logic"
commit id: "Refactor the logic"
checkout main
commit id: "Urgent bugfix on main"
merge feature/new-idea
commit id: "Prepare for release"
main odchodzi nowa gałąź,
feature/new-idea, do bezpiecznego developmentu. Po zakończeniu pracy jest ona scalana z powrotem do
main.
Wyobraź sobie, że chcesz poważnie przerobić swój projekt albo przeprowadzić ryzykowny eksperyment. Co byś zrobił bez Gita? Najpewniej skopiowałbyś cały projekt do nowego folderu i tam pracował. Jeśli efekt by się spodobał — przeniósłbyś go do głównego folderu. Jeśli nie — po prostu usunąłbyś kopię.
Gałęzie w Git działają na podobnej zasadzie, ale dużo elegantsze. Rozważmy to na przykładzie pisania książki:
- Masz gotowy rękopis (to twoja główna gałąź
main). - Chcesz napisać alternatywne zakończenie (tworzysz nową gałąź, na przykład
feature/new-idea). - Piszesz nowe zakończenie, nie ruszając głównego tekstu rękopisu (pracujesz w nowej gałęzi).
- Jeśli nowe zakończenie jest lepsze, zastępujesz nim stare (robisz merge —
merge). - Stary szkic z niepotrzebnym zakończeniem można usunąć (kasujesz gałąź).
2. Tworzenie nowej gałęzi i praca w niej
Krok 1. Otwórz menu zarządzania gałęziami.
Na górnym pasku IDE jest widget pokazujący nazwę aktualnej gałęzi (domyślnie — main). Kliknij go i wybierz + New Branch.
Krok 2. Nazwa nowej gałęzi.
Dobrą praktyką jest nazywać gałęzie zgodnie z zadaniem, które rozwiązujesz. Na przykład feature/add-usage-examples.
Po utworzeniu gałęzi IDE automatycznie przełączy się na nią. Zobaczysz nową nazwę w tym samym widżecie.
Krok 3. Wprowadź i zakomituj zmiany.
Teraz jesteś w swojej "piaskownicy". Dodajmy do pliku README.md nową sekcję z przykładami użycia. Wprowadź zmiany i zrób commit, jak nauczyłeś się na poprzednim wykładzie.
3. Przełączanie się między gałęziami
Twoje zmiany z przykładami użycia są teraz bezpiecznie zapisane w gałęzi feature/add-usage-examples. Wróćmy do głównej gałęzi main i sprawdźmy, co tam się dzieje.
Krok 1. Ponownie kliknij widget z nazwą aktualnej gałęzi.
Krok 2. W liście Local lub Recent wybierz gałąź main, i w pojawiającym się podmenu kliknij Checkout.
Krok 3. Sprawdź wynik.
Gdy się przełączysz, otwórz plik README.md. Zobaczysz, że sekcji z przykładami użycia tam nie ma! Została w innej gałęzi. Dzięki temu możesz pracować nad nową funkcjonalnością, nie ruszając stabilnej wersji w gałęzi main.
4. Scalanie gałęzi (Merge)
Komenda merge bierze wszystkie commity z gałęzi feature/add-examples (w tym przypadku commit C3) i łączy je z aktualną gałęzią main, tworząc nowy commit scalający.
gitGraph
commit id: "C1"
commit id: "C2"
branch feature/add-examples
checkout feature/add-examples
commit id: "C3: Add new section"
checkout main
merge feature/add-examples
Więc skończyłeś pracę nad zadaniem w gałęzi feature/add-usage-examples i chcesz dodać te zmiany do głównego projektu.
Krok 1. Przełącz się na gałąź docelową.
Upewnij się, że jesteś na tej gałęzi, DO KTÓREJ chcesz dodać zmiany. W naszym przypadku to main.
Krok 2. Wykonaj scalanie.
Ponownie kliknij widget zarządzania gałęziami. W liście wybierz gałąź, Z KTÓREJ chcesz wziąć zmiany (feature/add-usage-examples), i w podmenu wybierz Merge feature/add-usage-examples do main.
Krok 3. Sprawdź wynik.
Teraz w pliku README.md na gałęzi main pojawiła się twoja nowa sekcja z przykładami. Pomyślnie połączyłeś swoją pracę z główną wersją projektu!
5. Konflikty przy scalaniu: nie bój się, to normalne!
Czasami przy scalaniu gałęzi pojawiają się konflikty. Dzieje się tak, gdy w obu gałęziach zmieniono te same linie w tym samym pliku. Git nie potrafi sam zdecydować, która wersja jest poprawna, i prosi o twoją pomoc.
gitGraph
commit id: "C1: Common base"
branch feature/new-title
checkout main
commit id: "C2: Change in main"
checkout feature/new-title
commit id: "C3: Change in feature"
main i
feature/new-title, mają nowe commity (C2 i C3), które są oparte na wspólnym przodku (C1). To na pewno doprowadzi do konfliktu przy scalaniu.
Zasymulujmy konflikt:
- Upewnij się, że jesteś na gałęzi
maini nie masz niezapisanych zmian. - Od razu utwórz nową gałąź
feature/new-title, ale nie przełączaj się na nią jeszcze. Upewnij się, że checkbox Checkout branch jest odznaczony. - Teraz, będąc na gałęzi
main, zmień pierwszą linię wREADME.mdna "My Awesome Project" i zróbcommit. - Przełącz się na gałąź
feature/new-title. Zobaczysz, że pierwsza linia wREADME.mdpozostała stara: to stan pliku w momencie tworzenia gałęzi. Zmień tę samą linię na "My Super Project" i zróbcommit. - Wróć do gałęzi
maini wykonaj scalanie zfeature/new-title.
Teraz Git zobaczy, że obie gałęzie mają nowe, rozchodzące się historie od ich wspólnego przodka. W obu historiach zmieniono tę samą linię, więc Git nie będzie mógł wybrać, która wersja jest poprawna, i pokaże okno do rozwiązania konfliktu.
Merge Revision
Co tu widzisz:
- Po lewej (Your changes): wersja pliku z twojej aktualnej gałęzi (
main). - Po prawej (Changes from branch...): wersja pliku z gałęzi, którą scalasz.
- Po środku (Result): finalna wersja pliku, którą musisz złożyć.
Możesz klikać strzałki >> lub <<, żeby przyjąć w całości jedną z wersji.
Kiedy wynik w środkowym panelu ci odpowiada, kliknij Apply. IDE samo stworzy commit scalający i konflikt zostanie rozwiązany.
Dlaczego nie pojawił się konflikt?
Może zdarzyć się sytuacja, że wykonałeś wszystkie kroki, a konfliktu nie było. Najczęściej dlatego, że Git był w stanie wykonać fast-forward merge, bo historia jednej gałęzi po prostu kontynuowała historię drugiej. Aby konflikt był gwarantowany, historie gałęzi muszą rozjechać się w różne strony od wspólnego przodka.
Przykład:
- Masz jakiś commit w
main(powiedzmy C1). - Robisz nowy commit w
mainz tekstem "My Awesome Project". Gałąźmainteraz wskazuje na commit C2 (main -> C1 -> C2). - Tworzysz gałąź
feature/new-titlez aktualnego stanu main. To znaczy, że nowa gałąź też zaczyna się od commita C2. - Robisz commit w
feature/new-titlez tekstem "My Super Project". Ta gałąź "idzie do przodu" i teraz wskazuje na commit C3 (feature/new-title -> C1 -> C2 -> C3). - Wracasz do
main(która wciąż jest na commicie C2) i dajesz komendę scalenia feature/new-title.
Git patrzy i widzi, że gałąź main jest bezpośrednim przodkiem gałęzi feature/new-title. W historii main nie było żadnych nowych commitów, dopóki pracowałeś w innej gałęzi. Git myśli: "A, tu wystarczy przewinąć main do przodu do commita C3. Nie ma konfliktów". I po prostu przesuwa wskaźnik main na commit C3.
gitGraph
commit id: "C1"
commit id: "C2"
branch feature/new-title
checkout feature/new-title
commit id: "C3"
checkout main
merge feature/new-title
6. Przegląd historii zmian
Aby lepiej rozumieć, co się dzieje w twoim projekcie, warto patrzeć na jego historię.
Otwórz zakładkę Git w dolnej części IDE i wybierz Log. Zobaczysz graficzne przedstawienie wszystkich gałęzi i commitów. To pomoże wizualnie śledzić, która gałąź od której odgałęziła się i gdzie zostały scalone.
Tu możesz kliknąć dowolny commit, żeby zobaczyć, jakie zmiany w nim weszły, kto i kiedy go zrobił. To prawdziwa maszyna czasu dla kodu!
GO TO FULL VERSION