Lekce 13 - Git - Vnitřní struktura
V předchozím kvízu, Kvíz - Kolize mezi větvemi a vzdálený repositář v Gitu, jsme si ověřili nabyté zkušenosti z předchozích lekcí.
V dnešním Git tutoriálu se podíváme na
vnitřní strukturu Gitu. Ponoříme se do detailů způsobu
úschovy commitů a vykonávaných změn v souborech provedených Gitem. Také
si vysvětlíme, k čemu slouží složka .git/
.
Všechny příkazy si budeme opět zkoušet v našem
naklonovaném repozitáři laravel
z lekce Git - Základy -
Dokončení. Otevřeme terminál MinTTY
a pomocí příkazu
cd laravel
se do repozitáře přesuneme.
Vnitřní struktura Gitu
Git funguje jako tabulka mapující hodnoty (náš obsah) pomocí unikátních klíčů. Každá hodnota je posloupností bajtů. Přiřazením hodnoty vytvoří Git hashovací klíč pomocí kontrolního součtu SHA-1. Hashovací klíč slouží k identifikaci uložených hodnot bez ohledu na počítačovou platformu či operační systém. Jestliže se hodnota nemění, Git vždy poskytne stejný hash klíč.
Pro každý soubor Git počítá kontrolní součet SHA-1 v podobě 40místného hexadecimálního čísla, podle kterého si Git soubor ukládá.
Představme si, že chceme verzovat složku s několika soubory a podsložkami. Naivním řešením by bylo u každé nové verze překopírovat celý její obsah a takto zpětně skládat různé verze. To by bylo velmi neefektivní řešení. Navíc verze každého souboru by měla být jednoznačně identifikovatelná, abychom mohli verze různě kombinovat.
Vnitřní struktura Gitu se skládá z:
- BLOB objektů – uchovávají obsah jednotlivých souborů,
- Tree objektů – slouží k reprezentaci struktury složek a obsahují odkazy na BLOB objekty nebo další stromy,
- Commitů – zaznamenávají metadata, jako je autor, popis změn a odkazy na konkrétní stromy (tree objekty),
- Ukazatelů na commity – pomocí nich se definují vztahy mezi commity a větvemi v historii,
- Tagů – označují specifické commity nebo body v historii.
Ukažme si, jak jsou objekty ve vnitřní struktuře Gitu na sebe navzájem navázány:
Commity, tagy, BLOB a tree objekty jsou identifikovány pomocí šifry SHA-1, která zajišťuje jejich jedinečnost. V počátečních verzích Gitu bylo nutné tuto strukturu vytvářet ručně. Dnes Git tento proces automatizuje a uživatelé využívají příkazy k manipulaci se strukturou. I přesto se podíváme na základní principy, jak Git uvnitř pracuje, abychom lépe porozuměli jeho fungování.
Složka .git/
Při inicializaci nového úložiště pomocí příkazu
git init
Git vytvoří složku .git/
s několika
soubory a podsložkami. Jelikož jsme repozitář laravel
klonovali, složku .git/
již obsahuje. Přesuňme se do ní
pomocí příkazu cd .git
:
MINGW64:/c/mujgit/laravel ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (10.x) $ cd .git ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel/.git (GIT_DIR!) $
Následně příkazem ls
získejme výpis obsahu složky:
MINGW64:/c/mujgit/laravel/.git ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel/.git (GIT_DIR!) $ ls COMMIT_EDITMSG ORIG_HEAD description index logs/ packed-refs HEAD config hooks/ info/ objects/ refs/ ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel/.git (GIT_DIR!) $
Tento výpis zobrazuje seznam souborů a složek ve složce
.git/
, které jsou součástí základní struktury vytvořené
při inicializaci úložiště Git.
Samotné soubory ve složce .git/
mají specifické účely a
zastávají důležité role při uchovávání informací o stavu repozitáře
a jeho historie. Složka .git/
obsahuje soubory a složky:
HEAD
– odkazuje na aktuální referenční bod v repozitáři, aktuální větev (branch) nebo na konkrétní commit,description
– obsahuje textový popis repozitáře,index
– uchovává informace o stavu pracovní složky a staging oblasti,logs/
– obsahuje historii událostí v repozitáři,packed-refs
– obsahuje seznam zabalovaných referencí, typicky odkazy na konkrétní commity,config
– uchovává konfiguraci repozitáře,hooks/
– obsahuje spouštěcí skripty pro různé události,info/
– obsahuje různé informace o repozitáři,objects/
– uchovává všechny objekty v repozitáři,refs/
– obsahuje odkazy na commity a větve,COMMIT_EDITMSG
– obsahuje zprávy commitů,ORIG_HEAD
– ukládá stav hlavy před provedením operace změny.
Nyní si blíže popíšeme složky objects/
, info/
a logs/
.
Složka objects/
Složka objects/
je databáze objektů Gitu, v
nichž jsou uloženy všechny potřebné objekty pro uchování různých verzí
našeho projektu. Přesuňme se nyní do této složky příkazem
cd objects/
a získejme její obsah příkazem ls
:
MINGW64:/c/mujgit/laravel/.git/objects ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel/.git (GIT_DIR!) $ cd objects ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel/.git/objects (GIT_DIR!) $ ls 04/ 18/ 2c/ 30/ 51/ 5c/ 65/ 6e/ 7b/ 85/ a9/ ac/ b5/ c4/ info/ 16/ 29/ 2e/ 39/ 53/ 61/ 67/ 70/ 81/ a2/ aa/ ae/ c0/ ca/ pack/ ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel/.git/objects (GIT_DIR!) $
Nyní se na jednotlivé typy podsložek složky objects/
podíváme podrobněji.
Složky info/
a
pack/
Složky info/
a pack/
jsou využívány Gitem pro
provádění nízkoúrovňových optimalizací a k
manipulaci s objekty. Složka:
info/
– ukládá nezabalované objekty, obsahuje metadata a další informace o objektech v repozitáři,pack/
– ukládá zabalované objekty, čímž zlepšuje efektivitu úložiště a urychluje operace v repozitáři Git.
Složky s číselnými názvy
Tyto podsložky ve složce objects/
označují shluky objektů v
repozitáři Gitu. Pojďme se ponořit do těchto objektů a podívejme se na
to, co přesně jsou zač. Začneme tím, že se podíváme na poslední commit.
Zadáme příkaz git log
, kterým získáme poslední provedený
commit včetně jeho hashe:
MINGW64:/c/mujgit/laravel/.git/objects ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel/.git/objects (GIT_DIR!) $ git log commit 61f09d5980757dc0a9c05570d24584714b7cd635 (HEAD -> 10.x) Merge: 700444ac 53c4ef4e Author: itnetwork <[email protected]> Date: Wed Aug 30 10:42:37 2023 +0200 Oprava kolize při sloučení větví ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel/.git/objects (GIT_DIR!) $
Vidíme, že hash commitu je
61f09d5980757dc0a9c05570d24584714b7cd635
. Opět spustíme příkaz
ls
, abychom zobrazili obsah složky objects/
:
MINGW64:/c/mujgit/laravel/.git/objects ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel/.git/objects (GIT_DIR!) $ ls 04/ 18/ 2c/ 30/ 51/ 5c/ 65/ 6e/ 7b/ 85/ a9/ ac/ b5/ c4/ info/ 16/ 29/ 2e/ 39/ 53/ 61/ 67/ 70/ 81/ a2/ aa/ ae/ c0/ ca/ pack/ ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel/.git/objects (GIT_DIR!) $
Když porovnáme první dvě cifry commitu s názvy složek, zjistíme, že tato složka má tyto cifry stejné jako hash commitu:
Hash: 61f09d5980757dc0a9c05570d24584714b7cd635 Složka: 61/
Příkazem cd 61
se tedy přesuňme do této složky a zobrazme
příkazem ls
její obsah:
MINGW64:/c/mujgit/laravel/.git/objects/61 ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel/.git/objects (GIT_DIR!) $ cd 61 ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel/.git/objects/61 (GIT_DIR!) $ ls f09d5980757dc0a9c05570d24584714b7cd635 ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel/.git/objects/61 (GIT_DIR!) $
Vidíme, že je zde soubor, který obsahuje zbytek našeho hashe. Název souboru se rovná zbytku znaků, které tvoří hash klíč commitu. Toto označení složek a souborů v databázi objektů je konvence, kterou Git dodržuje pro efektivní vyhledávání objektů. V tomto případě se jedná o objekt v databázi objektů pro tento commit.
Složka logs/
Vrátíme se do složky .git/
, kde nalezneme složku
logs/
. Ta obsahuje historii událostí v
repozitáři. Tato složka uchovává různé záznamy a logy související s
pohybem referencí, jako jsou větve (branches) a reflogy.
Reflogy jsou záznamy o pohybu referencí včetně informací o
posledních změnách, například o změnách větví nebo o obnovení
ztracených commitů.
Každá změna v referencích, jako je přesunutí větve nebo změna historie commitů, je zaznamenána v této složce. Logy v této složce jsou uchovávány pro sledování a možnost obnovy historie změn a operací v repozitáři.
Složka logs/
obsahuje různé podsložky a soubory pro různé
typy logů a záznamů, které poskytují informace o pohybu v
repozitáři. Uchovávání těchto záznamů umožňuje vývojářům
analyzovat historii změn a provádět operace
obnovy.
Složka info/
Ve složce .git/
nalezneme také složku info/
,
která obsahuje různé informace o repozitáři. Tato složka slouží k
uchování různých konfiguračních a informačních souborů, které
poskytují metadata a další užitečné údaje pro Git repozitář.
Ve složce info/
můžeme najít tyto soubory:
exclude
– obsahuje pravidla pro ignorování souborů a složek v rámci repozitáře, podobně jako soubor.gitignore
,grafts
– uchovává informace o historických bodech spojování commitů, takzvaných graft points, a to v případě změny historie větví,attributes
– obsahuje specifické nastavení pro různé typy souborů, jako jsou atributy ovlivňující chování Gitu při práci se soubory.
V příští lekci, Git - Vnitřní struktura - Dokončení, detailněji prozkoumáme objekty typu
blob
, tree
, commit
a tag
.
Také si vysvětlíme, jak Git uchovává názvy souborů.