Szerkesztő:Madbence/Git tutorial

A VIK Wikiből

Leírás

A Git egy elosztott verziókezelő rendszer, tehát SVN-nel (és társaival) ellentétben nem egy központi szerveren van meg az egész *version history*, hanem (többnyire) lokálisan is megvan az egész repository. Rengeteg git parancs van, én csak a legfontosabbakat írom le (minden platformra van GUI is hozzá, nekem ezek nem túl szimpatikusak, sokkal hatékonyabb parancssorból buzgerálni mindent)

Kezdés

Üres repó létrehozása:

$ git init

Ha nem akarunk tökölni az mkdir project; cd project; git init unalmas folyamattal:

$ git init project

Készen is vagyunk. Jöjjön a másik módszer (a gyakoribb), amikor egy létező repóhoz akarunk hozzáférni. Ezt hívjuk klónozásnak.

$ git clone https://foo.bar/baz.git

Ez a parancs az aktuális könyvtárban csinál egy baz mappát, oda pedig mindent szépen letölt. Ha nem tetszik a baz, utolsó paraméterként odabiggyeszthetjük a célkönyvtár nevét (pl .-ot, ha az aktuális könyvtárba szeretnénk létrehozni a repót)

Kultúráltak vagyunk, úgyhogy konfigoljuk be a gitet:

$ git config --global user.name "Gipsz Jakab"
$ git config --global user.email gipsz@jakab.com

Aki nem szereti a vim editort (az bizony meleg!), az beállíthajta, mivel szeretné a commitokat szerkeszteni:

$ git config --global core.editor emacs

Emacs helyett persze mást is lehet én windowson notepad++-t szoktam használni (ha panaszkodik az elérési útra windowson, akkor az idézőjelekkel kell babrálni: "'C:/npp/npp.exe' -multiInst -nosession"). De egyébként ne használjunk windowst, nagyon gáz.

Hozzáadás

Ha csinálunk egy új fájlt/mappát, az alapból nem lesz verziókezelve, ez meg is nézhetjük a status parancs segítségével:

$ touch README
$ git status
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       README
nothing added to commit but untracked files present (use "git add" to track)

A git le is lövi a poént, az add parancs fájlokat/mappákat ad hozzá a következő commithoz (akárhányat)

$ git add README

Mostmár a rendszer látja a fájlt, de még nincs benne a repóban, committolni kell.

$ git status
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#       new file:   README

Ezt a commit parancs el is végzi nekünk...

$ git commit

Nagyon fontos dolgunk van, mégpedig írni egy commit üzenetet. Fontos, hogy világos, érthető legyen, később is lehessen tudni, miért történt az a változtatás. Ha nem tetszik az alap szövegszerkesztő, akkor be tudunk állítani sajátot, vagy rögtön a parancs mellet az -m kapcsolóval meg is írhatjuk az üzenetet.

$ git commit -m "Initial commit"

Nem kell mindig egyesével hozzáadni a commithoz a fájlokat, az -a kapcsoló automatikusan minden változást bevesz (az új fájlokat még mindig nekünk kell fölvenni!) Ha nem vagyunk biztosak benne, mi kerül a commitba, a --verbose kapcsoló a commit üzenet megadásakor az egész diffet berakja (diff=előző és mostani változat közötti különbség)

Villámgyors alias: $ git config --global alias.civ "commit --interactive --verbose", ezek után a $ git civ egy kényelmes szöveges menüt ad nekünk, ahol kényelmesen összerakhatjuk a kommitot.

Elkúrás

Mi van, ha elkúrtam az üzenetet, és már commitoltam? Semmi gond, lehet szerkeszteni:

$ git commit --amend

Az -m kapcsoló használható természetesen.

Mi van, ha nem az utolsó kommit rossz? Akkor egy kicsit nehezebb dolgod van, de semmi gond: $ git rebase -i xxx ahol xxx a rossz kommit szülője. Kapunk egy editort, ahol szépen fel vannak sorolva a kommitok, ezt lehet bántani, átrendezni, kommitokat egybeolvasztani, stb. Ha kulturáltan akarunk fejleszteni (ilyen elég ritkán fordul elő sajnos), akkor mielőtt feltöltenénk a szerverre a változtatásokat, előtte tegyük rendbe a kommitokat.

Mi van, ha szar az egész commit? A reset pont jól fog jönni:

$ git reset --soft HEAD~

Kis magyarázat. A commitok jönnek szép sorban, az utolsó commit az ágon a HEAD, a ~ jel a HEAD szülője lesz (~2 nagyszülő, satöbbi)

A --soft kapcsoló pedig azt fogja csinálni, hogy csak a HEAD mutatót helyezi át. Nem fog fájlokat módosítani, nem bántja a fájlokat, amiket hozzáadtunk a commithoz (add)

Kicsit drasztikusabb változat:

$ git reset --mixed HEAD~

Ez megcsinálja ugyanazt, mint a --soft, de a commithoz hozzáadott fájlokat (hívjuk indexnek ezután, mert ez a neve) is visszaállítja a mutatott commitra. Ha nem adunk meg a resetnek semmilyen kapcsolót, akkor ezt csinálja alapból.

Még félelmetesebb a

$ git reset --hard HEAD~

Ez mindent visszaállít, ténylegesen a fájlokat is! Szóval csak óvatosan.

Fejlesztési ágak

Eddig a commitok szép sorban jöttek egymás után, viszont nagyobb projecteknél ez nem igazán jó ötlet, célszerű a fejlesztést ágakra lebontani. Erre van megoldás a gitben:

$ git branch feature

A "feature" az ág neve, amit létrehozunk. A gyökere az aktuális commit. De még nem használjuk, szóval ezt is meg kell mondani:

$ git checkout feature

Vagy a kettő egyben:

$ git checkout -b feature

Ezzel elhagyjuk az eredeti fejlesztési ágat (alapból a fő ág a "master"), és átlépünk a "feature" ágra. Itt commitolhatunk kedvünkre, satöbbi. Sőt, még további ágakat is létrehozhatunk. Ha egy kicsit elvesztünk, hogy most milyen ágon is vagyunk, akkor simán a git branch megmondja egyrészt milyen ágaink vannak, másrészt megmondja melyiken is vagyunk (csillag van a neve előtt)

Ha kész a fícsör lefejlesztése, szeretnénk visszavezetni a főágba a változásokat. Erre lesz jó a félelmetes merge:

$ git checkout master
$ git merge feature
$ git branch -d feature

Először visszaváltunk a főágra. Aztán összeolvasztjuk a két ágat. Majd töröljük a feature ágat. Sajnos irtkán ilyen szép az élet, néha a git nem tudja magától megmondani, hogy mit honnan szedjen, többen szerkesztették ugyanazt a fájlt. Ilyenkor conflict van. Ezeket manuálisan kézzel kell kijavítani, elmenteni a fájlokat, majd commitolni manuálisan (a merge ugyanis egy commit).

Ha nagy mázlink van, és a master ágon senki sem fejlesztett, amíg mi a branchon bűvészkedtünk, akkor a merge helyett fast-forward történik, a head egyszerűen előreugrik (képzeljétek el az ágakat, mint függőleges vonalak, a commitok bogyók, elég jól lehet látni, miért is lehet ezt megtenni). Szóval ennek örülünk :)

Remote

Távoli repóba is jó ha mentünk, ilyeneket tud a github vagy a bitbucket (előbbi a preferált, illetve a menő).

Ha esetleg nem klónoztuk volna a repót, hanem initet használtunk, akkor hozzá kell adni a távoli repót a remote paranccsal:

$ git remote add origin https://foo.bar/baz.git

Az add hozzáad, az origin a neve, így fogjuk hívni ezután. Tiszta sor.

Le szeretnénk kérni a repó aktuális változatát:

$ git fetch

Ha több távoli repónk is van, akkor oda lehet írni a nevét is (alapból origin-nak hívják)

Ha szeretnénk az eddigi commitokat fenyomni a szerverre:

$ git push -u origin branch

Ahol origin a remote neve, branch az ág (pl master). Ez összeköti a lokális és távoli brancheket, szóval ezek után már később elég egy sima $ git push.

Ha esetleg lesz rá időm, majd írok a githubos pull-request alapú workflow-ról, elég kúl cucc.

Hogy is volt?

Már mindent tudunk a gitről, csak azt nem, hogy hogyan is tudjuk visszanézni, mit csináltunk. Ezt többnyire a log parancs tudja szépen megmutatni:

$ git log

Kb mindent ki lehet vele deríteni, az -n kapcsoló a bejegyzések számát limitálja, a --since="2 weeks ago" az utolsó két hét commitjait mutatja, ha egy fájlnevet adunk meg a végén, akkor csak a rá vonatkozó commitok jelennek meg (ugyanez mappanév/ változattal mappára), az -S'foo()' azokat a commitokat jeleníti meg, amiben benne volt (eltűnt/megjelent) a foo(), --stat megmutatja mennyi sor változott.

Formázni is lehet, a --pretty=online pl egysoros változatban nyomja ki.

Kismillió kapcsolója van, itt meg lehet találni mindet: http://linux.die.net/man/1/git-log

A --graph grafikusan is megjeleníti a fejlesztési ágakat. Itt egy példa:

$ git log --graph --oneline --date-order
* b450119 partial
*   39d69f0 Merge branch 'exp'
|\
* \   2bf5367 Merge branch 'exp2'
|\ \
* | | ab5a665 6
| * | 369d10b fb2
| * | 6db3ec6 fb1
| | * 0d726e6 fa4
| | * 5064725 fa3
| |/
| * 542c972 fa2
| * ad88635 fa1
|/
* d14df30 5
* be70310 4
*   21bb204 Merge branch 'feature'
|\
* | b911d4f third
| * 5e6acf2 feature6
| * 577f064 feature5
|/
* 37b0e0f feature4
* 662833a feature3

Mágikus, a fentihez hasonló nagyon trendi $ git lg alias:

$ git config --global alias.lg "log --graph --date-order --all --pretty='%C(yellow)%h%Creset -%C(red)%d%Creset %s %Cgreen(a: %ar, c: %cr) %C(bold blue)<%an>%Creset'"

Utoljára maradt a blame, ami sorran lebontva jeleníti meg egy fájl utolsó szerkesztőit:

$ git blame file

Hasznos, ha tudni akarjuk ki kúrta el a fájlt :)

Bisect, stb egy kicsit ödvenszebb téma, érdemes elolvasni a git könyvet: http://git-scm.com/book

Megjegyzés

Az írás 2012 elejéről származik, azóta kicsit jobban belemélyedtem a gitbe, de szerintem a leírás még használható. lennon (vita) 2013. január 20., 02:26 (CET)

Egy kicsit kibővítettem, bár még így is elég rövid lennon(vita) 2014. február 9., 18:26 (UTC)