# Branch-ek, elágazás #### Mik azok a branch-ek? Talán legegyszerűbb, ha előbb készítünk egyet. Az előző témakörben átneveztünk egy fájlt, de nem commitoltuk el. Ezt ne tegyük meg, hanem készítsünk egy ágat onnan, ahol jártunk mondjuk azzal a névvel, hogy `atnevezes`. Először nézzük meg, mi a helyzet jelenleg a `git status` paranccsal. ``` $ git status On branch master Changes to be committed: (use "git restore --staged <file>..." to unstage) renamed: gyumolcskosar -> gyumolcskosar.txt ``` Látható, hogy a `master` nevű ágon vagyunk. Ezt képzeljük el úgy, mint egy fa törzse, melyből le ágazunk. Nézzük meg jelenleg milyen branch-ek vannak a repo-nkban a `git branch` paranccsal. ``` $ git branch * master ``` Látható, hogy még csak egy van. Ha a `git branch <új branch neve>` parancsot kiadjuk, akkor készül egy új ág, de arra figyeljünk, hogy ilyenkor még nem megyünk át rá. Nézzük is meg, hogy tényleg elkészült a `git branch` paranccsal. ``` $ git branch atnevezes * master ``` Itt a `*` azt jelöli, hogy melyiken vagyunk jelenleg. Ha kiadnánk a `git status` parancsot, akkor is láthatnánk melyik ágon vagyunk. Gyerünk át az új ágra. Ehhez a `git checkout <ág neve>` parancsot tudjuk használni. ``` $ git checkout atnevezes D gyumolcskosar A gyumolcskosar.txt Switched to branch 'atnevezes' ``` Itt azt is látjuk azonnal, hogy a módosításainkkal nem történt semmi. Ezek jelenleg még `staged`-be vannak és ha elmentjük őket a commital, akkor az épp jelenlegi ágra fogja beilleszteni őket. Nézzük meg `git status`-al, hogy mi a helyzet. ``` $ git status On branch atnevezes Changes to be committed: (use "git restore --staged <file>..." to unstage) renamed: gyumolcskosar -> gyumolcskosar.txt ``` Látszik is, hogy az `atnevezes` ágon vagyunk. Mentsük el ide a módosításaink `Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz` üzenettel ``` $ git commit -m "Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz" [atnevezes 7de1c94] Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz 1 file changed, 0 insertions(+), 0 deletions(-) rename gyumolcskosar => gyumolcskosar.txt (100%) ``` Ezt követően ha kiadjuk a `git log --graph --oneline` parancsot, akkor meg is láthatjuk a jelenlegi helyzetet a mi fánkban: ``` * 7de1c94 (HEAD -> atnevezes) Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz * 80560db (master) jegyzeteim ignorálása * 30bf35d Hoztunk egy hordót * b677a86 Raktam bele egy körtét * c45abc3 Készítettem egy gyümölcskosarat ``` #### Hogy épül fel? Először is, ahhoz hogy tudja a git melyik mentéspont után melyik jön, mutatókat használ ehhez az ábrához hasonló módon: <div style="text-align:center"><img src="workshop/img/commits-and-parents.png" alt="Commits and parents" /></div> A mentéspontjaink az előzőre mutatnak. Ahogy láthattuk az előző fejezetben, a mentéspontok pedig mutatnak a megfelelő fájlokra amiket épp módosítottunk. Vizsgáljuk meg a jelenlegi repo-nkat, hogy pontosan mi merre is van. <div style="text-align:center"><img src="workshop/img/tree_with_one_branch.png" alt="Tree with one branch" /></div> A mentéspontok képesek mutatni az előzőre, ezt láthatjuk az ábrán. Továbbá azt is látjuk, hogy van még 3 pointerünk. Az egyik `master`, ez az ami a legfrissebb mentésre mutat a master ágon. Ugyanez igaz az `atnevezes` ág esetében, de oda még mutat egy `HEAD` mutató is. Ez az a mutató ami azt jelzi, hogy hol vagyunk mi jelenleg. Mikor egy új mentést hozunk létre, akkor az a mentés ide fog mutatni. Ezért is kellett figyelni az előzőnél, hogy mentés előtt átváltsunk a megfelelő ágra. #### Ágak közti mozgás Még mielőtt vissza mennénk a master-re, nézzük meg milyen fájljaink vannak az `ls -al` -el. ``` $ ls -al total 20 drwxrwxr-x 3 rlacko rlacko 4096 okt 8 21:07 . drwxrwxr-x 12 rlacko rlacko 4096 okt 8 16:49 .. drwxrwxr-x 8 rlacko rlacko 4096 okt 9 15:01 .git -rw-rw-r-- 1 rlacko rlacko 15 okt 8 20:43 .gitignore -rw-rw-r-- 1 rlacko rlacko 11 okt 8 17:29 gyumolcskosar.txt -rw-rw-r-- 1 rlacko rlacko 0 okt 8 20:09 hordo -rw-rw-r-- 1 rlacko rlacko 0 okt 8 20:42 jegyzeteim.txt ``` Egy pár extra adatot is kapunk, de nekünk most a `gyumolcskosar.txt` a lényeges. Most gyerünk vissza a `master` ágra a `git checkout <ág neve>` paranccsal. ``` $ git checkout master Switched to branch 'master' ``` Most adjuk ismét ki az `ls -al` parancsot. ``` $ ls -al total 20 drwxrwxr-x 3 rlacko rlacko 4096 okt 9 15:24 . drwxrwxr-x 12 rlacko rlacko 4096 okt 8 16:49 .. drwxrwxr-x 8 rlacko rlacko 4096 okt 9 15:24 .git -rw-rw-r-- 1 rlacko rlacko 15 okt 8 20:43 .gitignore -rw-rw-r-- 1 rlacko rlacko 11 okt 9 15:24 gyumolcskosar -rw-rw-r-- 1 rlacko rlacko 0 okt 8 20:09 hordo -rw-rw-r-- 1 rlacko rlacko 0 okt 8 20:42 jegyzeteim.txt ``` Látható, hogy vissza léptünk arra az állapotra mikor még nem változtattunk rajta. Ez elképesztően jó, ugyanis két teljesen külön álló munkát így elkülönítöttünk egymástól! Írjuk a `gyumolcskosar` fájl végére, hogy `szolo` és mentsük el azzal az üzenettel, hogy `Tettem a kosaramba szőlőt`. ``` $ git commit -m "Tettem a kosaramba szőlőt" [master 932cbeb] Tettem a kosaramba szőlőt 1 file changed, 1 insertion(+) ``` Most újra kiadva a `git log --graph --oneline` parancsot, már érdekesebb eredményt láthatunk. ``` $ git log --graph --oneline * 15719cf (HEAD -> master) Tettem a kosaramba szőlőt * 80560db jegyzeteim ignorálása * 30bf35d Hoztunk egy hordót ... ``` Mégis hova tünt a másik águnk? A git nem fogja alapból jelezni nekünk azt amit nem lát a jelenlegi mentéstől vissza menve. Hogy lássuk a másik ágat is, tegyük hozzá a `--all` kapcsolót. ``` $ git log --graph --oneline --all * 15719cf (HEAD -> master) Tettem a kosaramba szőlőt | * 7de1c94 (atnevezes) Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz |/ * 80560db jegyzeteim ignorálása * 30bf35d Hoztunk egy hordót ... ``` Na így már látjuk a másik ágat is. Még vizuálisabban jelenleg így állunk: <div style="text-align:center"><img src="workshop/img/tree_awesome.png" alt="Tree with one branch" /></div> Menjünk vissza az `atnevezes` ágra és módosítsunk picit. ``` $ git checkout atnevezes ``` Majd pedig nevezzük át a `hordo`-t `hordo.txt`-re. ``` $ mv hordo hordo.txt ``` És ezt is mentsük el ``` $ git add . $ git commit -m "Adtam kiterjesztést a hordónak" ``` Egy ismételt `git log`-al láthatjuk is a fánkat. ``` $ git log --graph --oneline --all * 9dcfc79 (HEAD -> atnevezes) Adtam kiterjesztést a hordónak * 7de1c94 Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz | * 15719cf (master) Tettem a kosaramba szőlőt |/ * 80560db jegyzeteim ignorálása ``` #### Mergelés Az egyik legfontosabb dolog az ágak létrehozása után, hogy betudjuk olvasztani az águnk valahova. Az lenne a feladat, hogy a `master`-re beillesszük az `atnevezes` ágon végzett módosításaink. Ehhez a `git merge <branch neve>` parancsot használhatjuk. A lényege, hogy ez a parancs azt az ágat amit kiválasztottunk megpróbálja beolvasztani oda ahol épp a `HEAD` mutatónk van. Gyerünk is át a `master` ágra. ``` $ git checkout master Switched to branch 'master' ``` Ezután pedig mergeljük át a `master`-re az `atnevezes` ágat. ``` git merge atnevezes ``` Ekkor meg fog nyílni a szövegszerkesztőnk, ugyanis egy új mentéspontot fogunk készíteni a `master águnkra`. A feladott merge üzeneten nem kell módosítanünk, teljesen jó úgy. A merge lefut és láthatjuk mi is történt: ``` $ git merge atnevezes Removing hordo Merge made by the 'recursive' strategy. gyumolcskosar => gyumolcskosar.txt | 0 hordo => hordo.txt | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename gyumolcskosar => gyumolcskosar.txt (100%) rename hordo => hordo.txt (100%) ``` Most egy újabb `git log`-al ezt láthatjuk: ``` * 366140d (HEAD -> master) Merge branch 'atnevezes' |\ | * 9dcfc79 (atnevezes) Adtam kiterjesztést a hordónak | * 7de1c94 Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz * | 15719cf Tettem a kosaramba szőlőt |/ * 80560db jegyzeteim ignorálása * 30bf35d Hoztunk egy hordót ``` Ez a bizonyos `merge commit` egyszerre mutat a két ág tartalmára. #### Merge conlict Mi van akkor ha ketten egyszerre ugyanazt változtatjuk? Úgy döntöttünk, hogy pálinkát szeretnénk főzni józsival, szóval a hordóba teszünk ízlés szerint valami gyümölcsöt. Gyerünk át a saját águnkra, de egy paranccsal. Ezt a `-b` kapcsolóval tudjuk elérni a `git checkout` mellett. ``` $ git checkout -b lacko ``` Most egy újabb `git branch` kiadásával már látható, hogy 3 ággal rendelkezünk. ``` atnevezes * lacko master ``` Tegyünk bele a `hordo.txt`-be egy nekünk tetsző gyümölcsöt. ```gyumolcs.txt korte ``` Ezt mentsük is el, de most picit csaljunk és ne rakjuk `staged`-be, hanem azonnal mentsük el `-a` kapcsolót használva. ``` $ git commit -a -m "Raktam a hordóba körtét" ``` Úgy döntöttünk a szomszéd Józsi, hogy ugyanebbe a hordóba körtét szeretne rakni. Menjünk át a master ágra és tegyük meg ott. Azt mondta a szomszéd, hogy szilvát szeretne beletenni, szóval: ```hordo.txt szilva ``` Ezt is mentsük el. ``` $ git commit -a -m "Raktam szilvát a hordóba" ``` Most ha megnézzük a gráfunkat újra, akkor láthatjuk is, hogy mi a helyzet: ``` $ git log --graph --oneline --all * 41f1c05 (HEAD -> master) Raktam szilvát a hordóba | * 6d6d1ac (lacko) Raktam a hordóba körtét |/ * 366140d Merge branch 'atnevezes' |\ | * 9dcfc79 (atnevezes) Adtam kiterjesztést a hordónak | * 7de1c94 Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz * | 15719cf Tettem a kosaramba szőlőt |/ * 80560db jegyzeteim ignorálása * 30bf35d Hoztunk egy hordót ... ``` Na és akkor most mergeljünk be a master-re a módosításaink. ``` $ git merge lacko Auto-merging hordo.txt CONFLICT (content): Merge conflict in hordo.txt Automatic merge failed; fix conflicts and then commit the result. ``` Oh! Merge conlict keletkezett. Nem kell megijedni, nem a világ vége és a git segít ahol tud. Az a helyzet, hogy egyszerre ugyanazt a sort módosítottuk és a git nem tudta eldönteni mit tegyen. Megtartsa az egyiket vagy mindkettőt? Mégis mi legyen? Ezeket a kérdéseket nekünk kell megválaszolnunk. Először nézzük meg, mit a státusz. ``` $ git status On branch master You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add <file>..." to mark resolution) both modified: hordo.txt no changes added to commit (use "git add" and/or "git commit -a") ``` Az van, hogy ilyenkor a git beírja a fájlunkba mind a két branch változásait és utána azt várja tőlünk, hogy átalakítsuk a fájlt, majd pedig azt elmentsük. Szóval nem kell megijedni, csak átírjuk mi kell nekünk és mentünk egyet. Nézzük meg mi van a fájlunkban. ```hordo.txt <<<<<<< HEAD szilva ======= korte >>>>>> lacko ``` Mit is jelent ez? Ketté szedte az bejövő adatokat a git arra ahová mergeltünk (`HEAD`) és amit mergeltünk (`lacko`). Köztük pedig egy sor "======="-t láthatunk. Itt már csak átírjuk a fájlt ahogy szeretnénk, hogy kinézzen. ```hordo.txt korte ``` Nézzük meg mi a státusz ezután: ``` git status On branch master You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add <file>..." to mark resolution) both modified: hordo.txt no changes added to commit (use "git add" and/or "git commit -a") ``` Továbbra is azt írja, amit az imént. Amíg nem commitoljuk a módosításunk, addig ezt is fogja. Hát akkor mentsünk. ``` git commit -a -m "lacko branch mergelve és konflikt megoldva" ``` Nézzük meg hogy néz ki a gráfunk ezután. ``` * 7341274 (HEAD -> master) lacko branch mergelve és konflikt megoldva |\ | * 6d6d1ac (lacko) Raktam a hordóba körtét * | 41f1c05 Raktam szilvát a hordóba |/ * 366140d Merge branch 'atnevezes' ... ``` Tehát most a merge commitunk egyben a konfliktusok megoldását is tartalmazza. Nem elképesztő? Innentől már csak együtt kell dolgozni, margeknél a konfliktusokat megoldani. Semmi extra effortot nem fog igényelni egy hasonló elvégzése. [Előző](workshop/2_basics?id=alapok) | [Következő](remote/1_basics?id=alapok-és-ssh-kulcs)