14. diel - Git - Vnútorná štruktúra - Dokončenie
V minulej lekcii, Git - Vnútorná štruktúra, sme sa pozreli na vnútornú štruktúru Gitu. Ponorili sme sa do detailov spôsobu úschovy commitov a vykonávaných zmien v súboroch vykonaných Gitom.
V dnešnom Git tutoriále dokončíme zoznámenie s
vnútornou štruktúrou Gitu detailnejším preskúmaním objektov typu
blob
, tree
, commit
a tag
.
Následne si vysvetlíme, ako Git uchováva názvy
súborov.
Opäť si všetky príkazy vyskúšame v našom naklonovanom
repositári Laravel z lekcie Git – Základy –
Dokončenie. Otvoríme terminál MinTTY
a pomocou príkazu
cd laravel
sa do repositára presunieme.
Typy objektov
Už vieme, že vnútorná štruktúra Gitu je tvorená z objektov typu
blob
, tree
, commit
a tag
.
Tieto objekty sú v Gite na seba takto naviazané:
Objekty blob
, tree
,
commit
a tag
sme si predstavili v lekcii Git -
Vnútorná štruktúra.
Teraz si jednotlivé objekty popíšeme a vysvetlíme si, ako Git uchováva súbory.
Objekt typu commit
Commit je iba textovým súborom, ktorý prešiel kompresiou, dostal hash a
bol uložený v úložisku objektov. Obsahuje metadáta, ako sú informácie o
autorovi, commiterovi,
dátume vytvorenia commitu a commit správe.
Na zobrazenie obsahu alebo typu ľubovoľného objektu v úložisku je možné
použiť nízkoúrovňový príkaz git
s názvom
cat-file
vo formátoch:
- git cat-file <hash of the commit> -t
,
- git cat-file <hash of the commit> -p
.
Obaja si teraz vyskúšame 😀
Príkaz
git cat-file <hash of the commit> -t
Teraz teda potrebujeme hash nejakého commitu. Pre ten nebudeme chodiť nikam
ďaleko, ale použijeme náš hash
61f09d5980757dc0a9c05570d24584714b7cd635
, s ktorým sme pracovali v
lekcii Git -
Vnútorná štruktúra.
Zadáme teda príkaz
git cat-file 61f09d5980757dc0a9c05570d24584714b7cd635 -t
, ktorým
získame typ objektu:
MINGW64:/c/mygit/laravel/.git IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git (GIT_DIR!) $ git cat-file 61f09d5980757dc0a9c05570d24584714b7cd635 -t commit IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git (GIT_DIR!) $
Príkaz
git cat-file <hash of the commit> -p
S tým istým hashom spustíme príkaz
git cat-file 61f09d5980757dc0a9c05570d24584714b7cd635 -p
, ktorým
získame výpis obsahu commitu:
MINGW64:/c/mygit/laravel/.git IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git (GIT_DIR!) $ git cat-file 61f09d5980757dc0a9c05570d24584714b7cd635 -p tree 2992d926d6f3495b3b04b88564a1a0fc958d5696 parent 700444ac9735f2a393116705951511421061458d parent 53c4ef4ea87f4d7169a8fa0b74aff591b3508bd8 author ictdemy <[email protected]> 1703077311 +0100 committer ictdemy <[email protected]> 1703077311 +0100 Fix collision when merging branches IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git (GIT_DIR!) $
Vidíme, že náš commit obsahuje:
- metadáta o commite ako informácie o strome
(
tree
), - rodičovské commity,
- autora,
- commitera,
- samotnú správu ku commitu.
Objekt typu tree
tree
alebo strom je objekt používaný na ukladanie
zložiek v našom projekte. Strom môže ukazovať na iné stromy a
vytvárať tak úplnú hierarchiu súborov a podpriečinkov.
Každý commit ukazuje na stromový objekt, ktorý v jednej snímke zachytáva stav úložiska v čase vykonania commitu. Tento snímok je verzia projektu, ktorú ukladáme do našej histórie Gitu.
Pozrieme sa, ako taký strom vyzerá. Spustite príkaz
git cat-file <hash of the commit> -t
pre hash stromu
(tree
) 2992d926d6f3495b3b04b88564a1a0fc958d5696
:
MINGW64:/c/mygit/laravel/.git IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git (GIT_DIR!) $ git cat-file 2992d926d6f3495b3b04b88564a1a0fc958d5696 -t tree IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git (GIT_DIR!) $
Získame typ objektu tree
.
Spustite ešte pre ten istý hash stromu príkaz
git cat-file <hash of the commit> -p
, ktorým získame
výpis súborov obsiahnutých v strome:
MINGW64:/c/mygit/laravel/.git IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git (GIT_DIR!) $ git cat-file 2992d926d6f3495b3b04b88564a1a0fc958d5696 -p ... 100644 blob 8f0de65c560259bd171d746d12aa187f666893a3 .editorconfig 100644 blob ea0665b0a60cfaafaa7b2c80992a0e406700e1a2 .env.example 100644 blob fcb21d396d657f597ef8b6729f73d89b0a871c9b .gitattributes ... 100644 blob 2c95e74d918d0ea0aef057d2ee97536521101c72 README.md ... 040000 tree a9b549189653697bdcc2597e2a81e93fae10cea6 storage 040000 tree 49a71909565d8572e9d915c039b0fab49d0f4a1a tests 100644 blob 421b5695627db43c022947cfc7c0ecce6b9689be vite.config.js IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git (GIT_DIR!) $
Vidíme, že pre každý riadok z objektu stromu Git zaznamenáva:
- oprávnenie,
- typ objektu,
- hash objektu,
- názov súboru.
Názvy súborov sú riadené objektom stromu, nie súbory samotnými. Neskôr si vysvetlíme, prečo to tak je.
Objekt typu blob
blob
objekty obsahujú binárne alebo textové dáta
súborov. Ide o čisté dáta bez informácií o súborovom názve,
ceste alebo akýchkoľvek metadátach, ktoré by identifikovali samotný
súbor.
Bloby reprezentujú konkrétnu verziu súboru v danom okamihu, a preto sú kľúčové pre sledovanie zmien v rámci projektu. Každá zmena vykonaná v súbore vytvára novú verziu blobu. Bloby umožňujú Gitu efektívne ukladať obsah súborov vrátane ich histórie.
Teraz sa na taký blob pozrieme. Spustite príkaz
git cat-file <hash of the commit> -t
pre hash súboru
README.md
:
MINGW64:/c/mygit/laravel/.git IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git (GIT_DIR!) $ git cat-file 2c95e74d918d0ea0aef057d2ee97536521101c72 -t blob IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git (GIT_DIR!) $
Získame typ objektu blob
. Pre ten istý hash spustíme príkaz
git cat-file
s parametrom -p
:
MINGW64:/c/mygit/laravel/.git IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git (GIT_DIR!) $ git cat-file 2c95e74d918d0ea0aef057d2ee97536521101c72 -p The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT). Added text 1 Added text 2 Editing a file on the 10.x branch Editing a file on the feature branch ... IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git (GIT_DIR!) $
Vidíme, že sme získali výpis obsahu súboru README.md
.
Objekt typu tag
tag
čiže značka predstavuje špeciálny
odkaz používaný na označenie commitov v
histórii repositára. Je to statický odkaz na konkrétny commit, ktorý
následne nemení svoju hodnotu. Akonáhle je pre určitý commit tag
vytvorený, jeho hodnota zostáva nemenná. Tagy slúžia na označenie
špecifických bodov v histórii repositára. Vytvorené tagy sú uložené v
priečinku tags/
vnútri zložky refs/
.
Poďme si skúsiť preskúmať nejaký tag 😀 Najprv sa ale vrátime späť
do koreňového adresára .git/
príkazom cd ..
. Tagy
sú uložené v priečinku refs/tags/
. Presunieme sa tam príkazom
cd refs/tags/
:
MINGW64:/c/mygit/laravel/.git IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git (GIT_DIR!) $ cd refs/tags/ IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git/refs/tags (GIT_DIR!) $
Spustite príkaz ls
, ktorým získame výpis
tagov v repositári:
MINGW64:/c/mygit/laravel/.git/refs/tags IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git/refs/tags (GIT_DIR!) $ ls annotated_tag easy_tag IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git/refs/tags (GIT_DIR!) $
Získajme hash tagu annotated_tag
príkazom
cat annotated_tag
:
MINGW64:/c/mygit/laravel/.git/refs/tags IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git/refs/tags (GIT_DIR!) $ cat annotated_tag 04a272f847c916d9f3ebe7070be57e60142f0ab8 IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git/refs/tags (GIT_DIR!) $
Keď máme hash, zistite typ objektu príkazom:
MINGW64:/c/mygit/laravel/.git/refs/tags IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git/refs/tags (GIT_DIR!) $ git cat-file 04a272f847c916d9f3ebe7070be57e60142f0ab8 -t tag IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel/.git/refs/tags (GIT_DIR!) $
Získame potvrdenie, že annotated_tag
je objekt typu
tag
:
MINGW64:/c/mygit/laravel/.git/refs/tags
tag
Týmto sme dokončili naše skúmanie objektov typu blob
,
tree
, commit
a tag
. Môžeme sa teda
pustiť do ďalšej časti, v ktorej si vysvetlíme, ako Git uchováva
názvy súborov.
Názvy súborov
V tejto kapitole pochopíme, prečo Git uchováva názvy súborov v objekte
typu tree
(strom), a nie v type blob
. Poďme na to
😀
Najprv sa vrátime späť do koreňového adresára laravel/
príkazom cd ../..
. Začneme tým, že si vytvoríme dva nové
commity. Spustíme nasledujúce príkazy, ktoré vytvoria:
- prvý commit s názvom súboru
test_file.txt
a obsahomTest file
, - zložku
tasks/
, - druhý commit s názvom súboru
file.txt
as obsahomTest file
umiestnenom v priečinkutasks/
.
Kód je nasledujúci:
MINGW64:/c/mygit/laravel IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $ echo "Test file" > test_file.txt IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $ git add . IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $ git commit -m "Created new test file" [10.x a0cac287] New test file created 1 file changed, 1 insertion(+) create mode 100644 test_file.txt IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $ mkdir tasks IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $ echo "Test file" > ./tasks/file.txt IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $ git add . IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $ git commit -m "Tasks folder created" [10.x 0c52e84c] Tasks folder created 1 file changed, 1 insertion(+) create mode 100644 tasks/file.txt IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $
Spustite príkaz git show
, aby sme získali hash
posledného commitu:
MINGW64:/c/mygit/laravel IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $ git show commit 9d75672de3f87202b615435d3a5ebbe55d4f99ec (HEAD -> 10.x) Author: ictdemy <[email protected]> Date: Thu Dec 21 14:30:51 2023 +0100 Tasks folder created diff --git a/tasks/file.txt b/tasks/file.txt new file mode 100644 index 00000000..2d750b67 --- /dev/null +++ b/tasks/file.txt @@ -0,0 +1 @@ +Test file IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $
Hash sme získali. Spustite s ním teda príkaz
git cat-file 9d75672de3f87202b615435d3a5ebbe55d4f99ec -p
, aby sme
získali výpis obsahu commitu:
MINGW64:/c/mygit/laravel IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $ git cat-file 9d75672de3f87202b615435d3a5ebbe55d4f99ec -p tree f53345c1ed5beaf290ee8edf4881c5a09f14226b parent ec4c318d68c305e42f32f2832cc8507b371f237f author ictdemy <[email protected]> 1703165451 +0100 committer ictdemy <[email protected]> 1703165451 +0100 Tasks folder created IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $
Dostali sme výpis obsahu commitu. Vidíme, že tento commit obsahuje
nadradený rodičovský objekt parent
, ktorým je predošlý
commit.
Okrem prvého commitu každý commit v Gite obsahuje odkaz
parent
na predošlý commit.
Aby sme sa pozreli do objektu tree
, spustme príkaz
git cat-file <hash of the commit> -p
s hashom
predchádzajúceho commitu:
MINGW64:/c/mygit/laravel IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $ git cat-file f53345c1ed5beaf290ee8edf4881c5a09f14226b -p 100644 blob 8f0de65c560259bd171d746d12aa187f666893a3 .editorconfig 100644 blob ea0665b0a60cfaafaa7b2c80992a0e406700e1a2 .env.example ... 040000 tree 8229fefca7d57f5c87adeef4e35dffa79bb691a6 tasks 100644 blob 2d750b67d34524994ba425d168d5ed2576c11492 test_file.txt 040000 tree 49a71909565d8572e9d915c039b0fab49d0f4a1a tests 100644 blob 421b5695627db43c022947cfc7c0ecce6b9689be vite.config.js IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $
Získali sme výpis obsahu objektu. Ako môžeme vidieť,
strom obsahuje súbor test_file.txt
s hashom
2d750b67d34524994ba425d168d5ed2576c11492
z predošlého commitu.
Novo obsahuje objekt tree
s hashom
8229fefca7d57f5c87adeef4e35dffa79bb691a6
.
Zobrazme si obsah tohto stromu, teda hash zložky tasks/
, týmto
príkazom:
MINGW64:/c/mygit/laravel IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $ git cat-file 8229fefca7d57f5c87adeef4e35dffa79bb691a6 -p 100644 blob 2d750b67d34524994ba425d168d5ed2576c11492 file.txt IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $
Spustite príkaz git cat-file <hash of the commit> -p
pre
zobrazenie obsahu súboru test_file.txt
s jeho hashom
2d750b67d34524994ba425d168d5ed2576c11492
(pozri vyššie):
MINGW64:/c/mygit/laravel IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $ git cat-file 2d750b67d34524994ba425d168d5ed2576c11492 -p Test file IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $
Príkaz nám vypísal jeho obsah, teda Test file
.
Záver
Teraz vidíme, že hash súboru file.txt
je rovnaký ako hash
súboru test_file.txt
, hoci obaja sú rôzne súbory na iných
miestach. Git totiž rozpoznal, že oba súbory majú presne rovnaký obsah. A
preto sa rozhodol vytvoriť iba jeden blob
a
použiť rovnakú referenciu dvakrát, namiesto toho, aby
vytvoril dva identické objekty.
Príkaz hash-object
Poďme si ešte náš záver potvrdiť nízkoúrovňovým príkazom
hash-object
na rovnakom obsahu Test file
oboch
vyššie uvedených súborov. Príkaz vezme časť obsahu a vráti pre neho hash
kľúč.
Spustite nasledujúci príkaz hash-object
pre vytvorenie hasha
Test file
:
MINGW64:/c/mygit/laravel IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $ echo "Test file" | git hash-object --stdin 2d750b67d34524994ba425d168d5ed2576c11492 IctDemy@DESKTOP-ADEVTG4 MINGW64 /c/mygit/laravel (10.x) $
Ak sa nám zobrazí chyba, použite príkaz
printf "Test file" | git hash-object --stdin
.
Získali sme hash 2d750b67d34524994ba425d168d5ed2576c11492
pre
reťazec Test file
. To znamená, že ak vytvoríme ďalší súbor
.txt
s obsahom Test file
, nový commit bude odkazovať
na rovnaký blob
s rovnakým
hashom.
Git spracováva objekty vytvorené v databáze tak efektívne, že znovu
používa objekty blob
zakaždým, keď je obsah rovnaký.
Nezáleží na tom, či ide o iný súbor vytvorený v inom priečinku. To je
dôvod, prečo sú názvy súborov uložené v
stromoch. Toto rozhodnutie umožňuje systému Git
spracovávať odkazy na rovnaký objekt blob
s
rôznymi názvami súborov.
V budúcej lekcii, Git - Grafické užívateľské rozhranie Git GUI, si predstavíme grafické užívateľské rozhranie Git GUI. Ukážeme si, ako v ňom vytvoriť commit a spravovať vetvy.