1. Czym są gałęzie i po co są potrzebne?
Praca z branches w Git — to jeden z kluczowych aspektów kontroli wersji, który pozwala równolegle prowadzić kilka linii rozwoju w jednym repozytorium. Rozgałęzianie 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, dla bezpiecznej pracy rozwojowej. Po zakończeniu pracy jest scalana z powrotem do
main.
Wyobraź sobie, że chcesz coś poważnie przerobić w swoim projekcie albo przeprowadzić ryzykowny eksperyment. Jak byś postąpił bez Git? Najprawdopodobniej skopiowałbyś cały projekt do nowego folderu i pracował w nim. Jeśli rezultat ci się spodoba — przeniósłbyś go do folderu głównego. Jeśli nie — po prostu usunąłbyś kopię.
Gałęzie w Git działają podobnie, ale znacznie bardziej elegancko. Przyjrzyjmy się temu na przykładzie pisania książki:
- Masz gotowy maszynopis (to twoja główna gałąź
main). - Chcesz napisać alternatywne zakończenie (tworzysz nową gałąź, np.
feature/new-idea). - Piszesz nowe zakończenie, nie naruszając głównego tekstu maszynopisu (pracujesz w nowej gałęzi).
- Jeśli nowe zakończenie okaże się lepsze, zastępujesz nim stare (wykonujesz scalenie gałęzi —
merge). - Stary szkic z niepotrzebnym zakończeniem można usunąć (usuwasz gałąź).
2. Tworzenie nowej gałęzi i praca w niej
Krok 1. Otwórz menu zarządzania gałęziami.
Na górnym pasku IDE znajduje się widżet wyświetlający nazwę bieżącej gałęzi (domyślnie — main). Kliknij go i wybierz + New Branch.
Krok 2. Nazwa nowej gałęzi.
Dobrą praktyką jest nazywanie gałęzi zgodnie z zadaniem, które rozwiązujesz. Na przykład feature/add-usage-examples.
Po utworzeniu gałęzi IDE automatycznie się na nią przełączy. Zobaczysz nową nazwę w tym samym widżecie.
Krok 3. Wprowadź i zacommituj zmiany.
Teraz jesteś w swojej „piaskownicy”. Dodajmy do naszego pliku README.md nową sekcję z przykładami użycia. Wprowadź zmiany i wykonaj commit, tak 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 zobaczmy, co tam słychać.
Krok 1. Ponownie kliknij widżet z nazwą bieżącej gałęzi.
Krok 2. Na liście Local lub Recent wybierz gałąź main i w wyświetlonym podmenu kliknij Checkout.
Krok 3. Sprawdź rezultat.
Gdy tylko się przełączysz, otwórz plik README.md. Zobaczysz, że nie ma w nim sekcji z przykładami użycia! Została w innej gałęzi. Dzięki temu możesz pracować nad nową funkcjonalnością, nie naruszając stabilnej wersji w gałęzi main.
4. Scalanie gałęzi (Merge)
Polecenie merge pobiera wszystkie commity z gałęzi feature/add-examples (w tym przypadku commit C3) i łączy je z bieżącą 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
A więc zakończyłeś pracę nad swoim 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ś w tej gałęzi, DO KTÓREJ chcesz dodać zmiany. W naszym przypadku to main.
Krok 2. Wykonaj scalanie.
Ponownie kliknij widżet zarządzania gałęziami. Na liście wybierz gałąź, Z KTÓREJ chcesz pobrać zmiany (feature/add-usage-examples), a w podmenu wybierz Merge feature/add-usage-examples do main.
Krok 3. Sprawdź rezultat.
Teraz w pliku README.md w 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 podczas scalania gałęzi pojawiają się konflikty. Dzieje się tak, gdy w obu gałęziach zmieniono te same linie w tym samym pliku. Git nie może sam zdecydować, która wersja jest właściwa, i prosi o twoją pomoc.
gitGraph
commit id: "C1: Wspólna baza"
branch feature/new-title
checkout main
commit id: "C2: Zmiana w main"
checkout feature/new-title
commit id: "C3: Zmiana w feature"
main i
feature/new-title, mają nowe commity (C2 i C3), które są oparte na wspólnym przodku (C1). To gwarantuje konflikt podczas scalania.
Zasymulujmy konflikt:
- Upewnij się, że jesteś w gałęzi
maini nie masz niezapisanych zmian. - Od razu utwórz nową gałąź
feature/new-title, ale jeszcze się na nią nie przełączaj. Upewnij się, że odznaczono Checkout branch. - Teraz, będąc w gałęzi
main, zmień pierwszą linię wREADME.mdna „My Awesome Project” i wykonajcommit. - Przełącz się na gałąź
feature/new-title. Zobaczysz, że pierwsza linia wREADME.mdpozostała tutaj stara: to stan pliku w momencie tworzenia gałęzi. Zmień tę samą linię na „My Super Project” i wykonajcommit. - Wróć do gałęzi
maini wykonaj scalenie zfeature/new-title.
Teraz Git zobaczy, że obie gałęzie mają nowe, rozbieżne historie względem wspólnego przodka. W obu historiach zmieniono tę samą linię, dlatego Git nie będzie w stanie wybrać właściwej wersji i pokaże ci okno rozwiązywania konfliktu.
Merge Revision
Co tutaj widzisz:
- Po lewej (Your changes): wersja pliku z twojej bieżącej gałęzi (
main). - Po prawej (Changes from branch...): wersja pliku z gałęzi, którą scalasz.
- Pośrodku (Result): wynikowa wersja pliku, którą musisz złożyć.
Możesz klikać strzałki >> lub <<, aby przyjąć w całości jedną lub drugą wersję.
Gdy wynik w panelu środkowym będzie ci odpowiadał, kliknij Apply. IDE samo utworzy commit scalający i konflikt zostanie rozwiązany.
Dlaczego konflikt nie wystąpił?
Może się zdarzyć, że wykonałeś wszystkie kroki, a konflikt nie wystąpił. Najczęściej wynika to z tego, że Git mógł wykonać fast-forward merge, ponieważ historia jednej gałęzi po prostu kontynuowała historię drugiej. Aby konflikt był gwarantowany, historie gałęzi muszą się rozejść w różne strony od wspólnego przodka.
Przykład:
- Masz pewien commit w
main(załóżmy, C1). - Dodajesz nowy commit w
mainz tekstem „My Awesome Project”. Gałąźmainwskazuje teraz na commit C2 (main -> C1 -> C2). - Tworzysz gałąź
feature/new-titlez bieżącego położenia gałęzi main. Oznacza to, że nowa gałąź również zaczyna się od commita C2. - Wykonujesz 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 wydajesz polecenie scalenia feature/new-title.
Git patrzy na sytuację i widzi, że gałąź main jest bezpośrednim przodkiem gałęzi feature/new-title. W historii main nie było żadnych nowych commitów, gdy pracowałeś w innej gałęzi. Git myśli: „A, trzeba po prostu przewinąć main do commita C3. Nie ma żadnych sprzeczności”. 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 dzieje się w twoim projekcie, warto zaglądać do jego historii.
Otwórz zakładkę Git w dolnej części IDE i wybierz Log. Zobaczysz graficzną reprezentację wszystkich swoich gałęzi i commitów. To pomoże w prosty sposób prześledzić, która gałąź od której się odłączyła i gdzie zostały scalone.
Tutaj możesz kliknąć dowolny commit, aby zobaczyć, jakie zmiany do niego trafiły, kto i kiedy go wykonał. To prawdziwa machina czasu dla kodu!
GO TO FULL VERSION