IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

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é:

Ukážka zviazanosti objektov vo vnútornej štruktúre Gitu - Git

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 obsahom Test file,
  • zložku tasks/,
  • druhý commit s názvom súboru file.txt as obsahom Test file umiestnenom v priečinku tasks/.

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.


 

Predchádzajúci článok
Git - Vnútorná štruktúra
Všetky články v sekcii
Git
Preskočiť článok
(neodporúčame)
Git - Grafické užívateľské rozhranie Git GUI
Článok pre vás napísal Filip Studený
Avatar
Užívateľské hodnotenie:
1 hlasov
.
Aktivity