Izvleci definicije v novo datoteko in posodobi poglavje o shrambi.
This commit is contained in:
parent
a34aecc98a
commit
bfb96486db
3 changed files with 110 additions and 56 deletions
19
definicije.typ
Normal file
19
definicije.typ
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#import "@preview/fletcher:0.5.8" as fletcher: diagram, node, edge
|
||||
#import fletcher.shapes: house, chevron, pill, hexagon
|
||||
|
||||
#let commit-color = green
|
||||
#let tag-color = orange
|
||||
#let branch-color = purple
|
||||
#let thin = 0.5pt;
|
||||
#let thindotted = (thickness: thin, dash: "dotted");
|
||||
#let thindashed = (thickness: thin, dash: "dashed");
|
||||
#let commit-node(coord, hash, ..args) = node(
|
||||
coord, raw(hash), shape: pill, fill: commit-color.lighten(50%), stroke: thin, ..args)
|
||||
#let commit-object(coord, hash, name, ..args) = node(
|
||||
coord, align(left, [#text(size: 8pt, gray.darken(50%), raw(hash))\ #name]),
|
||||
corner-radius: 7pt, fill: commit-color.lighten(50%), stroke: none, ..args)
|
||||
#let tree-object(coord, hash, content, ..args) = commit-object(coord, hash, content,
|
||||
width: 2cm, fill: blue.lighten(50%), ..args)
|
||||
#let file-object(coord, hash, name, ..args) = commit-object(coord, hash, name,
|
||||
width: 2cm, fill: gray.lighten(50%), ..args)
|
||||
#let git-object(hash, content) = table(columns: 1, [Zgoščena vrednost: #raw(hash)], raw(block:true, content))
|
||||
|
|
@ -2,22 +2,7 @@
|
|||
#set page("a4", margin: 5mm)
|
||||
#import "@preview/fletcher:0.5.8" as fletcher: diagram, node, edge
|
||||
#import fletcher.shapes: house, chevron, pill, hexagon
|
||||
|
||||
#let commit-color = green
|
||||
#let tag-color = orange
|
||||
#let branch-color = purple
|
||||
#let thin = 0.5pt;
|
||||
#let thindotted = (thickness: thin, dash: "dotted");
|
||||
#let thindashed = (thickness: thin, dash: "dashed");
|
||||
#let commit-node(coord, hash, ..args) = node(
|
||||
coord, raw(hash), shape: pill, fill: commit-color.lighten(50%), stroke: thin, ..args)
|
||||
#let commit-object(coord, hash, name, ..args) = node(
|
||||
coord, align(left, [#text(size: 8pt, gray.darken(50%), raw(hash))\ #name]),
|
||||
corner-radius: 7pt, fill: commit-color.lighten(50%), stroke: none, ..args)
|
||||
#let tree-object(coord, hash, content, ..args) = commit-object(coord, hash, content,
|
||||
width: 2cm, fill: blue.lighten(50%), ..args)
|
||||
#let file-object(coord, hash, name, ..args) = commit-object(coord, hash, name,
|
||||
width: 2cm, fill: gray.lighten(50%), ..args)
|
||||
#import "definicije.typ": *
|
||||
|
||||
#diagram(
|
||||
//debug: 1,
|
||||
|
|
|
|||
130
git-obzornik.typ
130
git-obzornik.typ
|
|
@ -1,10 +1,11 @@
|
|||
#set page("a4", margin: 20mm)
|
||||
#set page("a4", margin: 20mm, numbering: "1")
|
||||
#set heading(numbering: "1.")
|
||||
#show heading: block.with(below: 1.5em)
|
||||
#set text(lang: "sl")
|
||||
#show link: set text(blue)
|
||||
#import "@preview/fletcher:0.5.8" as fletcher: diagram, node, edge
|
||||
#import fletcher.shapes: house, chevron, pill
|
||||
#import "definicije.typ": file-object, tree-object, git-object
|
||||
|
||||
#let note(content) = rect(stroke: none, width: 100%,
|
||||
text(style: "italic",
|
||||
|
|
@ -65,73 +66,119 @@ Ko ustvarimo nov Git repozitorij, Git ustvari direktorij z imenom `.git`, ki vse
|
|||
- posnetke stanja v rezličnih trenutkih s podatki o avtoju, datumu in opisu sprememb
|
||||
- kazalce na posamezne posnetke stanja
|
||||
|
||||
Git repozitorij je vsak direktorij, ki vsebuje poddirektorij `.git` z zgoraj navedenimi podatki.
|
||||
Git repozitorij je vsak direktorij, ki vsebuje poddirektorij `.git` z zgoraj navedenimi podatki.
|
||||
Podrobnosti o tem lahko preberete
|
||||
#link("https://git-scm.com/book/en/v2/Git-Internals-Git-Objects")[poglavju o shrambi objektov] v knjigi o Gitu.
|
||||
|
||||
== Zgoščevalna funkcija
|
||||
|
||||
Git ne shranjuje datotek z običajnimi imeni, ampak za ime uporabi vrednost zgoščevalne funkcije njene vsebine.
|
||||
Git uporablja zgoščevalno funkcijo _SHA-1_.
|
||||
Git uporablja zgoščevalno funkcijo _SHA-1_. Funkcija SHA1 je posebna implementacija zgoščevalne funkcije, ki se uporablja v kriptografiji.
|
||||
|
||||
Naj bo $B$ množica vseh možnih podatkovnih nizov(besedil). Zgoščevalna funkcija _SHA1_ je funkcija
|
||||
$
|
||||
H: B -> {0, 1, dots, 2^(160)-1},
|
||||
$
|
||||
ki vsakemu besedilu $b$ priredi 160-bitno vrednost $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. Kljub temu, da zgoščevalna funkcija $H$
|
||||
ki vsakemu besedilu $b$ priredi 160-bitno _zgoščeno vrednost_ 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.
|
||||
Kljub temu, da zgoščevalna funkcija $H$
|
||||
ni injektivna, je verjetnost, da bi imela dva podatkovna niza isto vrednost $H$ zelo majhna($approx 2^(-159)$). Zato lahko v praksi predpostavimo, da je z vrednostjo $H(b)$ niz $b$ enolično določen.
|
||||
|
||||
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 vrednostjo $H(b)$ enako `8dd6d4bdaeff93016bd49474b54a911131759648` bo shranjena v `.git/objects/8d/d6d4bdaeff93016bd49474b54a911131759648`].
|
||||
Vsebina $b$ je tako vedno dostopna pod imenom $H(b)$. Tako dobimo _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 vrednost zgoščevalne funkcije, kot je njeno ime. Lahko tudi shranimo več različic iste datoteke, saj ima vsaka različica drugačno zgoščevalno vrednost. Zgoščevalna vrednost služi tudi kot kontrola, če je prišlo do kvaritve podatkov, ki so shranjeni v Git repozitoriju.
|
||||
$h_1 h_2 h_3 dots h_(40)$ zapis $H(b)$ v 16-tišlkem sistemu. Datoteka, katere vsebina ima zgoščeno vrednost $H(b)$ enako `8dd6d4bdaeff93016bd49474b54a911131759648` bo shranjena v `.git/objects/8d/d6d4bdaeff93016bd49474b54a911131759648`].
|
||||
Vsebina $b$ je tako vedno dostopna pod imenom $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 vrednost zgoščevalne funkcije, kot je njeno ime. Lahko tudi shranimo več različic iste datoteke, saj ima vsaka različica drugačno zgoščevalno vrednost. Zgoščevalna vrednost služi tudi kot kontrola, če je prišlo do kvaritve podatkov, ki so shranjeni v Git repozitoriju.
|
||||
|
||||
== Merklejeva drevesa
|
||||
== 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 direktorija?
|
||||
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 direktorija? Git za to ustvari nov tip objekta _drevo_ (angl. _tree_), ki hrani preprost seznam imen datotek in naslovov na vsebino datotek v direktoriju. Naslov na vsebino datoteke $b$ je seveda zgoščena vrednost vsebine $H(b)$. Seznam imen datotek in zgoščenih vrednosti je preprosta tekstovna datoteka, za katero lahko izračunamo zgoščeno vrednost. Zgoščena vrednost datotečnega drevesa natanko določa tako imena datotek, kot tudi vsebino datotek, ki so vsebovane v direktoriju. Če se katerakoli datoteka ali ime datoteke v direktoriju spremeni, se bo spremnila tudi
|
||||
njena zgoščena vrednost in posledično zgoščena vrednost za drevo. Poleg posameznih datotek, lahko drevo vsebuje tudi poddrevesa. Tako lahko rekurzivno ustvarimo drevesno podatkovno strukturo, ki zajema direktorij z datotekami in poddirektoriji v poljubni globini.
|
||||
|
||||
#figure(caption: [Vsebina direktorija v Gitu je preprost seznam datotek in poddirektorijev in zgoščenih vrednosti njihove vsebine],
|
||||
raw(align: left, block: true,
|
||||
"
|
||||
100644 blob bcc1382241e267cf790ca6b3afe9fde6dcf1072f bla.txt
|
||||
100644 blob 2ce22b4dc77442103f095503f1205937c1b0fcfc blabla.txt
|
||||
040000 tree 605f479464bebe4f7250ace49bab48e72855f84a podmapa
|
||||
"))
|
||||
|
||||
Poglejmo si primer. Denimo, da imamo v naslednjo strukturo datotek in poddirektorijev
|
||||
#figure(raw(block: true,
|
||||
"
|
||||
├── bla.txt (vsebina: bla)
|
||||
└── mapa
|
||||
├── bla.txt (vsebina: bla)
|
||||
└── blabla.txt (vsebina: blabla)
|
||||
"))
|
||||
|
||||
Git bo shranil naslednje objekte v vsebinsko naslovljivo shrambo:
|
||||
- vsebino datoteke `bla.txt`:
|
||||
#git-object("bcc1382241e267cf790ca6b3afe9fde6dcf1072f", "bla")
|
||||
- vsebino datoteke `blabal.txt`:
|
||||
#git-object("2ce22b4dc77442103f095503f1205937c1b0fcfc", "blabla")
|
||||
- seznam datotek v direktoriju `mapa`:
|
||||
#git-object("e8cc593eddfb9cfdafb4f9c46ab7f5a05ea00b2b",
|
||||
"100644 blob bcc1382241e267cf790ca6b3afe9fde6dcf1072f bla.txt
|
||||
100644 blob 2ce22b4dc77442103f095503f1205937c1b0fcfc blabla.txt")
|
||||
- seznam datotek v korenskem direktoriju:
|
||||
#git-object("1331d77b31e40d6b470706b195f21244bb32cf21",
|
||||
"100644 blob bcc1382241e267cf790ca6b3afe9fde6dcf1072f bla.txt
|
||||
040000 tree e8cc593eddfb9cfdafb4f9c46ab7f5a05ea00b2b mapa")
|
||||
|
||||
Git z uporabo zgoščene vrednosti kot kazalca na vsebino, vsebino direktorija 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 drevo, ampak usmerjen aciklični graf.
|
||||
|
||||
#figure(caption: [Primer datotečnega grafa povezanega z zgoščenimi vrednostmi],
|
||||
diagram(
|
||||
{
|
||||
let bla(coord, ..args) = file-object(coord, "bcc138", ..args)[bla]
|
||||
let blabla(coord, ..args) = file-object(coord, "2ce22b", ..args)[blabla]
|
||||
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`]
|
||||
}
|
||||
))
|
||||
|
||||
Posledično lahko celotno vsebino direktorija opišemo z eno samo zgoščeno vrednostjo. Če spremenimo vsebino, ime ali lokacijo datoteke, bo sprememba vplivala na zgoščeno vrednost spremenjene vsebine in sprememba bo splavala na površje do zgoščene vrednosti za korenski direktorij. Zgoščena vrednost 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.
|
||||
]
|
||||
|
||||
#note[
|
||||
Dostop do objekta je mogoč, če poznamo *zgoščeno vrednost* njegove vsebine. To pomeni, da je referenca na
|
||||
posamezen objekt v Gitu preprosto zgoščena vrednost(angl. hash) vsebine tega objekta. Po drugi strani je
|
||||
vsebina objekta določena z njegovo zgoščeno vrednostjo. To pomeni, da lahko enostavno preverimo verodostojnost vsebine, ki je shranjena v Gitu. Git hrani skladišče objektov v direktoriju `.git/objects`.
|
||||
|
||||
]
|
||||
= Zgodovinski graf sprememb
|
||||
|
||||
V prejšnjem poglavju smo videli, kako Git hrani vsebino direktorija in kako je mogoče do vsebine dostopati če poznamo zgoščeno vrednost korenskega direktorija. Zgodovinsko drevo sprememb je preprosta razširitev omenjene podatkovne strukture.
|
||||
|
||||
== Posnetki stanja
|
||||
|
||||
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. Vsakemu vnosu je prirejena *zgoščena vrednost vnosa*, ki je 40-mestna heksadecimalna vrednost,
|
||||
izračunana s SHA-1, in je natanko določena z vsebino shranjenih datotek in metapodatkov vnosa.
|
||||
Vnose in vsebino datotek hrani Git v #link("https://git-scm.com/book/en/v2/Git-Internals-Git-Objects")[skladišču objektov].
|
||||
Do objektov v skladišču lahko dostopamo, če poznamo njihovo _zgoščeno vrednost_. Objekti, ki jih Git hrani v skladišču
|
||||
so *vnosi*, *posnetki direktorijev* in *posnetki posameznih datotek*.
|
||||
sprememb. Podobno kot objekt tipa _drevo_, je tudi vnos objekt v vsebinsko naslovljivi shrambi, ki je ima določeno *zgoščeno vrednost vnosa*. Zgoščena vrednost vnosa je natanko določena z vsebino shranjenih datotek in metapodatkov vnosa.
|
||||
|
||||
#figure(
|
||||
table(columns: 1, [*zgoščena vrednost*: 8dd6d4bdaeff93016bd49474b54a911131759648],
|
||||
```
|
||||
tree 65c47feec7465e80492620a48206793e078702e0
|
||||
git-object("8dd6d4bdaeff93016bd49474b54a911131759648",
|
||||
"tree 65c47feec7465e80492620a48206793e078702e0
|
||||
parent 16f2994757f1213935b8edb9ae7fee3a8e9ec98d
|
||||
author MV <mv@example.com> 1765235698 +0100
|
||||
committer MV <mv@example.com> 1765235698 +0100
|
||||
|
||||
Dodaj bla
|
||||
```,
|
||||
stroke: 1pt, align: left),
|
||||
"),
|
||||
caption: [Primer vnosa v Gitu. Vnos vsebuje zgoščeno vrednost posnetka direktorija(`tree`), zgoščeno vrednost
|
||||
starševskega vnosa (`parent`) in metapodatke. Tudi sam vnos je natančno določen z zgoščeno vrednostjo.],
|
||||
)
|
||||
Posnetki direktorijev so v Gitu posebne vrste objekti tipa `tree`. Vsebujejo zgoščene vrednosti in metapodatke o
|
||||
datotekah in direktorijih, ki jih vsebuje.
|
||||
#figure(table(columns: 1, stroke:1pt, [*zgoščena vrednost*: `d934342ca420dd0d9828782c7103103f2922d2a6`],
|
||||
```
|
||||
100644 blob 76018072e09c5d31c8c6e3113b8aa0fe625195ca bar.txt
|
||||
100644 blob ba0e162e1c47469e3fe4b393a8bf8c569f302116 foo.txt
|
||||
040000 tree 3b8bfca88b2cc4127ce5909eb3a7395e8b5f2b6a podmapa
|
||||
```
|
||||
),
|
||||
caption: [Primer posnetka direktorija v Gitu (objekt tipa `tree`). Posnetek vsebuje zgoščene vrednosti datotek in direktorija, ki jih vsebuje. Uporaba zgoščenih vrednosti natančno določa vsebino posnetka direktorija.])
|
||||
#note[
|
||||
Skladišča objektov v Gitu je
|
||||
#link("https://en.wikipedia.org/wiki/Content-addressable_storage")[skladišče vsebinsko naslovljivih objektov].
|
||||
Dostop do objekta je mogoč, če poznamo *zgoščeno vrednost* njegove vsebine. To pomeni, da je referenca na
|
||||
posamezen objekt v Gitu preprosto zgoščena vrednost(angl. hash) vsebine tega objekta. Po drugi strani je
|
||||
vsebina objekta določena z njegovo zgoščeno vrednostjo. To pomeni, da lahko enostavno preverimo verodostojnost vsebine, ki je shranjena v Gitu. Git hrani skladišče objektov v direktoriju `.git/objects`.
|
||||
]
|
||||
)
|
||||
|
||||
= Zgodovinski graf sprememb
|
||||
Posamezni vnosi so povezani v *usmerjen acikličen graf (DAG)*, ki predstavlja zgodovino sprememb.
|
||||
Vsak *vnos* je *vozlišče* v grafu. Vsak vnos izhaja iz enega ali več starševskih vnosov. Izjema je prvi vnos.
|
||||
Vsak vnos je povezan s točno določenim posnetekom vsebine korenskega datotečnega drevesa, ki ga identificira zgoščena vrednost. Poleg tega so posamezni vnosi so povezani v *usmerjen acikličen graf (DAG)*, ki predstavlja zgodovino sprememb. Vsak *vnos* je *vozlišče* v grafu. Vsak vnos izhaja iz enega ali več starševskih vnosov. Izjema je prvi vnos.
|
||||
*Povezave* v grafu povezujejo vnose z njihovimi starši.
|
||||
|
||||
#figure(
|
||||
|
|
@ -159,6 +206,8 @@ Vsak *vnos* je *vozlišče* v grafu. Vsak vnos izhaja iz enega ali več staršev
|
|||
caption: [Vnosi v Gitu kot usmerjen graf. Vsak vnos(razen prvega) ima povezavo na vnose iz katerih izhaja.]
|
||||
)
|
||||
|
||||
|
||||
|
||||
= Kazalci: veje in značke
|
||||
|
||||
Poleg objektov kot so _vnosi_, _posnetki direktorijev_ in _posnetki datotek_ pozna git še reference. Reference so kazalci z določenim imenom na posamezen vnos.
|
||||
|
|
@ -268,4 +317,5 @@ Opis dela z Gitom presega namen tega dokumenta. Zato vas raje preusmerimo na ura
|
|||
Pri pripravi dokumenta sem uporabil Gemini 3. Vse odgovore sem preveril in uredil po svoje.
|
||||
|
||||
Sledi še skica, ki povzame vse komponente Git repozitorija.
|
||||
#set page(numbering: none)
|
||||
#include "git-figure.typ"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue