Zamenjaj zgoščeno vrednost z zgostitvijo
This commit is contained in:
parent
aec037c0dd
commit
9f6565cf08
1 changed files with 33 additions and 27 deletions
|
|
@ -24,8 +24,12 @@ Martin Vuk
|
|||
#v(2em)
|
||||
|
||||
#abstract[
|
||||
Git je program, ki omogoča vodenje zgodovine različic datotek v neki mapi(direktoriju). V glavnem se uporablja za upravljanje z izvorno kodo pri razvoju računalniških programov. Mnogi med nami pa ga uporabljajo tudi pri pisanju besedil v _LaTeX_-u. Poleg tega, da Git hrani zgodovino sprememb, tudi omogoča da več ljudi hkrati sodeluje pri urejanju istih datotek.
|
||||
Ogledali si bomo, kako Git deluje. Opisali bomo, kako Git uporabi _zgoščevalne funkcije_, _Merklejeva drevesa_ in _usmerjene aciklične grafe_, da shrani zgodovino različic in omogoči hkratno urejanje vsebine. Matematični model, ki ga Git uporablja je v resnici zelo preprost in njegovo razumevanje nas lahko reši marsikatere zagate, ki nastane med njegovo uporabo.
|
||||
Git je program, ki omogoča vodenje zgodovine različic datotek v neki mapi(direktoriju). V glavnem se uporablja za upravljanje z izvorno
|
||||
kodo pri razvoju računalniških programov. Mnogi med nami pa ga uporabljajo tudi pri pisanju besedil v _LaTeX_-u. Poleg tega, da Git
|
||||
hrani zgodovino sprememb, tudi omogoča da več ljudi hkrati sodeluje pri urejanju istih datotek.
|
||||
Ogledali si bomo, kako Git deluje. Opisali bomo, kako Git uporabi _zgoščevalne funkcije_, _Merklejeva drevesa_ in
|
||||
_usmerjene aciklične grafe_, da shrani zgodovino različic in omogoči hkratno urejanje vsebine. Matematični model, ki ga Git uporablja
|
||||
je v resnici zelo preprost in njegovo razumevanje nas lahko reši marsikatere zagate, ki nastane med njegovo uporabo.
|
||||
]
|
||||
|
||||
= Kaj je Git?
|
||||
|
|
@ -40,7 +44,9 @@ Za vsako različico hrani Git zapis o avtorju, datumu in opis sprememb, ki so na
|
|||
različico. Vse te imformacije dajejo podroben pregled nad zgodovino sprememb.
|
||||
|
||||
#note[
|
||||
Git in GitHub nista eno in isto. Ljudje pogosto mešajo Git in GitHub. Git je program, ki si ga lahko vsakdo namesti in poganja na svojem računalniku. Program Git je ustvaril Linus Torvalds, da bi lažje upravljal z izvorno kodo za jedro operacijskega sistema Linux. GitHub je javno spletišče, ki je namenjeno skladiščenju Git repozitorijev.]
|
||||
Git in GitHub nista eno in isto. Ljudje pogosto mešajo Git in GitHub. Git je program, ki si ga lahko vsakdo namesti in poganja na
|
||||
svojem računalniku. Program Git je ustvaril Linus Torvalds, da bi lažje upravljal z izvorno kodo za jedro operacijskega sistema Linux.
|
||||
GitHub je javno spletišče, ki je namenjeno skladiščenju Git repozitorijev.]
|
||||
#note[
|
||||
Sisteme, ki omogočajo hranjenje preteklih različic datotek, imenujemo
|
||||
#link("https://en.wikipedia.org/wiki/Version_control")[sistemi za nadzor različic] (angl. version control system (VCS)) ali
|
||||
|
|
@ -62,7 +68,7 @@ V nadaljevanju bomo obravnavali nasledjne teme:
|
|||
= 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, s ki smo jih dodali v repozitorij
|
||||
- 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
|
||||
|
|
@ -73,28 +79,28 @@ Podrobnosti o tem lahko preberete v knjigi Pro Git
|
|||
|
||||
== Zgoščevalna funkcija
|
||||
|
||||
Git ne shranjuje datotek z običajnimi imeni, ampak za ime uporabi vrednost zgoščevalne funkcije njene vsebine.
|
||||
Git ne shranjuje datotek z običajnimi imeni, ampak za ime uporabi vrednost zgoščevalne funkcije njene vsebine. Vrednosti zgoščevalne funkcije vsebine pravimo _zgostitev_ vsebine.
|
||||
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 _zgoščeno vrednost_ besedila $H(b)$. Funkcija $H$, je izbrana tako, da
|
||||
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.
|
||||
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.
|
||||
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 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.
|
||||
$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`].
|
||||
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.
|
||||
|
||||
== 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 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 mapi. Če se katerakoli datoteka ali ime datoteke v mapi 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 mapo z datotekami in podmapami v poljubni globini.
|
||||
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 zgoščenih vrednosti njihove vsebine],
|
||||
#figure(caption: [Vsebina mape v Gitu je preprost seznam datotek in podmap in zgostitev njihove vsebine],
|
||||
raw(align: left, block: true,
|
||||
"
|
||||
100644 blob bcc1382241e267cf790ca6b3afe9fde6dcf1072f bla.txt
|
||||
|
|
@ -125,13 +131,13 @@ Git bo shranil naslednje objekte v vsebinsko naslovljivo shrambo:
|
|||
"100644 blob bcc1382241e267cf790ca6b3afe9fde6dcf1072f bla.txt
|
||||
040000 tree e8cc593eddfb9cfdafb4f9c46ab7f5a05ea00b2b mapa")
|
||||
|
||||
Git z uporabo zgoščene vrednosti 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
|
||||
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.
|
||||
|
||||
#let bla(coord, ..args) = file-object(coord, "bcc138", ..args)[bla]
|
||||
#let blabla(coord, ..args) = file-object(coord, "2ce22b", ..args)[blabla]
|
||||
|
||||
#figure(caption: [Primer datotečnega grafa povezanega z zgoščenimi vrednostmi],
|
||||
#figure(caption: [Primer datotečnega grafa povezanega z zgostitvami],
|
||||
diagram(
|
||||
{
|
||||
bla((-1, 0), name:<bla>)
|
||||
|
|
@ -145,27 +151,27 @@ diagram(
|
|||
}
|
||||
))
|
||||
|
||||
Posledično lahko vsebino celotne mape 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 korensko mapo. Zgoščena vrednost 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.
|
||||
]
|
||||
|
||||
#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 mapi `.git/objects`.
|
||||
Dostop do objekta je mogoč, če poznamo *zgostitev* njegove vsebine. To pomeni, da je referenca na
|
||||
posamezen objekt v Gitu preprosto zgostitev(angl. hash) vsebine tega objekta. Po drugi strani je
|
||||
vsebina objekta določena z njegovo zgostitvijo. To pomeni, da lahko enostavno preverimo verodostojnost vsebine, ki je shranjena v Gitu. Git hrani skladišče objektov v mapi `.git/objects`.
|
||||
|
||||
]
|
||||
= Zgodovinski graf sprememb
|
||||
|
||||
V prejšnjem poglavju smo videli, kako Git hrani vsebino celotne mape in kako je mogoče do vsebine dostopati če poznamo zgoščeno vrednost korenskega mape. Zgodovinsko drevo sprememb je preprosta razširitev omenjene podatkovne strukture.
|
||||
V prejšnjem poglavju smo videli, kako Git hrani vsebino celotne mape in kako je mogoče do vsebine dostopati če poznamo zgostitvijo korenskega mape. 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. 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.
|
||||
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.
|
||||
|
||||
#figure(
|
||||
git-object("8dd6d4bdaeff93016bd49474b54a911131759648",
|
||||
|
|
@ -176,11 +182,11 @@ committer MV <mv@example.com> 1765235698 +0100
|
|||
|
||||
Dodaj bla
|
||||
"),
|
||||
caption: [Primer vnosa v Gitu. Vnos vsebuje zgoščeno vrednost posnetka mape(`tree`), zgoščeno vrednost
|
||||
starševskega vnosa (`parent`) in metapodatke. Tudi sam vnos je natančno določen z zgoščeno vrednostjo.],
|
||||
caption: [Primer vnosa v Gitu. Vnos vsebuje zgostitev posnetka mape(`tree`), zgostitev
|
||||
starševskega vnosa (`parent`) in metapodatke. Tudi sam vnos je natančno določen z zgostitevjo.],
|
||||
)
|
||||
|
||||
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.
|
||||
Vsak vnos je povezan s točno določenim posnetekom vsebine korenskega datotečnega drevesa, ki ga identificira zgostitev. 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(
|
||||
|
|
@ -212,10 +218,10 @@ Git hrani zgodovino sprememb v _vsebinsko naslovljivi shrambi objektov_, ki hran
|
|||
- `blob`: vsebina datotek,
|
||||
- `tree`: vsebina mape,
|
||||
- `commit`: posnetek vsebine v določenem trenutku.
|
||||
Objekti so poevazni v _usmerjen aciklični graf_. Podgraf na vnosih določa zgodovino sprememb. Naslovi objektov so _zgoščene vrednosti_ vsebine objekta, zato je zagotovljena verodostojnost shranjenih podatkov.
|
||||
Objekti so poevazni v _usmerjen aciklični graf_. Podgraf na vnosih določa zgodovino sprememb. Naslovi objektov so _zgostitve_ vsebine objekta, zato je zagotovljena verodostojnost shranjenih podatkov.
|
||||
|
||||
#figure(
|
||||
caption: [Vsebinsko naslovljiva shramba objektov v Gitu. Naslovi so zgoščene vrednosti vsebine. Shramba vsebuje dva vnosa. V prvem vnosu smo dodali dve datoteki `bla.txt` in `blabla.txt`, v drugem vnosu pa smo spremenili le vsebino datotoeke `bla.txt`.],
|
||||
caption: [Vsebinsko naslovljiva shramba objektov v Gitu. Naslovi so zgostitve vsebine. Shramba vsebuje dva vnosa. V prvem vnosu smo dodali dve datoteki `bla.txt` in `blabla.txt`, v drugem vnosu pa smo spremenili le vsebino datotoeke `bla.txt`.],
|
||||
diagram(
|
||||
{
|
||||
node((0, -1))[vsebina (blob)]
|
||||
|
|
@ -327,7 +333,7 @@ Vse te pomene damo vejam ljudje, ki sodelujemo v nekem Git repozitoriju. Za Git
|
|||
Povzemimo sedaj, kaj smo spoznali o podatkovnem modelu Gita.
|
||||
V vsebinsko naslovljivi shrambi hrani Git posnetke stanja celotne mape, ki ga vodimo v repozitoriju skupaj z metapodatki o spremembah. Najpomembnejša pojma sta:
|
||||
- *Vnos* (angl. *commit*) je posnetek trenutnega stanja projekta, shranjen kot vozlišče v zgodovinskem grafu, ki vsebuje posnetek stanja datotek ter metapodatke (avtor, čas, sporočilo).
|
||||
- *Zgoščena vrednost vnosa* (angl. *commit hash*) je 40-mestna heksadecimalna vrednost, izračunana s SHA-1, ki enolično identificira vnos na podlagi vsebine posnetka in metapodatkov.
|
||||
- *zgostitev vnosa* (angl. *commit hash*) je 40-mestna heksadecimalna vrednost, izračunana s SHA-1, ki enolično identificira vnos na podlagi vsebine posnetka in metapodatkov.
|
||||
|
||||
Izven shrambe objektov hrani Git še reference na posamezne vnose. Poznamo dve vrsti referenc:
|
||||
- *Veja* (angl. *branch*) je premična reference, ki kaže na določen vnos v zgodovini in se samodejno premakne naprej, ko dodajamo nove vnose. Veje omogočajo vzporedne razvojne linije ki so med sabo neodvisne.
|
||||
|
|
@ -355,7 +361,7 @@ Ukaz
|
|||
git checkout referenca
|
||||
```
|
||||
spremeni datoteke v delovni kopiji tako, da se ujemajo z vnosom, na katerega kaže referenca. Poleg tega
|
||||
prestavi oznako `HEAD` na isti vnos. Če je referenca veja, jo nastavi, kot aktivno vejo. Če je referenca oznaka ali zgoščena vrednost vnosa, priedmo v stanje brez aktivne veje (angl. _deteached HEAD_).
|
||||
prestavi oznako `HEAD` na isti vnos. Če je referenca veja, jo nastavi, kot aktivno vejo. Če je referenca oznaka ali zgostitev vnosa, priedmo v stanje brez aktivne veje (angl. _deteached HEAD_).
|
||||
|
||||
== Commit
|
||||
Ukaz
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue