-
Rafael László authoredRafael László authored
Alapok
Mit tegyek ha elakadok?
Git-ben van egy beépített git help parancs:
$ git help <verb>
$ git <verb> --help
$ man git-<verb>
Például a config-al kapcsolatos dolgok:
$ git help config
De ha csak egy gyors áttekintésre van szükséged:
\$ git config -h
usage: git config [<options>]
Config file location
--global use global config file
--system use system config file
--local use repository config file
--worktree use per-worktree config file
-f, --file <file> use given config file
--blob <blob-id> read config from given blob object
Action
--get get value: name [value-regex]
...
Repository
A Git repository egy olyan mappa, mely Git verziókezelés alatt áll. Például az a mappa, ahol van egy .git mappa, az egy git repo.
\$ ls -al
total 20
drwxrwxr-x 4 rlacko rlacko 4096 okt 8 12:59 .
drwxrwxr-x 3 rlacko rlacko 4096 okt 7 12:04 ..
drwxrwxr-x 5 rlacko rlacko 4096 okt 7 12:46 docs
drwxrwxr-x 8 rlacko rlacko 4096 okt 8 16:39 .git
-rw-r--r-- 1 rlacko rlacko 17 okt 7 12:09 README.md
Csináljunk egy sajátot!
Hozzunk létre egy tetszőleges projekt mappát és lépjünk bele
$ mkdir projektem
$ cd projektem
Nézzük meg, hogy mi a helyzet a git-el ezzel a mappában.
Ehhez a git status
parancsot tudjuk használni.
Ez a parancs a jelenlegi git repo-nkról képes
információkat kiírni.
\$ git status
fatal: not a git repository (or any of the parent directories): .git
Teljesen üres a mappa, még nincs verzió kontroll alatt.
ls -al
-el tudjuk is ellenőrizni.
Tegyük verziókontroll alá a git init
paranccsal.
Ez beállítja nekünk a master
branchet és más alap dolgokat.
A branch-ről még később beszélek, de azt jegyezzük meg addig,
hogy ide kerülnek a mentéspontjaink egymás után sorban, mint
egy fa ága.
\$ git init .
Initialized empty Git repository in .../projektem/.git/
Ha megnézzük, mostmár van egy .git mappánk
\$ ls -al
total 12
drwxrwxr-x 3 rlacko rlacko 4096 okt 8 16:52 .
drwxrwxr-x 12 rlacko rlacko 4096 okt 8 16:49 ..
drwxrwxr-x 7 rlacko rlacko 4096 okt 8 16:52 .git
Ebben van minden adatunk a git repo-val kapcsolatban. Gyakorlatilag mikor egy távoli git repo-t leszedünk, akkor ezt a mappát kapjuk meg. Ebből ezután a git alkalmazásunk előállítja nekünk a master ág legutóbbi mentéspontját.
Mentéseink tárolása
Egy logikus megoldásnak tűnhet, hogy az egyes fájlok közt csak az eltéréseket tároljuk. Például:
1. mentés:
alma
2. mentés:
[1.mentés 1.sora]
alma
Ez annyiból jó, hogy a tárhellyel spórol, viszont nem gyors. Képzeljünk el egy 1000 commit-ból álló repo-t. Mi történik mikor a legutóbbit lekérjük?
Erre egyik megoldás más verziókezelőknél, hogy optimalizálnak és mondjuk 50 mentésenként csinálnak egy teljes mentést, stb.
A Git ezt úgy oldja meg, hogy egy mentés az összes fájlt
egy az egybe lemásolja.
Például egyik mentés alkalmával feltöltök egy 1gb-os videót,
majd a következő mentéskor törlöm, akkor az a videó
benne marad a git repo-ban.
Persze utólag tudunk olyat, hogy kitöröljük az adott mentésből,
de ez nem ajánlott használata a Git-nek.
Oké, tehát például mappákba bemásolja a mentéseinket valamilyen módon, de mégis hova?
$ tree .git/objects/
.git/objects/
├── 13
│ └── 46dac32baea8123272f60b6a04227fe3872bdb
...
├── e6
│ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
├── f4
│ └── 5a6ff55496414b573e97064e998f065182eeee
├── info
└── pack
Mégis mik ezek?
A Git tömörítve és titkosítottan hashelve tárolja a fájlokat.
A hashelésnek annyi a lényege, hogy a fájl teljes tartalmán
átfuttatunk egy algoritmust, mely ezután kiköp egy 0-9a-z
szöveget és ha akár 1 bit-et is változtatunk egy fájlon, akkor
más lesz a hash-e, sőt a titkosítás miatt még feltörni is
lehetetlen.
Tehát ha valaki elcommitol valamit, akkor azt már más nem tudja
megváltoztatni anélkül, hogy változna a hash.
Így tudjuk biztosítani a teljes konzisztenciát az elosztott
repo-k között.
Hash-t láthatunk például a mentéspontjainkon, fájljainkon, stb.
Ennél jobban nem megyek bele a témába, de érdekes olvasmány. A lényeg, hogy mindenhol ott vannak a hash-ek, és erre mindjárt látunk példát.
Változtatások mentése
Na de hogyan készítünk ilyen mentéseket?
A fájljainknak különböző állapotai létezhetnek egy repo-ban.
- Untracked: Ami még nincs verziókontroll alatt
- Staged: Ami már verziókontroll alatt van de még nem mentettük el
- Unmodified: Amit már elmentettünk és azóta nem változott
- Modified: Az a fájl, ami már verziókontroll alatt van és változott. Ezt utánna szintén Stage-be tudjuk tenni
Nézzük meg ezen az ábrán és egy példa projekten keresztül:
Mi a jelenlegi helyzet a repo-ban, miután inicializáltuk?
\$ git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
Láthatjuk, hogy még nincsenek mentéspontjaink és nincs mit elmentenünk és egyben a git próbál segíteni, hogy hogyan tudunk stagelni valamit. Ezt több helyen is megfigyelhetjük a git-ben. Próbál segíteni ahol csak tud, minél kényelmesebbé téve a munkánkat.
Vegyünk fel egy új fájlt.
echo 'alma' > gyumolcskosar
Itt az echo
egy olyan parancs volt, mely kiírta nekünk a
terminálra azt, hogy "alma", de átirányítottuk egy fájlba
a >
operátorral és mivel nem létezett a fájl, azt létre is
hozta.
Újra megvizsgálva a status-t, látni fogjuk, hogy megjelent, de még nincs verziókontroll alatt.
\$ git status
...
Untracked files:
(use "git add <file>..." to include in what will be committed)
gyumolcskosar
nothing added to commit but untracked files present (use "git add" to track)
Ahhoz, hogy git alá helyezzük, a git add <fájl>
parancsot
fogjuk kiadni.
Ezek a parancsok mind képesek rá, hogy
Unix-os módon több fájlra is kiadhatóak legyenek.
Például a <fájl>
lehet *.jpg
amivel minden .jpg fájlt kijelölünk a jelenlegi mappában"
\$ git add gyumolcskosar
Ezután megjelenik, mint új fájl a git adatbázisában.
\$ git status
...
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: gyumolcskosar
A fájlunk átkerült staged módba és ezt akár mostmár el is
tudjuk menteni.
A mentéshez a git commit
parancsot tudjuk
használni.
$ git commit
-ot kiadva megnyilik a beállított szövegszerkesztőnk és némi
információ a leendő mentéspontról.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
#
# Initial commit
#
# Changes to be committed:
# new file: gyumolcskosar
Láthatjuk amit a git status
parancs írna ki és pár extra
segítséget a git-től.
A # -el kezdődő sorok kommentek, ezek nem fognak a commit
üzenetbe belekerülni.
Írjuk be az első sorba, hogy Készítettem egy gyümölcskosarat
,
majd mentsük el a fájlt és zárjuk be a szövegszerkesztőt.
\$ git commit
[master (root-commit) c45abc3] Készítettem egy gyümölcskosarat
1 file changed, 1 insertion(+)
create mode 100644 gyumolcskosar
A git mikor érzékelte, hogy bezártuk a fájlt, akkor abból kiolvasta a sorokat, ignorálva a #-el kezdődőket és hozzáadta a mentéspontunkhoz, mint üzenet. Ezt láthatjuk is a visszajelzésben. Továbbá megjelent pár további hasznos információ is.
Ismételten nézzük meg mi a helyzet a reponkban:
\$ git status
On branch master
nothing to commit, working tree clean
Mostmár nem szól amiatt, hogy még nincsen mentésünk, továbbá azt is írja, hogy még semmin nem változtattunk, nem tudunk mit elmenteni.
Nézzük meg a további két állapotot is amiben lehet egy fájl.
Írjuk bele a gyumolcskosar fájlba, hogy korte
alma
korte
Ezután kiadva a git status
-t:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: gyumolcskosar
no changes added to commit (use "git add" and/or "git commit -a")
Látható, hogy mostmár modified
a fájlunk, mentsük is el,
de most picit másképp. A git és általában minden Unix
parancsnak áttudunk adni úgynevezett kapcsolókat.
Például git commit -m <message>
.
Ez annyit spórol meg nekünk, hogy nem kell szövegszerkesztőt
megnyitnia a git-nek mikor új commit-ot készítünk,
hanem átraktuk a parancsot olyan módba,
hogy várjon egy szöveget, mint mentéshez kapcsolódó üzenet.
Általában logikusak az egy betűs rövidítések:
-m: message, -a: all
, de tudunk hosszabb verziókat is
használni, mint --message, --all
.
Ne felejtsük el először stagelni a mentendő fájljaink egy
git add <fájl>
parancs kiadásával.
$ git add gyumolcskosar
$ git commit -m "Raktam bele egy körtét"
Készítsünk egy új fájlt hordo
néven és nézzük mit ír ki
a git status -s
parancs.
$ git status -s
?? hordo
Ezzel a kapcsolóval képesek vagyunk egy rövidített státuszt
lekérni. Stageljük majd pedig commitoljuk el
"Hoztunk egy hordót"
üzenettel. A lépések közt nézzük meg
mit ír ki a git status -s
.
Mi van akkor, ha valami fájlt nem szeretnénk verziókontroll alá tenni? Gondolok például a build-ek mappáira vagy adott Eszköz által generált fájlokra?
Hozzunk létre egy .gitignore
fájlt és egy jegyzeteim.txt
fájlt.
Ezután adjuk ki a git status
parancsot.
Láthatjuk, hogy a jegyzeteim
fájl nem jelent meg, tehát
ignoráljuk a fájlt. Stage-ljük, majd mentsük el a fájlt a
git add .
, git commit -m "jegyzeteim ignorálása"
Fájlok mozgatása
A git semmi adatot nem tárol változásokról, csak mentéseket készít, ahogy említettem az előző részben. Próbáljuk ki, hogy mi történik ha átnevezünk egy fájlt?
mv gyumolcskosar gyumolcskosar.txt
git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: gyumolcskosar
Untracked files:
(use "git add <file>..." to include in what will be committed)
gyumolcskosar.txt
no changes added to commit (use "git add" and/or "git commit -a")
Látható, hogy az eredeti fájlt "töröltük" és egy új fájlt vettünk fel a repo-ba. Érdekes, mi lenne ha stagelnénk a változtatásokat?
$ git add .
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: gyumolcskosar -> gyumolcskosar.txt
Most meg már látszik, hogy csak átnevezés történt?
A Git képes rá, hogy felismerje a fájlokat és eldöntse, hogy ugyanaz volt a kettő, tehát átnevezés történt.