Posodobi zgostitve za primer
This commit is contained in:
parent
0208e1588d
commit
40e17b1e06
3 changed files with 2384 additions and 2391 deletions
4700
git-obzornik.pdf
4700
git-obzornik.pdf
File diff suppressed because it is too large
Load diff
|
|
@ -61,21 +61,19 @@ V nadaljevanju bomo obravnavali nasledjne teme:
|
|||
- _Podatkovno skladišče:_ Kako Git uporablja #link("https://sl.wikipedia.org/wiki/Zgo%C5%A1%C4%8Devalna_funkcija")[zgoščevalno funkcijo]
|
||||
in #link("https://en.wikipedia.org/wiki/Merkle_tree")[Merklejeva drevesa] za hranjenje posnetkov vsebine mape.
|
||||
- _Zgodovina sprememb:_ Kako zgodovino predstavimo z #link("https://en.wikipedia.org/wiki/Directed_acyclic_graph")[usmerjenim acikličnim grafom],
|
||||
v katerem so vozlišča različice in ki povezuje različice z njihovimi neposrednimi predhodniki.
|
||||
v katerem so vozlišča različice, povezave pa povežejo različice z njihovimi neposrednimi predhodniki.
|
||||
- _Reference_: Kako preproste reference (kazalci) na vsebino omogočajo bliskovito
|
||||
preklaplanje med različicami in preprečijo popolno zmešnjavo, ko več ljudi hkrati spreminja iste datoteke.
|
||||
|
||||
= Podatkovno skladišče
|
||||
|
||||
Ko ustvarimo nov Git repozitorij, Git ustvari podmapo z imenom `.git`, ki vsebuje vse podatke, ki jih Git potrebuje. Git v mapi `.git` hrani različne stvari:
|
||||
- vsebino datotek, ki smo jih dodali v repozitorij
|
||||
- drevesno strukturo mape
|
||||
- posnetke stanja v rezličnih trenutkih s podatki o avtoju, datumu in opisu sprememb
|
||||
- kazalce na posamezne posnetke stanja
|
||||
Ko ustvarimo nov Git repozitorij, Git ustvari podmapo z imenom `.git` z vsemi podatki, ki jih Git potrebuje. Git v mapi `.git` hrani različne stvari:
|
||||
- vsebino datotek, ki smo jih dodali v repozitorij,
|
||||
- drevesno strukturo korenske mape, ki jo hranimo v repozitoriju,
|
||||
- posnetke stanja v različnih trenutkih s podatki o avtoju, datumu in opisu sprememb,
|
||||
- kazalce na posamezne posnetke stanja.
|
||||
|
||||
Git repozitorij je vsaka mapa, ki vsebuje podmapo `.git` z zgoraj navedenimi podatki.
|
||||
Podrobnosti o tem lahko preberete v knjigi Pro Git
|
||||
#cite(<chacon_102_nodate>, supplement: [pog. 10.2]).
|
||||
|
||||
== Zgoščevalna funkcija
|
||||
|
||||
|
|
@ -87,34 +85,37 @@ $
|
|||
H: B -> {0, 1, dots, 2^(160)-1},
|
||||
$
|
||||
ki vsakemu besedilu $b$ priredi 160-bitno zgostitev besedila $H(b)$. Funkcija $H$, je izbrana tako, da
|
||||
sprememba enega samega bita v besedilu $b in B$ spremeni vrednost $H(b)$. Poleg tega zahtevamo, da je porazdelitev vrednosti $H(b)$ čim bližje enakomerni porazdelitvi. To pomeni, da so vse vrednosti $H(b)$ približno enako verjetne.
|
||||
sprememba enega samega bita v besedilu $b in B$ spremeni vrednost $H(b)$. Poleg mora dobra zgoščevalna funkcija zagotoviti, da je porazdelitev vrednosti $H(b)$ čim bližje enakomerni porazdelitvi. To pomeni, da so vse vrednosti $H(b)$ približno enako verjetne.
|
||||
Kljub temu, da zgoščevalna funkcija $H$
|
||||
ni injektivna, je verjetnost, da bi imela dva podatkovna niza isto zgostitev (vrednost $H$) zelo majhna($approx 2^(-159)$). Zato lahko v praksi predpostavimo, da je niz $b$ enolično določen z njegovo zgostitvijo $H(b)$.
|
||||
|
||||
Ko datoteko z vsebino $b$ zabeležimo v Git repozitorij, git shrani vsebino v datoteko z imenom $H(b)$ v `git/objects`#footnote[V resnici Git shrani vsebino v datoteko z imenom $h_3 h_4 dots h_(40)$ v mapi $h_1 h_2$, kjer je
|
||||
$h_1 h_2 h_3 dots h_(40)$ zapis $H(b)$ v 16-tišlkem sistemu. Datoteka, katere vsebina ima zgostitev $H(b)$ enako `8dd6d4bdaeff93016bd49474b54a911131759648` bo shranjena v `.git/objects/8d/d6d4bdaeff93016bd49474b54a911131759648`].
|
||||
$h_1 h_2 h_3 dots h_(40)$ zapis $H(b)$ v 16-tiškem sistemu. Datoteka, katere vsebina ima zgostitev $H(b)$ enako `8dd6d4bdaeff93016bd49474b54a911131759648` bo shranjena v `.git/objects/8d/d6d4bdaeff93016bd49474b54a911131759648`].
|
||||
Vsebina $b$ je tako vedno dostopna pod imenom, ki je enako njeni zgostitvi $H(b)$. Tako dobimo #link("https://en.wikipedia.org/wiki/Content-addressable_storage")[vsebinsko naslovljivo shrambo objektov], ki je ena od bistvenih značilnosti Gita. Ta način shranjevanja omogoča, da lahko vedno preverimo, če ima shranjenjena vsebina isto zgostitev, kot je njeno ime. Lahko tudi shranimo več različic iste datoteke, saj ima vsaka različica drugačno zgostitev. Zgostitev služi tudi kot kontrola, če je prišlo do kvaritve podatkov, ki so shranjeni v Git repozitoriju.
|
||||
|
||||
Podrobnosti o tem, kako Git hrani podatke, si lahko preberete v knjigi Pro Git
|
||||
#cite(<chacon_102_nodate>, supplement: [pog. 10.2]).
|
||||
|
||||
== Datotečna drevesa
|
||||
|
||||
V vsebinsko naslovljivo shrambo objektov lahko shranimo vsebino datotek in njihovih prejšnjih različic. A kako ohranimo informacijo o imenu datotek in drevesni strukturi mape? Git za to ustvari nov tip objekta _drevo_ (angl. _tree_), ki hrani preprost seznam imen datotek in naslovov na vsebino datotek v mapi. Naslov na vsebino datoteke $b$ je seveda zgostitev vsebine $H(b)$. Seznam imen datotek in zgostitev je preprosta tekstovna datoteka, za katero lahko izračunamo zgostitev. zgostitev datotečnega drevesa natanko določa tako imena datotek, kot tudi vsebino datotek, ki so vsebovane v mapi. Če se katerakoli datoteka ali ime datoteke v mapi spremeni, se bo spremnila tudi
|
||||
V vsebinsko naslovljivo shrambo objektov lahko shranimo vsebino datotek in njihovih prejšnjih različic. A kako ohranimo informacijo o imenu datotek in drevesni strukturi mape? Git za to ustvari nov tip objekta _drevo_ (angl. _tree_), ki hrani preprost seznam imen datotek in naslovov na vsebino datotek v mapi. Naslov na vsebino datoteke $b$ je seveda zgostitev vsebine $H(b)$. Seznam imen datotek in zgostitev je preprosta tekstovna datoteka, za katero lahko izračunamo zgostitev. Zgostitev datotečnega drevesa natanko določa tako imena datotek, kot tudi vsebino datotek, ki so vsebovane v mapi. Če se katerakoli datoteka ali ime datoteke v mapi spremeni, se bo spremnila tudi
|
||||
njena zgostitev in posledično zgostitev za drevo. Poleg posameznih datotek, lahko drevo vsebuje tudi poddrevesa. Tako lahko rekurzivno ustvarimo drevesno podatkovno strukturo, ki zajema mapo z datotekami in podmapami v poljubni globini.
|
||||
|
||||
#figure(caption: [Vsebina mape v Gitu je preprost seznam datotek in podmap in zgostitev njihove vsebine],
|
||||
#figure(caption: [Vsebina mape v Gitu je preprost seznam datotek in podmap ter zgostitev njihove vsebine], kind: table,
|
||||
raw(align: left, block: true,
|
||||
"
|
||||
100644 blob bcc1382241e267cf790ca6b3afe9fde6dcf1072f bla.txt
|
||||
100644 blob 2ce22b4dc77442103f095503f1205937c1b0fcfc blabla.txt
|
||||
040000 tree 605f479464bebe4f7250ace49bab48e72855f84a podmapa
|
||||
100644 blob 33476f4951afc28d5ac2dc0d42d82f17ac817de2 bla.txt
|
||||
100644 blob 2ce22b4dc77442103f095503f1205937c1b0fcfc blabla.txt
|
||||
040000 tree ae247f2a35aadade5863aec2475cf13020304b06 podmapa
|
||||
"))
|
||||
|
||||
Poglejmo si primer. Denimo, da imamo v naslednjo strukturo datotek in podmap
|
||||
#figure(raw(block: true,
|
||||
"
|
||||
├── bla.txt (vsebina: bla)
|
||||
└── mapa
|
||||
├── bla.txt (vsebina: bla)
|
||||
└── blabla.txt (vsebina: blabla)
|
||||
├── blabla.txt (vsebina: blabla)
|
||||
└── podmapa
|
||||
└── bla.txt (vsebina: bla)
|
||||
"))
|
||||
|
||||
Git bo shranil naslednje objekte v vsebinsko naslovljivo shrambo:
|
||||
|
|
@ -122,14 +123,15 @@ Git bo shranil naslednje objekte v vsebinsko naslovljivo shrambo:
|
|||
#git-object("bcc1382241e267cf790ca6b3afe9fde6dcf1072f", "bla")
|
||||
- vsebino datoteke `blabal.txt`:
|
||||
#git-object("2ce22b4dc77442103f095503f1205937c1b0fcfc", "blabla")
|
||||
- seznam datotek v mapi `mapa`:
|
||||
#git-object("e8cc593eddfb9cfdafb4f9c46ab7f5a05ea00b2b",
|
||||
- seznam datotek v mapi `podmapa`:
|
||||
#git-object("ae247f2a35aadade5863aec2475cf13020304b06",
|
||||
"100644 blob bcc1382241e267cf790ca6b3afe9fde6dcf1072f bla.txt
|
||||
100644 blob 2ce22b4dc77442103f095503f1205937c1b0fcfc blabla.txt")
|
||||
")
|
||||
- seznam datotek v korenski mapi:
|
||||
#git-object("1331d77b31e40d6b470706b195f21244bb32cf21",
|
||||
"100644 blob bcc1382241e267cf790ca6b3afe9fde6dcf1072f bla.txt
|
||||
040000 tree e8cc593eddfb9cfdafb4f9c46ab7f5a05ea00b2b mapa")
|
||||
#git-object("473e0bbfc9de64fdca00e611e5666788ddf664ca",
|
||||
"100644 blob 33476f4951afc28d5ac2dc0d42d82f17ac817de2 bla.txt
|
||||
100644 blob 2ce22b4dc77442103f095503f1205937c1b0fcfc blabla.txt
|
||||
040000 tree ae247f2a35aadade5863aec2475cf13020304b06 podmapa")
|
||||
|
||||
Git z uporabo zgostitve kot kazalca na vsebino, vsebino mape postavi v podatkovno strukturo, ki jo matematično lahko opišemo z _usmerjenim acikličnim grafom_. Ko je vsebina
|
||||
datotek enaka(npr. `bla.txt` in `mapa/bla.txt`), Git shrani le eno kopijo, ki je dostopna v datoteki `.git/objects/bc/c1382241e267cf790ca6b3afe9fde6dcf1072f`. Zato datotečno drevo v Gitu ni nujno predstavljeno kot drevo, ampak kot usmerjen aciklični graf.
|
||||
|
|
@ -140,18 +142,18 @@ datotek enaka(npr. `bla.txt` in `mapa/bla.txt`), Git shrani le eno kopijo, ki je
|
|||
#figure(caption: [Primer datotečnega grafa povezanega z zgostitvami],
|
||||
diagram(
|
||||
{
|
||||
bla((-1, 0), name:<bla>)
|
||||
blabla((-1, 1), name: <blabla>)
|
||||
tree-object((1, 1), "e8cc59", name: <mapa>)[drevo]
|
||||
tree-object((3, 0), "1331d7", name: <root>)[drevo]
|
||||
edge(<root>, <bla>, "->")[`bla.txt`]
|
||||
edge(<root>, <mapa>, "->")[`mapa`]
|
||||
edge(<mapa>, <bla>, "->")[`bla.txt`]
|
||||
edge(<mapa>, <blabla>, "->")[`blabla.txt`]
|
||||
bla((-1, 1), name:<bla>)
|
||||
blabla((-1, 0), name: <blabla>)
|
||||
tree-object((1, 1), "ae247f", name: <mapa>)[drevo]
|
||||
tree-object((3, 0), "473e0b", name: <root>)[drevo]
|
||||
edge(<root>, <bla>, "->", label-angle: auto)[`bla.txt`]
|
||||
edge(<root>, <mapa>, "->", label-angle: auto, label-sep: -1.2em)[`mapa`]
|
||||
edge(<mapa>, <bla>, "->", label-angle: auto, label-sep: -1.2em)[`bla.txt`]
|
||||
edge(<root>, <blabla>, "->")[`blabla.txt`]
|
||||
}
|
||||
))
|
||||
|
||||
Posledično lahko vsebino celotne mape opišemo z eno samo zgostitvijo. Če spremenimo vsebino, ime ali lokacijo datoteke, bo sprememba vplivala na zgostitev spremenjene vsebine in sprememba bo splavala na površje do zgostitve za korensko mapo. zgostitev služi tako kot identifikator vsebine, kot tudi kot kontrolna vsota, ki omogoča detekcijo sprememb.
|
||||
Posledično lahko vsebino celotne mape opišemo z eno samo zgostitvijo. Če spremenimo vsebino, ime ali lokacijo datoteke, bo sprememba vplivala na zgostitev spremenjene vsebine in sprememba bo splavala na površje do zgostitve za korensko mapo. Zgostitev služi tako kot identifikator vsebine, kot tudi kot kontrolna vsota, ki omogoča detekcijo sprememb.
|
||||
|
||||
#note[
|
||||
Podatkovna struktura objektov v Gitu je podobna Merklejevim drevesom. Razlika je v tem, da Gita hrani le eno kopijo datotek z identično vsebino, zato dobimo usmerjen aciklični graf in ne drevesa. Postopek je podoben veriženju blokov, ki se uporablja v kriptovalutah.
|
||||
|
|
@ -171,7 +173,7 @@ V prejšnjem poglavju smo videli, kako Git hrani vsebino celotne mape in kako je
|
|||
|
||||
Osnovna enota v Gitu je *Vnos* (angl. *commit*). Vnos je posnetek stanja zabeleženih datotek v trenutku,
|
||||
ko je bil ustvarjen. Poleg vsebine datotek vsak vnos vsebuje še metapodatke o avtorju, datumu vnosa in opisom
|
||||
sprememb. Podobno kot objekt tipa _drevo_, je tudi vnos objekt v vsebinsko naslovljivi shrambi, ki je ima določeno *zgostitev vnosa*. zgostitev vnosa je natanko določena z vsebino shranjenih datotek in metapodatkov vnosa.
|
||||
sprememb. Podobno kot objekt tipa _drevo_, je tudi vnos objekt v vsebinsko naslovljivi shrambi, ki ima določeno *zgostitev vnosa*. Zgostitev vnosa je natanko določena z vsebino shranjenih datotek in metapodatkov vnosa.
|
||||
|
||||
#figure(
|
||||
git-object("8dd6d4bdaeff93016bd49474b54a911131759648",
|
||||
|
|
@ -230,7 +232,7 @@ Objekti so poevazni v _usmerjen aciklični graf_. Podgraf na vnosih določa zgod
|
|||
bla((0, -0.5), name:<bla>)
|
||||
blabla((0, 0.5), name:<blabla>)
|
||||
file-object((0, 1.5),"33476f", name:<bla1>)[bla!]
|
||||
tree-object((2, 0), "ae12fg", name:<koren0>)[koren]
|
||||
tree-object((2, 0), "5e12fg", name:<koren0>)[koren]
|
||||
tree-object((2, 1), "32e4f1", name: <koren1>)[koren]
|
||||
commit-object((4, 0), "7e43a1", name: <commit0>)[Prvi vnos]
|
||||
commit-object((4, 1), "4ef531", name: <commit1>)[Popravi bla.txt]
|
||||
|
|
@ -270,7 +272,7 @@ Poleg objektov kot so _vnosi_, _posnetki map_ in _posnetki datotek_ pozna git š
|
|||
caption: [Veja (angl. branch) ali značka(angl. tag) je preprost kazalec na posamezen vnos(angl. commit). ]
|
||||
)
|
||||
|
||||
Referenc git ne hrani v skladišču objektov, temveč posebej v mapi `.git/refs`. Zato so reference vezane na posamezen repozitorij in se lahko razlikujejo med različnimi kloni določenega repozitorija.
|
||||
Referenc git ne hrani v skladišču objektov, temveč posebej v mapi `.git/refs`. Reference vezane na posamezen repozitorij in se lahko razlikujejo med različnimi kloni določenega repozitorija.
|
||||
|
||||
*Veja* (angl. *branch*) je posebne vrste referenca, ki se premika, ko dodajamo nove vnose. Vsakič ko ustvarimo nov vnos, se trenutno aktivna veja premakne na novo ustvarjeni vnos.
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
url = {https://git.fri.uni-lj.si/martin.vuk/git-intro},
|
||||
abstract = {Uvod v Git},
|
||||
language = {en-US},
|
||||
urldate = {2026-01-03},
|
||||
journal = {git-intro},
|
||||
author = {Vuk, Martin},
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue