Ugrás a lényegre

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 07ac740] 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:

* 07ac740 (HEAD -> atnevezes) Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz
* 996698c (master) jegyzeteim ignorálása
* 36552bc Hoztunk egy hordót is
* a8a9b26 Raktam bele egy körtét
* 2a685fc 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:

Commits and parents

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.

Tree with one branch

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
drwxr-xr-x 3 blint blint 4096 Mar 20 13:02 .
drwxr-xr-x 3 blint blint 4096 Mar 19 12:39 ..
drwxr-xr-x 8 blint blint 4096 Mar 20 13:12 .git
-rw-r--r-- 1 blint blint 15 Mar 20 13:01 .gitignore
-rw-r--r-- 1 blint blint 11 Mar 20 12:58 gyumolcskosar.txt
-rw-r--r-- 1 blint blint 0 Mar 20 12:59 hordo
-rw-r--r-- 1 blint blint 0 Mar 20 13:01 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
drwxr-xr-x 3 blint blint 4096 Mar 20 13:16 .
drwxr-xr-x 3 blint blint 4096 Mar 19 12:39 ..
drwxr-xr-x 8 blint blint 4096 Mar 20 13:16 .git
-rw-r--r-- 1 blint blint 15 Mar 20 13:01 .gitignore
-rw-r--r-- 1 blint blint 11 Mar 20 13:16 gyumolcskosar
-rw-r--r-- 1 blint blint 0 Mar 20 12:59 hordo
-rw-r--r-- 1 blint blint 0 Mar 20 13:01 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 c8496bf] 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

* c8496bf (HEAD -> master) Tettem a kosaramba szőlőt
* 996698c jegyzeteim ignorálása
* 36552bc Hoztunk egy hordót is
...

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

* c8496bf (HEAD -> master) Tettem a kosaramba szőlőt
| * 07ac740 (atnevezes) Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz
|/
* 996698c jegyzeteim ignorálása
* 36552bc Hoztunk egy hordót is
* a8a9b26 Raktam bele egy körtét
* 2a685fc Készítettem egy gyümölcskosarat

Na így már látjuk a másik ágat is. Még vizuálisabban jelenleg így állunk:

Tree with one branch

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

* c040bc1 (HEAD -> atnevezes) Adtam kiterjesztést a hordónak
* 07ac740 Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz
| * c8496bf (master) Tettem a kosaramba szőlőt
|/
* 996698c jegyzeteim ignorálása
* 36552bc Hoztunk egy hordót is
* a8a9b26 Raktam bele egy körtét
* 2a685fc Készítettem egy gyümölcskosarat

Mergelés

Az egyik legfontosabb dolog az ágak létrehozása után, hogy be tudjuk 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ítanunk, teljesen jó úgy.

A merge lefut és láthatjuk mi is történt:

$ git merge atnevezes
Merge made by the 'recursive' strategy.
") Hozz\303\241adtam a txt kiterjeszt\303\251st a gy\303\274m\303\266lcskosar f\303\241jlhoz" | 248 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
gyumolcskosar => gyumolcskosar.txt | 0
hordo => hordo.txt | 0
3 files changed, 248 insertions(+)
create mode 100644 ") Hozz\303\241adtam a txt kiterjeszt\303\251st a gy\303\274m\303\266lcskosar f\303\241jlhoz"
rename gyumolcskosar => gyumolcskosar.txt (100%)
rename hordo => hordo.tx (100%)

Most egy újabb git log --graph --oneline --all-al ezt láthatjuk:

*   e4b5d9d (HEAD -> master) Merge branch 'atnevezes'
|\
| * c040bc1 (atnevezes) Adtam kiterjesztést a hordónak
| * 07ac740 Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz
* | c8496bf Tettem a kosaramba szőlőt
|/
* 996698c jegyzeteim ignorálása
* 36552bc Hoztunk egy hordót is
* a8a9b26 Raktam bele egy körtét
* 2a685fc Készítettem egy gyümölcskosarat

Ez a bizonyos merge commit egyszerre mutat a két ág tartalmára.

Merge conflict

Mi van akkor ha ketten egyszerre ugyanazt változtatjuk?
Úgy döntöttünk, hogy pálinkát szeretnénk főzni Rickel, 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 blint

Most egy újabb git branch kiadásával már látható, hogy 3 ággal rendelkezünk.

  atnevezes
* blint
master

Tegyünk bele a hordo.txt-be egy nekünk tetsző gyümölcsöt.

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 a szomszéd Rick, hogy ugyanebbe a hordóba szilvát szeretne rakni. Menjünk át a master ágra és tegyük meg ott.

Tehát:
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

* 85744ad (HEAD -> master) Raktam szilvát a hordóba
* e4b5d9d (blint) Merge branch 'atnevezes'
|\
| * c040bc1 (atnevezes) Adtam kiterjesztést a hordónak
| * 07ac740 Hozzáadtam a txt kiterjesztést a gyümölcskosar fájlhoz
* | c8496bf Tettem a kosaramba szőlőt
|/
* 996698c jegyzeteim ignorálása
* 36552bc Hoztunk egy hordót is
* a8a9b26 Raktam bele egy körtét
* 2a685fc Készítettem egy gyümölcskosarat

Na és akkor most mergeljünk be a master-re a módosításaink.

$ git merge blint
Auto-merging hordo.txt
CONFLICT (content): Merge conflict in hordo.txt
Automatic merge failed; fix conflicts and then commit the result.

Oh! Merge conflict 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, mi 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
>>>>>> blint

Mit is jelent ez? Ketté szedte az bejövő adatokat a git arra ahová mergeltünk (HEAD) és amit mergeltünk (blint). Köztük pedig egy sor "======="-t láthatunk. Itt már csak átírjuk a fájlt ahogy szeretnénk, hogy kinézzen.

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 "blint branch mergelve és konflikt megoldva"

Nézzük meg hogy néz ki a gráfunk ezután.

*   7341274 (HEAD -> master) blint
branch mergelve és konflikt megoldva
|\
| * 6d6d1ac (blint) 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.