[[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, 2024
* 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 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)