[[oktatas:programozás:verziókontroll:git|< Git]] ====== A Git használata ====== * **Szerző:** Sallai András * Copyright (c) 2014, Sallai András * Szerkesztve: 2014, 2015, 2016, 2019, 2020, 2022, 2023 * Licenc: [[https://creativecommons.org/licenses/by-sa/4.0/|CC BY-SA 4.0]] * Web: https://szit.hu ===== Bevezetés ===== ==== A Gitről ==== A Git egy elosztott verziókövető rendszer. Angolul **Decentralized Version Control System**, röviden **DVCS**, de **Distributed Version Control System** rövidítésének is tartják. Ez azt jelenti, hogy a felhasználó nem csak az aktuális verziót tartja a gépén, hanem az egész tároló (repository) tartalmát, ellentétben a központosított rendszerekkel. Ennek az az előnye, hogy hálózat nélkül is tudunk dolgozni (offline). Az SVN és más hasonló verziókövető rendszerek központosított verziókövető rendszerek. Angolul **Centralized Version Control Systems**, röviden **CVCS**. A CVCS alapú rendszerek a commitokat a rendszerbekerüléshez viszonyítják. A Git esetén ez nem így működik. A Git pillanatnyi állapotokat (snapshot) tárol. A Gitet eredetileg a **Linux projekt** számára hozta létre **Linus Torvalds**. Alkalmas nagy projektek használatára. A Gittel parancssorban dolgozunk, de rendelkezésre áll néhány grafikus felületű program is. A git és a gtihub használatáról Linux alatt a [[oktatas:linux:programozas#git|következő helyen találunk leírást]]. A git szerver telepítéséről pedig [[oktatas:linux:git_szerver|itt]]. ==== Összehasonlítás más verziókövetőkkel ==== A Git rendszer eltér más verziókövető rendszerek működésétől, mint amilyen a Subversion vagy a Perforce. A legfőbb különbség a Git és más verziókövető rendszerek között az adatok kezelésében van. Más verziókövető rendszerek minden állományról készítenek egy mentést. A Git ezzel szemben, ha egy állomány nem változott, akkor azt nem tárolja el. Csak egy **mutatót** hoz létre az **előző verzióra**. {{:oktatas:programozas:verziokontroll:git_tarolas_verzionkent.png|}} Vannak rendszerek, amelyek az állományok egy részéről készítenek csak másolatot. A Git csak a változtatott állományról, de az adott állomány egész részéről. ===== Telepítés ===== Debian alapú Linuxon: apt-get install git Windowsra innen lehet letölteni: * https://git-scm.com/download/win * https://gitforwindows.org/ Grafikus kliens: apt-get install git-cola vagy: * http://git-cola.github.io/ vagy ncurses alapú kliens Linuxra: apt-get install tig Szervertelepítés Linuxra az [[oktatas:linux:git_szerver|oktatás:linux:git szerver]] lapon. Telepítés Windowsra [[oktatas:operációs_rendszerek:windows:git|Git Windowsra lapon olvasható]]. Commit nézegető: apt install gitk Windowson a Git telepítésével a gitk alapértelmezetten felkerül. ===== Működés ===== ==== Helyi működés ==== A gitben, amikor fájlokon és más erőforrásokon dolgozunk, minden helyben történik, **nincs** szükség **hálózati kapcsolatra**. Így a munkánk gyors és offline lehet. A munkánkat bármikor szinkronizálhatjuk egy központi tárolóval. ==== Fogalmak ==== === Commit === A commit, a fájlokról elmentett pillanatkép. Érdemes úgy megválasztani a commitjainkat, hogy az logikailag összetartozó egységeket együtt commitoljuk. A git rendszerben commit alparanccsal használjuk. A commit a legelemibb tárolandó egység. Érdemes minél sűrűbben commitolni. === Branch === Fejlesztés egy ága. Amikor készítünk egy projektet és azt a Git-be helyezzük, lesz egy fő (master) branch-ünk. Ebből újabb branch-eket hozhatunk létre. A háttérben egy branch létrehozása egy mutató az utolsó állapotra. Egy branch tulajdonképpen commitok összessége. === Clone === Távoli gépről másolatot készíthetünk egy branch-ről. === Checkout === A branchek közötti váltásra használható. === Push === Ha kiadok egy commit parancsot, akkor az csak helyben történik -- nem úgy mint az SVN-ben. A központi szerverrel való szinkronizáláshoz szükségünk van a Push műveletre a push paranccsal. === Head === Egy mutató, ami a munkánk során az aktuális branch-re mutat. A HEAD mutatja hol, milyen ágon dolgozunk. === Munkakönyvtár === A munkakönyvtár az a könyvtár, amelyben létrehozzuk a forrásállományainkat, és ahol dolgozunk rajtuk. Ez tulajdonképpen a projekt könyvtára. === Stage === A stage egy átmeneti hely. Azokat az állományokat, amelyeket most hoztunk létre vagy módosítottuk a stage helyre kell tenni, ha szeretnénk követett állapotba tenni. === Repository === Tároló, ahol a fájlok tárolásra kerülnek. A helyi gépen a tároló valójában a .git könyvtárban van. A távolig szerveren, egy .git kiterjesztésű könyvtár a szokásos tárolási hely. === Helyi tároló === A helyi tároló a munkakönyvtár, a stage hely és a repository helyek együttese. {{:oktatas:programozás:verziókontroll:git_helyi_tarolo.png?300|}} {{:oktatas:programozás:verziókontroll:git_tavoli_tarolo.png?100|}} === upstream === A távoli tároló, ahova mindenki feltölt. === downstream === A helyi tároló ahol dolgozol. ==== Kliens-szerver felépítés ==== A git szerver-kliens alapú, de használható szerver nélkül is, mivel kliens oldalon is tárolódik az összes állomány. Alapvetően egy helyi tárolóban dolgozunk, a szerverre egy push művelettel töltjük fel az adatainkat. {{:oktatas:programozás:verziókontroll:gitkliensszerver.png?300|}} A letöltés, clone, pull és fecth műveletekkel lehetséges. ==== Fájlok állapota ==== A fájlok a munkakönyvtárunkban alapvetően két állapota lehet: * untracked - nem követett * tracked - követett * modified - módosult a commit óta * unmodified - a commit óta nem módosult * staged - a legközelebbi commit esetén tárolásra kerül ==== Pillanatképek ==== A git segítségével a munkánkról pillanatfelvételeket készítünk. Minden felvétel kap egy azonosítót. {{:oktatas:programozas:verziokontroll:pillanatkepek.png|}} Amikor elindítjuk a fejlesztések pillanatfelvételeit egy úgynevezett master ágat, vagy angolosan branch-et hozunk létre. Később más ágakat is fogunk használni, és mindig a HEAD mondja meg éppen melyik ággal dolgozunk. Minden pillanatkép tartalmaz egy mutatót az előző pillanatképre. ===== Kezdő lépések ===== ==== Bemutatkozás a Git számára ==== A git számára meg kell adni egy teljes nevet, és egy e-mail címet. Ez a név és cím fog megjelenni, minden commitban. git config --global user.name "Keresztnév Vezetéknév" git config --global user.email "joska@zold.and" Ezek az adatok a ~/.gitconfig nevű fájlban kerülnek tárolásra, vagyis az adott felhasználónak globális lesz, vagyis minden projekthez ezt fogja használni. Állítsuk be a kedvenc szövegszerkesztőnket. Linuxon, például ha telepítve van az mc: git config --global core.editor mcedit Windowson: git config --global core.editor notepad Sortörések automatikus cseréjének kikapcsolása: git config --global core.autocrlf false Állítsuk be színes kiíratás is: git config --global color.ui true A felhasználónév lekérdezés: git config user.name E-mail cím ekérdezés: git config user.email Az összes beállítás lekérdezése: git config --list A lehetséges kimenete: user.email=joska@zold.and user.name=Nagy Jozsef giggle.main-window-maximized=false giggle.main-window-geometry=700x550+1192+459 giggle.main-window-view=FileView push.default=simple core.repositoryformatversion=0 core.filemode=true core.bare=false core.logallrefupdates=true remote.origin.url=https://github.com/joska/myprojekt remote.origin.fetch=+refs/heads/*:refs/remotes/origin/* branch.master.remote=origin branch.master.merge=refs/heads/master Kérdezzük le, hol tárolja a git ezeket az adatokat: git config --list --show-origin ===== Helyi munka ===== ==== Új projekt ==== mkdir TesztProjekt cd TesztProjekt git init A **//git init//** parancs létrehoz a TesztProjekt könyvtárban egy **//.git//** könyvtárat. Ez tulajdonképpen egy helyi adatbázis, ami eltárolja a projektünk verzióit, és minden azzal kapcsolatos információt. Azt is mondhatjuk, hogy a projektünk, most már a Git része. ==== Használat ==== Kérdezzük le a fájlok státuszát: git status Most hozzunk létre egy állományt: touch readme.txt Kérdezzük le újból a státuszt: git status A git add paranccsal a stage helyre tesszük a fájlokat, majd a commit paranccsal elkészítjük a pillanatképet. {{:oktatas:programozas:verziokontroll:git_munka_szines_03.png|}} A stage, inkább csak egy állapot. Tegyük követett állapotba a readme.txt fájlt: git add readme.txt Innentől kezdve commit esetén ez az állomány is tárolásra kerül. Most nézzük meg újra a státuszt: git status # On branch master # # Initial commit # # Changes to be committed: # (use "git rm --cached ..." to unstage) # # new file: readme.txt # A Changes to bi commited után felsorolt állományok staged állapotban vannak. Változtassuk meg a readme.txt állományt: echo "egy" > readme.txt Ellenőrizzük a státuszt: git status # On branch master # # Initial commit # # Changes to be committed: # (use "git rm --cached ..." to unstage) # # new file: readme.txt # # Changes not staged for commit: # (use "git add ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # modified: readme.txt # Adjuk hozzá újra readme.txt fájlt: git add readme.txt Nézzük meg a státuszt: git status # On branch master # # Initial commit # # Changes to be committed: # (use "git rm --cached ..." to unstage) # # new file: readme.txt # Fűzzünk megint valamit readme.txt fájlhoz: echo "ketto" >> readme.txt Nézzük meg a változásokat a diff paranccsal: git diff A diff parancs csak akkor fog látni egy állományt ha az nincs staged állapotba. Ha a staged állapotú állományokat is szeretnéd látni: git diff --cached ==== Commit ==== A staged állapotú állományok tárolásra kerülnek. git commit A git megnyitja egy szövegszerkesztőt a megjegyzés leírásához. A szövegszerkesztő beállítása: git config --global core.editor mcedit Persze mi magunk is megadhatjuk a parancssorban a megjegyzéseket: get commit -m "Egy és kettő hozzáadása" {{oktatas:programozás:szoftverfejlesztés:verziókontroll:githelyioperaciok.png?300|}} Az utolsó commit módosítása: git commit --amend Ha szeretnénk a commit tulajdonosát és/vagy e-mail címét megváltoztatni: git commit --amend --author="Vezetéknév Keresztnév " Ügyeljünk arra, hogy a beállított szövegszerkesztővel meg fog nyílni, a commit szövege. Az alapértelmezett szövegszerkesztő pedig Windowson is a **vim**. Állítsuk be a jegyzettömböt, ha nem megy a vim használata. Ha megnyílt a commit és azt nem akarjuk szerkeszteni (csak a nevet és az e-mail címet akartuk változtatni), akkor csak simán lépjünk ki belőle. Kilépés vimből mentés nélkül: :q! A név és az e-mail cím megváltozik. Tegyük fel, hogy korábbi commitot szeretnénk változtatni. A következő commitok vannak: * egy * ketto * harom * negy * ot * hat A HEAD a "hat" commitra mutat, mi pedig szeretnénk megváltoztatni a "harom" és a "negy" commitot. A következőket tegyük: Adjuk meg, hogy a "ketto" után szeretnénk javítani: git rebase -i ketto A megadott szövegszerkesztőben a commitokat látjuk felsorolva. Jelöljük meg az "harom" és a "negy" commitokat szerkesztésre az "edit" szóval. Mentsünk, lépjünk ki a szerkesztőből. Végezzük el a változtatást: git commit --amend --author="Vezetéknév Keresztnév " Lépjünk tovább: git rebase --continue Most a "negy" commitnál vagyunk. Végezzük el a változtatásokat: git commit --amend --author="Vezetéknév Keresztnév " git rebase --continue Elkészült. A commit paranccsal a helyi tárolóba kerültek a fájlok. Nézzük meg mik vannak tárolva: git ls-files Esetleg: git ls-tree --full-tree -r HEAD A státusz rövidítése: git status -s Automatikus stage állapotba: git commit -a -m 'Valami' git commit --all --message 'Valami' Próba: git commit --dry-run ==== Napló ==== git log A commit-ok adatait tekinthetjük meg. A git-log ha lapozóprogramot használ, a futás után nem adja vissza a várakozási jelet. Lebeszélhetjük a lapozó program használatáról a --no-pager: git --no-pager log Még több kapcsoló: git log --abbrev-commit git log --oneline git log --no-notes git log --pretty="format:%h %s %d" A kimenet hasonló lehet: 5345711 Első sor beírva (HEAD, master) d78adf3 Kezdés Kimenet díszítve, ágak mutatása: git log --oneline --decorate --graph --all Az adott ágból elhagyott commitok is jelenjenek meg: git log --reflog ==== Hivatkozásnapló ==== Ha elhagytunk egy commitot, például egy hard reset miatt, az nem veszett el. Ha tudjuk a commit azonosítóját (vagy az első négy számot), vissza tudunk állni rá. A commit azonosítója kideríthető az előző fejezetben látott, --reflog kapcsolóval, vagy: git reflog show Lehetséges kimenet: b634470 (HEAD -> master) HEAD@{0}: reset: moving to b634 024a96d HEAD@{1}: reset: moving to 024a b634470 (HEAD -> master) HEAD@{2}: reset: moving to b634 024a96d HEAD@{3}: commit: Szilva hozzáadása b634470 (HEAD -> master) HEAD@{4}: commit: Körte hozzáadása a029c66 HEAD@{5}: commit (initial): Init ==== Fájlok törlése ==== git rm readme.txt Ezzel a paranccsal töröljük fizikailag az állományt, töröljük a stage-ről és a tracedek közül. Ha nem szeretnénk törölni a stage-ről és a tracedek közül, akkor használjuk a --cached kapcsolót. git rm --cached readme.txt Utolsó két commit: git log -2 Commit-ok közötti különbségek: git log -p Utolsó változtatás: git log -p -1 ==== Fájlok, könyvtárak átnevezése ==== Úgy szeretnénk átnevezni, hogy az verziókezelve legyen. Az mv parancsot nem szükséges önmagában használni, a git mv parancs megoldja a fizikai átnevezést is. A git rm után csak egy commit szükséges: git mv eredetiNev ujNev git commit -m "Átnevezve" ==== Fájlok kizárása a Gitből ==== Néhány állományt szeretnénk majd kizárni a Git tárolónkból. Ez úgy tehetjük meg, ha felvesszük a következő állományba: .gitignore Ezek nem jelölhetők meg untraced állapotúként és nem lehetnek commitólni sem. Példa: *.class # Csomagfájlok # *.jar *.war *.ear *.old Linux alatt több információ: man gitignore A .gitignore állományt adjuk hozzá a tárolóhoz. git add .gitignore ==== Módosítás különbségei ==== Nézzük meg az utolsó és az utolsó előtti commit különbségét. Commit után már csak a commitok azonosítójának megadásával tudjuk megtenni. git log -2 git diff 2343..3432 Ha még nem volt commit, akkor elég a git diff: git add fajlnev.txt git diff Ha csak egy behúzás volt a módosítása, de soron belül egyébként semmi nem változott, akkor is változásnak fogja fel: -eredeti sor + eredeti sor A -w kapcsolóval, kizárhatjuk a whitespace karakterek figyelését: git diff -w 2343..3432 Két külön ág közötti különbség: git diff master..devel-1 ==== Ki változtatott ==== Lekérdezhetjük, az adott fájlban adott sort ki változtatta meg. Ezt a blame alparanccsal tehetjük meg. git blame readme.txt Néhány kapcsoló: git blame -w # whitespace elutasítása git blame -M # szöveg mozgatás elutasítása git blame -C # szöveg mozgatása másik fájlba elutasítva ==== Visszaállítás ==== {{:oktatas:programozas:verziokontroll:visszaallas.png|}} Unstaged local changes (before you commit) Nézzük, hogyan tudunk visszaállni az utolsó commit állapotába. Még commit előtt vagyunk és a fájlok még nincsennek a staged állapotban. Kérdezzünk le egy státuszt: git status Így láthatjuk milyen fájlokról lehet szó, pontos útvonallal. Egy fájl visszaállítása: git checkout -- Az összes változtatás visszaállítása (még nem volt git add): git reset --hard Az összes változás visszaállítása, a jelenlegi mentésével, későbbi felhasználás esetére. git stash Ha már volt git add, vagyis staged helyen van, akkor a visszavonás: git reset --hard HEAD Az **összes verzió** mutatása, ami már nem szerepel commitként, azt is: git log --reflog Visszaállás egy végleges mentésre: git checkout aa761 Vagy: git reset --hard aa761 Ezt megtehetjük ha már változtattunk, de megtehetjük, ha éppen egy commit után vagyunk. {{:oktatas:programozas:verziokontroll:git:visszaallas_adott_verziora.png?400|}} {{:oktatas:programozas:verziokontroll:git:visszaallas_adott_verziora_2.png?400|}} A --no-pager és a --reflog alkalmazása együtt: git --no-pager log --reflog ==== Nem követett fájlok törlése ==== Visszaállításkor előfordul, hogy nem követett fájlok maradnak, amit szeretnénk törölni. Először nézzük meg, milyen fájlok törlődnének: git clean -n Ha minden rendben, akkor mehet a törlés: git clean -f Könyvtárak eltávolítása: git clean -f -d Figyelmen kívül hagyott fájlok eltávolítása: git clean -f -X A figyelmen kívül hagyott és a nem figyelmen kívül hagyott fájlok eltávolítása: git clean -f -x Könyvtáron belüli nem követett fájlok törlése: git clean -f könyvtárútvonala ===== Munka a távoli szerverrel ===== {{:oktatas:programozás:verziókontroll:gittavolioperaciok.png|}} Ha https://github.com szerverrel szeretnénk dolgozni, nézzük meg a következő [[oktatas:programozas:verziokontroll:github|GitHub-s lapot]] ==== Helyi változat létrehozása ==== A clone parancsot akkor használjuk, ha olyan tárolóval szeretnénk dolgozni, amelyik nem áll rendelkezésre a helyi gépünkön. Ha szeretnénk dolgozni projekt1.git projekten, akkor a clone paranccsal töltsük le: git clone 192.168.5.103:/home/git/projekt1.git A javításokat visszatölthetjük, a push paranccsal. A felhasználó a saját könyvtárára így is hivatkozhat: git clone ssh://usernev@servernev/~/projekt1.git git clone usernev@servernev:/~/projekt1.git ==== Név URL összerendelés ==== Ahhoz, hogy a távoli gépre fel tudjunk tölteni létre kell hoznunk egy nevet és egy hozzátartozó URL-t. Az elsődleges név szokásosan az "**origin**" szokott lenni. Hogy milyen összerendelések vannak, a következő képen kérdezhetjük le: git remote Adjunk hozzá egy hozzárendelést: git remote add origin ssh://usernev@servernev/~/repo/projekt1.git Most megint nézzük meg, milyen összerendelések vannak: git remote Ha használjuk a -v kapcsolót is, akkor azt is kiírja milyen URL tartozik az adott névhez. Ha szeretnénk megváltoztatni egy nevet akkor a "rename" alparancs segít: git remote rename origin masiknev Törlés: git remote rm masiknev URL javítása: git remote set-url origin ssh://usernev@servernev/~/repo/projekt1.git Másik példa: git remote set-url origin git@192.168.5.103:/home/git/zold.git Lekérdezés: git remote get-url origin ==== Tartalom frissítése ==== Szeretnénk egy távoli tárolóból frissíteni a munkakönyvtárunkat. Lépjünk a munkakönyvtárba: cd c:\tervek\zold Feltételezzük, hogy be van állítva a távoli tároló: Leszedjük a tároló tartalmát: git pull origin master A pull parancsot, akkor szoktuk használni, ha rendelkezésünkre áll egy .git könyvtár. Ha nincs .git könyvtárunk, vagyis nincs munkaanyagunk, akkor git clone parancsot használjuk. A git pull parancs felülírja a helyi állományokat. ==== Tartalom letöltése megtekintésre ==== A **//git fetch//** paranccsal úgy tölthetjük le az állományokat, hogy nem írja felül a helyi állományokat. Egy külön branchként töltődik le. Letöltés: git fetch origin master Ezek után lesz egy remote/origin/master branch-ünk, ha erre váltunk, megnézhetjük a szerverről letöltött frissítést. Váltás a letöltött branch-re: git checkout remotes/origin/master A git diff paranccsal megnézhetjük a különbséget: git diff master..origin/master Ha szerverről leszedett állományok megfelelnek, akkor összeolvaszthatjuk a helyi állományokkal: git merge master origin/master ==== Feltöltés ==== Feltöltés: git push origin master A --tags kapcsolóval, a címkék is feltöltésre kerülnek, ha vannak. git push --tags origin master Egyszerre két branch is feltölthető: git push origin master devel A **git push** után mindig meg kell adni az **origin master** (vagy amit használunk). Megadható, hogy legyen mindig ez az alapértelmezés: git push --set-upstream origin master Innentől kezdve elég ez: git push Ha git clone paranccsal szedtük le a munkaanyagot, akkor elég a git push parancs: git push ==== Távoli tárolóból szeretnénk dolgozni ==== Ha nincs példányunk a projektből: git clone usernev@valahol.hu:projektnev ==== Mit tartalmaz a távoli tároló? ==== A show parancs közbeiktatásával azt is megtudhatjuk mit tud rólunk a távoli szerver. git remote show origin ==== Távoli tároló utolsó commit ==== git rev-parse origin/master Például: $ git rev-parse origin/master 817c888d15575a0fedfa78280bdc42a18f956168 ==== gitk ==== A **gitk** egy git tároló böngésző. Megmutatja a tárolóban történt változásokat, a kiválasztott commitokat. A gitk ezeket vizuálisan is megjeleníti, miközben megmutatja a commitok kapcsolatát. Egyik gyakran használt kapcsolója a --all, amely az összes változat megmutatására utasít. Ha ezt nem használjuk, akkor csak az aktuális változat, például a master ágat mutatja. ==== Távoli elágazások ==== git branch -a Kezdőpont ez legyen: git checkout -b fejlesztes remotes/origin/fejlesztes Helyben is létrejön és aktív is lesz. ===== Elágazás ===== ==== Elágazás létrehozása ==== Az elágazás a Git-ben a branch. A branch alparanccsal tudunk egy külön elágazás létrehozni. Amikor létrehozunk egy git projektet, a főágban dolgozunk, aminek a neve "master". Az újabb elágazásnak, egy új nevet kell adnunk. Az elágazás létrehozása: git branch Példa git branch devel1 Ezek után egy külön ágon is fejleszhetünk: {{:oktatas:programozas:verziokontroll:gitelagazas_02.png|}} A parancs, csak létrehozza a branch-et, de a HEAD nem áll át. Ha szeretnénk átállni a devel1 ágra, használjuk git checkout parancsot: git checkout devel1 Egy másik példa kedvéért legyen egy projekt, amely három állományból áll, A1, B1 és C1. Lásd az ábrán: {{:oktatas:programozás:verziókontroll:gitbranch.png?300|}} A továbbfejlesztés eredményeként, létrejön a A2, B2 és C2, megint továbbfejlesztve A3, B3 és C3. Ha létrehozok egy branchet, akkor egy külön ágon másolat jön létre a három állományból. A képen az első commit után egy branchet is készítettünk, amely egy külön ágat alkot. A létező branchek **listázásához** írjuk a parancssorba: git branch Ha létrehoztunk egy devel-1 branchet, akkor ehhez hasonlót kell lássunk a kimenetben: devel-1 * master A * karakter mutatja az aktív branchet. ==== Átállás másik elágazásra ==== Másik branch-re -- elágazásra -- átállás a checkout alparanccsal lehetséges: git checkout A kiadott parancsok ez után a ujagneve nevű branch-on hajtódnak végre. git switch A switch csak a 2.23-s verziótól érhető el, amit 2021-ben adtak ki. * https://kodekloud.com/blog/git-switch-vs-checkout/ ==== Helyi és távoli branch ==== Alapértelmezetten csak a helyi brancheket láthatjuk. A helyi és távoli branchet a -a vagy --all kapcsolókkal tekinthetjük meg: git branch -a Távoli branchek: git branch -r ==== Branch példa ==== Hozzunk létre egy devel-1 branchet: git branch devel-1 Branch név általános példák: * devel-1 * feature-1 * ficsor-1 * kiserlet-1 * fejlesztes-1 * sajatossag-1 * jokod Álljunk át a devel-1 elágazásra: git checkout devel-1 Álljunk vissza a főágra: git checkout master A -b azonnal létre hozza a devel-2 ágat, ha az nem létezik: git checkout -b devel-2 ==== Branch példa ábrákkal ==== Tegyük fel, hogy van egy master águnk, ahol már volt 3 commit, vagyis van három pillanatképünk. Készítünk egy devel1 nevű ágat, a git branch devel1 paranccsal. A HEAD ettől nem áll át automatikusan. {{:oktatas:programozas:verziokontroll:elagazas_01.png|}} Ha átállunk a git checkout devel1 utasítással a devel1 ágra, akkor a HEAD át áll, vagyis innentől kezdve a devel1 ágra mutat. {{:oktatas:programozas:verziokontroll:elagazas_02.png|}} Fejlesztünk a devel1 ágon, majd a commit paranccsal elkészítjük a pillanatképet. {{:oktatas:programozas:verziokontroll:elagazas_03.png|}} Most visszaállunk a master ágra. {{:oktatas:programozas:verziokontroll:elagazas_04.png|}} A master ágon is fejlesztünk, majd a commit paranccsal elkészítjük a pillanatképet. {{:oktatas:programozas:verziokontroll:elagazas_05.png|}} ==== Branch törlése ==== Töröljük a branchet: git branch -d devel-01 A nyomai megmaradnak. Nyomtalanul törlés: git checkout master git branch -D devel-01 A -D esetén nem ellenőrzi, hogy volt-e merge, ezért óvatosan. ==== Branch átnevezése ==== git branch -m devel-01 ficsor-01 ==== Branchek összefésülése ==== Adott a master és a fejlesztes branch. Szeretnénk a masterbe fésülni a fejlesztes branchet. Átváltok a master ágra, majd összefésülök: git checkout master git merge fejlesztes gitk A fast forward az jelenti problémamentesen össze lett fésülve. Ilyenkor a gitk-ban látszik hogy a két branch azonos. Konfliktus esetén szerkesszük a fájlt és töröljük a >>>>, =====, >>>>> sorokat. Majd commit. ===== Segítség ===== A git help parancs önmagában is segít. Kiírja milyen alparancsai vannak a gitnek: git help Ezek után már könnyű megnézni egy alparancsról mit kell tudni: git help Néhány alternatíva: git --help man git- Például: git help config Az alparancsokról kézikönyvet a Debian GNU/Linux rendszereken így is kérhetünk: man git ===== git gui ===== A git rendelkezik egy gui nevű alparanccsal is. Ekkor beindul egy grafikus felület, ahol git műveleteket kattintgatva tudjuk végrehajtani. Egyszerűen írjuk be parancssorba: git gui Linux alatt külön telepszik: apt install git-gui ===== Egyéb beállítások ===== Ékezetes fájlnevek: git config --global core.quotepath false Automatikus színezés: git config --global color.ui auto Álnevek létrehozása: git config --global alias.co checkout git config --global alias.ci commit git config --global alias.gl "git log" CR cseréje CRLF-re: git config core.autocrlf true Értéke true, false vagy input lehet. core.autcrlf=true repo / \ / \ crlf > lf lf>crlf core.autcrlf=input repo / \ / \ crlf > lf \ core.autcrlf=false repo / \ / \ / \ ===== Címkézés ===== Az egyes commitok azonosítói elég barátságtalanok egy átlagember számára. Lehetőségünk van az egyes commitokhoz egy címkét rendelni, így az azonosító szám helyett, használhatjuk ezt a címként. Címkét a már végrehajtott commithoz rendelhetünk. A commit után csak írjuk be: git tag cimke01 Ellenőrizzük a gitk paranccsal: gitk A használatban lévő címkéket lekérdezhetjük ha a tag alparancsnak nem adok meg paramétert: git tag Újabb commit után a címke az előző commithoz fog tartozni. Például: echo "új sor" >> vmi.txt git add vmi.txt git commit gitk A címkék lehetővé teszik a könnyebb állapotváltást. Például: git checkout cimke01 gitk Itt még visszaválthatok az előző commitra: git checkout master Az újabb commithoz adjunk egy újabb címkét. git tag cimke02 gitk A diff parancs is könnyebben használható címkékkel: git diff cimk01..cimke02 A címke a törölhető a következő módon: git tag -d cimke02 ===== Commitok eldobása ===== Ha még nem volt commit és "add" parancs sem, de a változásokat szeretném eldobni: git reset --hard Az utolsó commit óta eltelt minden változat eldobva. git status A fájlból is eltűnik. A hash azonosítóra hivatkozva, a korábbi commitig is eldobhatók a változások. Megnézem a naplót: git log Ha van lapozó program, kikapcsolható: git --no-pager log A --no-pager kapcsoló nélkül is megnézhetjük, de mivel lapozó program indul, a kilépés után eltűnik a képernyőről a kimenet. Kikeresem az utolsó commitot amit még szeretnék megtartani. git reset --hard 3483fg34 A HEAD ezentúl ide fog mutatni. A minimálisan 4 karaktert kell megadni az azonosítóból. git reset --hard 3483 ==== Új fájlok ==== A git reset nem dobja el az új fájlokat. Ha ezeket szeretnénk törölni: git clean -f Ez tulajdonképpen a nem követett fájlokat törli. * A -f nélkül és clean.requireForce git beállítás nélkül a git megtagadja a törlést. * A -d hatására a nem követett könyvtárakat is bejárja. * A -n hatására csak szimuláció történik. * A -x hatására a .gitignore fájlban megadott fájlok és könyvtárakra is érvényes. * Szükséges a -d kapcsoló * A -X hatására csak az "ignorált" fájlok kerülnek törlésre. ===== A commit szövegének cseréje ===== git commit --amend Az alapértelmezett szövegszerkesztőben megnyílik és javíthatjuk. Emlékeztető, hogyan állítjuk be a szövegszerkesztőt: git config core.editor notepad ===== Átmeneti mentés ===== git status touch ujfajl.txt git add ujfal.txt git commit Módosítom a fájlt: echo körte > ujfajl.txt git status Ezt a fájlt szeretnénk ideiglenesen eltenni: git stash save "változat egy" git status Újra a régivel folytatom. echo szilva > ujfajl.txt git stash save "változat kettő" git status Két fájl átmeneti tárolóba került. Listázzuk ezeket a fájlokat: git stash list A kimenet ehhez hasonló lesz: stash@{0}: On master: változat egy stash@{1}: On master: változat kettő Részletesebb információ: git stash show Esetleg a -p paraméterrel a különbségek is megjelennek. git stash show -p stash@\{0} A másik fájl: git stash show -p stash@\{1} Módosítás alkalmazása: git stash apply A legutoljára elmentett commitot alkalmazza. git stash list Fájl tartalmának ürítése: git reset --hard git stash list Utoljára elmentett commitot törli és alkalmazza: git stash pop Megadhatjuk melyik commit legyen: git stash pop stash@\{0} git stash list git status Nézzünk bele a fájlba. Ott van. Átmeneti tárolóból törlés: git stash drop Így, paraméter nélkül, az utolsót törli. ===== Archívum készítés ===== A munkakönyvtárról készíthetünk archívumot, adott formátumban. A hozzáférhető formátumok a -l vagy --list kapcsolóval kérdezhetők le. git archive -l LinuxMint rendszeren nálam a következő lehetőségeket kapom: tar tgz tar.gz zip Tar csomag készítése git archive HEAD > ../csomag.tar Vagy tömörítve: git archive HEAD | gzip > ../csomag.tar.gz Esetleg adjuk meg a formátumot: git archive HEAD --format=tar.gz > ../csomag.tar.gz ==== Utolsó commit ==== Az utolsó előtti és az utolsó commit közötti keletkezett könyvtárak és fájlok archiválása: git archive -o ../utolso.zip HEAD $(git diff --name-only --diff-filter=d HEAD^..HEAD) * git diff --name-only --diff-filter=d HEAD^..HEAD * Az utasítás megadja az utolsó előtti és az utolsó commit könyvtárakat és fájlokat. * --name-only * a fájlokat tartalmak nélkül, mutatja. * --diff-filter=d * A törölt fájlokat nem szeretnénk. * HEAD^..HEAD * ez mondja meg mely fájlokról van szó * Az utolsó HEAD elhagyható: HEAD^..HEAD Ha az utolsó előtti, előtti commit-tól szeretnénk: HEAD-2.. Használhatjuk a tar parancsot is: tar -czf utolso.tar.gz $(git diff --name-only --diff-filter=d HEAD^..HEAD ===== Takarítás ===== Ebben a részben a **du** parancsot használjuk, de ez Windowson csak Git Bash Shell esetén érhető el. Ellenőrizzük, hogy sérültek-e az adatok: git fsck Checking object directories: 100% (256/256), done. Ellenőrizzük le, mennyi adatot foglal egy .git könyvtárunk: du -sb .git Ekkor bájtban megadva láthatjuk az eredményt. Például: 81706 .git Ha Kibibájtban szeretnénk: du -sh .git Az eredmény ehhez hasonló: 160K Ha felesleges objektumok vannak, vagy egyszerűen tömöríteni kellene, akkor használjuk a git gc parancsot: git gc A futás után egy lehetséges kimenet: git gc Counting objects: 3, done. Writing objects: 100% (3/3), done. Total 3 (delta 0), reused 0 (delta 0) Ezek után ellenőrizzük újra a könyvtár méretét: du -sb .git 70834 .git du -sh .git 148K .git ===== Összefésülés ===== ==== merge ==== Legyen egy háromszög kerület, területszámító program, amelyet eddig fejlesztünk: class Program01 { public static void szamitHaromszog() { int 3 + 4 + 5; } public static void main(String[] args) { System.out.println("Hi"); } } Ekkor csinálunk rá egy elágazást. Legyen a neve: devel. git branch devel Ezt az ágat azonban nem fejlesztjük tovább. A master ágat azonban tovább fejlesztjük. Lesz egy jegy() metódus, majd commit. Lesz egy ertek() metódus, majd commit. class Program01 { public static void szamitHaromszog() { int 3 + 4 + 5; } public static void jegy() { System.out.println("Nevem jön ide"); } public static void ertek() { System.out.println("Értéke ez."); } public static void main(String[] args) { System.out.println("Hi"); } } Rájövünk, hogy nem is így kellett volna. Áttérünk a devel változatra: git checkout devel Először írunk egy getTriangleRange() metódust. Majd írunk egy getTriangleArea() metódust. class Program01 { public static double getTriangleRange(double a, double b, double c) { return a + b + c; } public static doubel getTriangleArea() { double s = (a + b + c) /2; return Math.sqrt(s*(s-a)*(s-b)*(s-c)); } public static void main(String[] args) { System.out.println("Hi"); } } Ellenőrizzük a gitk paranccsal hol tartunk: gitk --all {{:oktatas:programozás:verziókontroll:gitelagazas.png|}} A devel ág kódja teljesen jó. A master ág kódja viszont teljesen rossz amióta lett egy új branch. Átváltunk a master ágra: git checkout master Majd a merge paranccsal összefésülést kezdeményezünk: git merge devel A kimeneten kiíródik a konfliktus ténye: Auto-merging Program01.java CONFLICT (content): Merge conflict in Program01.java Automatic merge failed; fix conflicts and then commit the result. Az egyik megoldás lehet kézi javítás. Ha most megnyitjuk a Program01.java állományt, akkor ezt látjuk: class Program01 { <<<<<<< HEAD public static void szamitHaromszog() { int 3 + 4 + 5; } public static void jegy() { System.out.println("Nevem jön ide"); } public static void ertek() { System.out.println("Értéke ez."); ======= public static double getTriangleRange(double a, double b, double c) { return a + b + c; } public static doubel getTriangleArea() { double s = (a + b + c) /2; return Math.sqrt(s*(s-a)*(s-b)*(s-c)); >>>>>>> devel } public static void main(String[] args) { System.out.println("Hi"); } } Kitöröljük ettől: <<<<<<< HEAD az egyenlőség jelekig, majd a végéről töröljük a >>>>>>> devel sort. Elkészült. A második, hogy visszavonjuk az összefésülést: git merge --abort A harmadik lehetőség, hogy átvegyük a develágból az összes módosítást: git checkout MERGE_HEAD -- . Ez után jöhet a commit: git commit Ellenőrizzük a gitk paranccsal hol tartunk: gitk {{:oktatas:programozás:verziókontroll:gitelagazasosszefesulve.png|}} Majd törölhetjük a devel ágat: git checkout master git reset --hard devel Ellenőrizzük a gitk paranccsal hol tartunk: gitk {{:oktatas:programozás:verziókontroll:gitelagazasosszefesulvedevelresetelve.png|}} Ezen a ponton a devel és a master ág megegyezik. ==== rebase ==== A példa kedvéért vegyünk egy egyszerű példát: Feladatunk egy szamok.txt állomány fejlesztése, amely soronként tartalmaz számokat. Az első sor egyeseket, a következő ketteseket, stb. Indulás echo 11111 > szamok.txt git init git add szamok.txt git commit -m "Kezdés" echo 222222 >> szamok.txt git add szamok.txt git commit -m "Kettesek" Elágaztatunk, és a devel-1-et fejlesztjük tovább, ahol római számokat használunk: git branch devel-1 git checkout devel-1 echo "III III III III III" >> szamok.txt git add szamok.txt git commit -m "Hármasok" echo "IV IV IV IV IV" >> szamok.txt git add szamok.txt git commit -m "Négyesek" Egyesítjük a master és a devel-1 ágat: git checkout master git rebase devel-1 ==== Fájlok kódolása ==== Így nem akarja az LF bájtokat CRLF-re cserélni: git config --global core.autocrlf false ===== Linkek ===== Bash prompt beállítása: * https://github.com/magicmonty/bash-git-prompt * https://github.com/jimeh/git-aware-prompt/blob/master/prompt.sh * http://code-worrier.com/blog/git-branch-in-bash-prompt/ Windows kliens: * https://code.google.com/p/tortoisegit/ * http://git-cola.github.io/ * https://git-cola.github.io/downloads.html * http://gitextensions.github.io/ (2021) Tananyag: * http://nevergone.hu/hu/blog/100416/git-verziokezelo-linux-alatt * http://wiki.hup.hu/index.php/Hogyan_haszn%C3%A1ljuk_a_Git_verzi%C3%B3kezel%C5%91_rendszert Online szabadon használható Git tárolók: * https://gitlab.com * https://docs.gitlab.com/ee/user/project/import/github.html * https://gitea.io/ * https://git.wiki.kernel.org/index.php/GitHosting (Gyűjtemény) * https://github.com * https://pages.github.com/ (Webhely a Git projekteknek) Puska: * https://nonbleedingedge.com/cheatsheets/git.html (2020)