diff --git a/git-obzornik.tex b/git-obzornik.tex index a26232e..9e8e003 100644 --- a/git-obzornik.tex +++ b/git-obzornik.tex @@ -28,28 +28,28 @@ \maketitle \begin{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 \emph{zgoščevalne funkcije}, \emph{Merklejeva drevesa} -in \emph{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 \emph{zgoščevalne funkcije}, \emph{Merklejeva drevesa} + in \emph{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. \end{abstract} \section{Kaj je Git?} -\href{https://git-scm.com/}{Git} je kot \textbf{časovni stroj} za -datoteke. Uporabniku omogoča, da vidi \textbf{pretekle različice} -datotek, spreminja datoteke, \textbf{brez skrbi, da bi kaj pokvaril} in -datoteke \textbf{deli z drugimi}. Poleg časovnega stroja je Git -\textbf{razpršeno skladišče datotek}. Omogoča, da datoteke -\textbf{hkrati ureja več uporabnikov} na različnih računalnikih in -kasneje spremembe \textbf{združi}. +\href{https://git-scm.com/}{Git} je kot \emph{časovni stroj} za +datoteke. Uporabniku omogoča, da vidi \emph{pretekle različice} +datotek, spreminja datoteke, brez skrbi, da bi kaj pokvaril in +jih deli z drugimi. Poleg časovnega stroja je Git +tudi \emph{razpršeno skladišče datotek}. Omogoča, da datoteke +hkrati ureja več uporabnikov na različnih računalnikih in +kasneje spremembe združi. Git hrani vsebino mape z datotekami in celotno zgodovino različic datotek iz preteklosti. Za vsako različico hrani Git zapis o avtorju, @@ -60,7 +60,7 @@ sprememb. Sisteme, ki omogočajo hranjenje preteklih različic datotek, imenujemo \href{https://en.wikipedia.org/wiki/Version_control}{sistemi za nadzor različic} (angl. version control system (VCS)) ali \emph{sistemi za -upravljanje z izvorno kodo} (angl. Source Code Management (SCM)). +upravljanje z izvorno kodo} (angl. Source Code Management (SCM)). Poleg nadzora različic Git omogoča hkratno spreminjanje datotek več uporabnikov na različnih računalnikih. Zato je Git \href{https://en.wikipedia.org/wiki/Distributed_version_control}{distribuiran @@ -68,31 +68,31 @@ sistem za nadzor različic} (angl. Distributed Version Control System (DVCS)). \begin{opomba} -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. + Ljudje pogosto mešajo Git in GitHub, ki pa nista eno in isto. + 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. \end{opomba} V nadaljevanju bomo obravnavali nasledjne teme: \begin{itemize} -\item - \emph{Podatkovno skladišče:} Kako Git uporablja - \href{https://sl.wikipedia.org/wiki/Zgo\%C5\%A1\%C4\%8Devalna_funkcija}{zgoščevalno - funkcijo} (angl. hash function)? in - \href{https://en.wikipedia.org/wiki/Merkle_tree}{Merklejeva drevesa} - za hranjenje posnetkov vsebine mape. -\item - \emph{Zgodovina sprememb:} Kako zgodovino predstavimo z - \href{https://en.wikipedia.org/wiki/Directed_acyclic_graph}{usmerjenim - acikličnim grafom}, v katerem so vozlišča različice, povezave pa - povežejo različice z njihovimi neposrednimi predhodniki? -\item - \emph{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? + \item + \emph{Podatkovno skladišče:} Kako Git uporablja + \href{https://sl.wikipedia.org/wiki/Zgo\%C5\%A1\%C4\%8Devalna_funkcija}{zgoščevalno + funkcijo} (angl. hash function)? in + \href{https://en.wikipedia.org/wiki/Merkle_tree}{Merklejeva drevesa} + za hranjenje posnetkov vsebine mape. + \item + \emph{Zgodovina sprememb:} Kako zgodovino predstavimo z + \href{https://en.wikipedia.org/wiki/Directed_acyclic_graph}{usmerjenim + acikličnim grafom}, v katerem so vozlišča različice, povezave pa + povežejo različice z njihovimi neposrednimi predhodniki? + \item + \emph{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? \end{itemize} \section{Podatkovno skladišče} @@ -102,15 +102,15 @@ Ko ustvarimo nov Git repozitorij, Git ustvari podmapo z imenom \texttt{.git} hrani različne stvari: \begin{itemize} -\item - vsebino datotek, ki smo jih dodali v repozitorij, -\item - drevesno strukturo korenske mape, ki jo hranimo v repozitoriju, -\item - posnetke stanja v različnih trenutkih s podatki o avtoju, datumu in - opisu sprememb, -\item - kazalce na posamezne posnetke stanja. + \item + vsebino datotek, ki smo jih dodali v repozitorij, + \item + drevesno strukturo korenske mape, ki jo hranimo v repozitoriju, + \item + posnetke stanja v različnih trenutkih s podatki o avtoju, datumu in + opisu sprememb, + \item + kazalce na posamezne posnetke stanja. \end{itemize} Git repozitorij je vsaka mapa, ki vsebuje podmapo \texttt{.git} z zgoraj @@ -122,49 +122,51 @@ preberete v knjigi Pro Git \cite{chacon_102_nodate}. Git ne shranjuje datotek z običajnimi imeni, ampak za ime uporabi 160 bitno število (40 mestno število v 16-tiškem zapisu), ki ga izračuna iz vsebine datoteke. Git za izračun imena uporabi \emph{zgoščevalno -funkcijo}. Naj bo \(B\) množica vseh možnih podatkovnih nizov(besedil), + funkcijo}. Naj bo \(B\) množica vseh možnih podatkovnih nizov(besedil), \(n\)-bitna zgoščevalna funkcija je funkcija -\[H:B \rightarrow \left\{ 0,1,\ldots,2^{n} - 1 \right\},\] ki vsakemu -besedilu \(b\) priredi \(n\)-bitno vrednost \(H(b)\). Vrednosti +\[ + H:B \rightarrow \left\{ 0,1,\ldots,2^{n} - 1 \right\}, +\] +ki vsakemu besedilu \(b\) priredi \(n\)-bitno vrednost \(H(b)\). Vrednosti zgoščevalne funkcije \(H(b)\) pravimo \emph{zgostitev} vsebine \(b\) (angl. hash). Git hrani datoteke pod imeni, ki so enaka zgostitvi vsebine. Kaj pa če imata dve različni vsebini isto zgostitev? Funkcija \(H\) ni injektivna, saj je množica nizov, bistveno večja od množice zgostitev. To pomeni, da imata lahko dve različni datoteki enako zgostitev. Če se to zgodi, rečemo, da pride do \emph{trka -zgostitve}. V primeru trka zgostitve bi Git shranil le eno datoteko, + zgostitve}. V primeru trka zgostitve bi Git shranil le eno datoteko, za drugo pa bi predpostavil da je že shranjena. Zato je funkcija \(H\) izbrana tako, da sprememba enega samega bita v besedilu \(b \in B\) spremeni vrednost \(H(b)\) in je porazdelitev vrednosti \(H(b)\) čim bližje enakomerni porazdelitvi. To pomeni, da so vse vrednosti \(H(b)\) -približno enako verjetne. Na ta način zmanjšamo verjetnost trka( -glej \hyperref[sec_trk]{{[}sec\_trk{]}}). Verjetnost trka +približno enako verjetne. Na ta način zmanjšamo verjetnost trka +(glej poglavje \ref{sec_trk}). Verjetnost trka je izjemno majhna, zato Git lahko predpostavi, da je niz \(b\) enolično določen z njegovo zgostitvijo \(H(b)\). Git uporablja \(160\) bitno zgoščevalno funkcijo \emph{SHA1}. Funkcija SHA1 je posebna implementacija zgoščevalne funkcije, ki se je uporabljala v kriptografiji\footnote{Leta 2017 so raziskovalci iz CWI - Amsterdam in Google Research našli prvi praktični primer dveh - različnih pdf datotek, ki imata isto SHA1 - zgostitev\cite{stevens_first_2017}. Opisan napad so poimenovali - \emph{SHAttered}. Git je zato z verzijo \texttt{v2.13.0} začel - uporabljati verzijo SHA1, ki je odporna proti napadu \emph{SHAttered}. - Kljub temu razvijalci Gita načrtujejo, da bodo SHA1 postopoma - nadomestili s SHA-256.}. + Amsterdam in Google Research našli prvi praktični primer dveh + različnih pdf datotek, ki imata isto SHA1 + zgostitev\cite{stevens_first_2017}. Opisan napad so poimenovali + \emph{SHAttered}. Git je zato z verzijo \texttt{v2.13.0} začel + uporabljati verzijo SHA1, ki je odporna proti napadu \emph{SHAttered}. + Kljub temu razvijalci Gita načrtujejo, da bodo SHA1 postopoma + nadomestili s $256$ bitno zgoščevalno funkcijo SHA-256.}. Ko datoteko z vsebino \(b\) zabeležimo v Git repozitorij, Git izračuna zgostitev vsebine \(H(b)\) in jo shrani v datoteko z imenom \(H(b)\) v -\texttt{git/objects}\footnote{V resnici Git shrani vsebino v datoteko z - imenom \(h_{3}h_{4}\ldots h_{40}\) v mapi \(h_{1}h_{2}\), kjer je - \(h_{1}h_{2}h_{3}\ldots h_{40}\) zapis \(H(b)\) v 16-tiškem sistemu. - Datoteka, katere vsebina ima zgostitev \(H(b)\) enako - \texttt{8dd6d4bdaeff93016bd49474b54a911131759648} bo shranjena v - \texttt{.git/objects/8d/d6d4bdaeff93016bd49474b54a911131759648}}. +\texttt{.git/objects}\footnote{V resnici Git shrani vsebino v datoteko z +imenom \(h_{3}h_{4}\ldots h_{40}\) v mapi \(h_{1}h_{2}\), kjer je +\(h_{1}h_{2}h_{3}\ldots h_{40}\) zapis \(H(b)\) v 16-tiškem sistemu. +Datoteka, katere vsebina ima zgostitev \(H(b)\) enako +\texttt{8dd6d4bdaeff93016bd49474b54a911131759648} bo shranjena v +\texttt{.git/objects/8d/d6d4bdaeff93016bd49474b54a911131759648}}. Vsebina \(b\) je tako vedno dostopna pod imenom, ki je enako njeni zgostitvi \(H(b)\). Tako dobimo \href{https://en.wikipedia.org/wiki/Content-addressable_storage}{vsebinsko -naslovljivo shrambo objektov}, ki je ena od bistvenih značilnosti Gita. + 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 @@ -178,86 +180,88 @@ in njihovih prejšnjih različic. A kako ohranimo informacijo o imenu datotek in drevesni strukturi mape? Git za to ustvari nov tip objekta \emph{drevo} (angl. \emph{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. +je seveda zgostitev vsebine \(H(b)\). +\begin{figure}[h] + \centering + \begin{Verbatim}[frame=single] +100644 blob 33476f4951afc28d5ac2dc0d42d82f17ac817de2 bla.txt +100644 blob 2ce22b4dc77442103f095503f1205937c1b0fcfc blabla.txt +040000 tree ae247f2a35aadade5863aec2475cf13020304b06 podmapa + \end{Verbatim} + \caption{Vsebina mape v Gitu je preprost seznam datotek in podmap ter + zgostitev njihove vsebine. Številke na začetku določajo dovoljenja za datoteke + po sistemu Posix.} +\end{figure} + +Drevo preprost seznam v tekstovni datoteki, za katerega lahko prav tako 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 +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. -\begin{figure} -\centering -\begin{Verbatim}[frame=single] -100644 blob 33476f4951afc28d5ac2dc0d42d82f17ac817de2 bla.txt -100644 blob 2ce22b4dc77442103f095503f1205937c1b0fcfc blabla.txt -040000 tree ae247f2a35aadade5863aec2475cf13020304b06 podmapa -\end{Verbatim} -\caption{Vsebina mape v Gitu je preprost seznam datotek in podmap ter -zgostitev njihove vsebine} +Poglejmo si primer. Denimo, da imamo v korenski mapi naslednje datoteke in +podmape. + +\begin{figure}[h] + \centering + \begin{Verbatim}[frame=single] + ├── bla.txt (vsebina: bla) + ├── blabla.txt (vsebina: blabla) + └── podmapa + └── bla.txt (vsebina: bla) + \end{Verbatim} + \caption{Struktura datotek in podmap, ki jo bomo hranili v Gitu.} \end{figure} -Poglejmo si primer. Denimo, da imamo v naslednjo strukturo datotek in -podmap - -\begin{figure} -\centering -\begin{Verbatim}[frame=single] -├── bla.txt (vsebina: bla) -├── blabla.txt (vsebina: blabla) -└── podmapa - └── bla.txt (vsebina: bla) -\end{Verbatim} -\caption{Struktura datotek in podmap, ki jo bomo hranili v Gitu.} -\end{figure} -\pagebreak Git bo shranil naslednje objekte v vsebinsko naslovljivo shrambo: \begin{itemize} -\item - vsebino datoteke \texttt{bla.txt} -\begin{Verbatim}[frame=single] + \item + vsebino datoteke \texttt{bla.txt} + \begin{Verbatim}[frame=single] bla -\end{Verbatim} -v \gitobject{bc}{c1382241e267cf790ca6b3afe9fde6dcf1072f} -\item - vsebino datoteke \texttt{blabal.txt} -\begin{Verbatim}[frame=single] + \end{Verbatim} + v \gitobject{bc}{c1382241e267cf790ca6b3afe9fde6dcf1072f} + \item + vsebino datoteke \texttt{blabal.txt} + \begin{Verbatim}[frame=single] blabla -\end{Verbatim} - v \gitobject{2c}{e22b4dc77442103f095503f1205937c1b0fcfc} -\item - seznam datotek v mapi \texttt{podmapa} + \end{Verbatim} + v \gitobject{2c}{e22b4dc77442103f095503f1205937c1b0fcfc} + \item + seznam datotek v mapi \texttt{podmapa} -\begin{Verbatim}[frame=single] + \begin{Verbatim}[frame=single] 100644 blob bcc1382241e267cf790ca6b3afe9fde6dcf1072f bla.txt -\end{Verbatim} - v \gitobject{ae}{247f2a35aadade5863aec2475cf13020304b06} -\item - seznam datotek v korenski mapi -\begin{Verbatim}[frame=single] + \end{Verbatim} + v \gitobject{ae}{247f2a35aadade5863aec2475cf13020304b06} + \item + seznam datotek v korenski mapi + \begin{Verbatim}[frame=single] 100644 blob 33476f4951afc28d5ac2dc0d42d82f17ac817de2 bla.txt -100644 blob 2ce22b4dc77442103f095503f1205937c1b0fcfc blabla.txt -040000 tree ae247f2a35aadade5863aec2475cf13020304b06 podmapa -\end{Verbatim} - v \gitobject{47}{3e0bbfc9de64fdca00e611e5666788ddf664ca} +100644 blob 2ce22b4dc77442103f095503f1205937c1b0fcfc blabla.txt +040000 tree ae247f2a35aadade5863aec2475cf13020304b06 podmapa + \end{Verbatim} + v \gitobject{47}{3e0bbfc9de64fdca00e611e5666788ddf664ca} \end{itemize} Z uporabo zgostitve kot kazalca na vsebino, Git vsebino mape postavi v podatkovno strukturo, ki jo matematično lahko opišemo z \emph{usmerjenim -grafom}. Če je vsebina datotek enaka(npr. \texttt{bla.txt} in + grafom}. Če je vsebina datotek enaka(npr. \texttt{bla.txt} in \texttt{mapa/bla.txt}), Git shrani le eno kopijo, ki je dostopna v -datoteki \linebreak\texttt{.git/objects/bc/c1382241e267cf790ca6b3afe9fde6dcf1072f}. +datoteki z imenom enakim zgostitvi vsebine. Zato datotečno drevo v Gitu ni nujno predstavljeno kot drevo, ampak kot -\emph{usmerjen aciklični graf}. +\emph{usmerjen (aciklični) graf}\footnote{Teoretično bi lahko dosegli, da bi bili v grafu tudi cikli, +a je to zelo malo verjetno in zato to možnost ignoriramo.}. -\begin{figure} -\centering -\includegraphics[width=0.6\linewidth]{slike/file-graph.pdf} -\caption{Primer datotečnega grafa povezanega z zgostitvami. Zaradi -preglednosti bomo v slikah izpisali le prvih 6 znakov zgostitve.} +\begin{figure}[h] + \centering + \includegraphics[width=0.6\linewidth]{slike/file-graph.pdf} + \caption{Primer datotečnega grafa povezanega z zgostitvami. Zaradi + preglednosti bomo v slikah izpisali le prvih 6 znakov zgostitve.} \end{figure} Posledično lahko vsebino celotne mape opišemo z eno samo zgostitvijo. Če @@ -266,22 +270,22 @@ 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. -Opomba\\ -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. +\begin{opomba} + 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 graditve + datotečnega drevesa v Gitu je soroden veriženju blokov, ki se uporablja v + kriptovalutah. +\end{opomba} -Opomba\\ -Dostop do objekta je mogoč, če poznamo \textbf{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 \texttt{.git/objects}. +Ponovimo, kar smo spoznali o Gitu. Git hrani vsebino datotek in datotečno strukturo +v \emph{vsebinsko naslovljivi shrambi} (v mapi \texttt{.git/objects}). +To pomeni, da je referenca na posamezen objekt v Gitu preprosto zgostitev njegove vsebine +in da lahko do določene vsebine dostopamo le, če poznamo njeno zgostitev. Po drugi strani +je vsebina za vse praktične primere določena s svojo zgostitvijo. Tako lahko enostavno +preverimo verodostojnost vsebine, ki je shranjena v Gitu. -\section{Trki zgostitev in rojstnodnevni -paradoks}\label{sec_trk} +\section{Trki zgostitev in rojstnodnevni paradoks}\label{sec_trk} Git hrani datoteke pod imeni, ki so enaka zgostitvi vsebine. Če imata dve datoteki z različno vsebino isto zgostitev, Git shrani le eno @@ -299,16 +303,26 @@ tako da je vsaka izbira enakomerno porazdeljena. Kolikšna je verjetnost \(p(n,h)\), da bosta vsaj dve števili enaki? Verjetnost \(p(n,h)\) izračunamo elementarno z verjetnostjo nasprotnega dogodka: -\[1 - p(n,h) = \frac{h \cdot (h - 1)\cdots(h - n + 1)}{h^{n}} = \prod_{k = 1}^{n - 1}\left( 1 - \frac{k}{h} \right).\] +\[1 - p(n,h) = \frac{h \cdot (h - 1)\cdots(h - n + 1)}{h^{n}} = + \prod_{k = 1}^{n - 1}\left( 1 - \frac{k}{h} \right).\] Če izraz logaritmiramo, dobimo -\[\log(1 - p(n,h)) = \sum_{k = 1}^{n - 1}\log(1 - \frac{k}{h}) < - \sum_{k = 1}^{n - 1}\frac{k}{h} = \frac{- \left( n(n - 1) \right)}{2h}.\]\protect\phantomsection\label{eq_log_ocena}{} +\begin{eqnarray} + \log(1 - p(n,h)) = \sum_{k = 1}^{n - 1}\log(1 - \frac{k}{h}) < + - \sum_{k = 1}^{n - 1}\frac{k}{h} = \frac{- \left( n(n - 1) \right)}{2h}. + \label{eq_log_ocena} +\end{eqnarray} + Res! Logaritem je konveksna funkcija, zato so vrednosti manjše od vrednosti na tangenti \(\log(1 - \frac{k}{h}) = \log(1 - x) < x = \frac{k}{h}\). Od tod izpeljemo oceno za \(p(n,h)\) -\[p(n,h) > 1 - e^{\frac{- \left( n(n - 1) \right)}{2h}} \approx 1 - e^{- \frac{n^{2}}{2h}}.\]\protect\phantomsection\label{eq_ocena}{} +\begin{eqnarray} +p(n,h) > 1 - e^{\frac{-\left( n(n - 1) \right)}{2h}} \approx 1 - e^{-\frac{n^{2}}{2h}}. +\label{eq_ocena} +\end{eqnarray} + Za vrednosti \(1 \ll n \ll h\) je \(1 - e^{- \frac{n^{2}}{2h}}\) tudi dobra aproksimacija za \(p(n,h)\). @@ -317,13 +331,12 @@ trka, moramo rešiti obratno nalogo: največ koliko števil \(n(p,d)\) lahko izberemo, da bo verjetnost pojava dveh enakih števil manjša od \(p \in \lbrack 0,1\rbrack\)? Natančen odgovor na to vprašanje ni tako preprost \cite{brink_probably_2012}. Lahko pa uporabimo oceno -(\hyperref[eq_ocena]{{[}eq\_ocena{]}}) in čez palec ocenimo vrednost -\(n(p,h)\): +(\ref{eq_ocena}) in čez palec ocenimo vrednost \(n(p,h)\): \[\begin{array}{r} - - n^{2} \approx \log(1 - p) \Rightarrow \\ -n(p,h) \approx \sqrt{2h\log(\frac{1}{1 - p})} \approx \sqrt{2h}. -\end{array}\] + - n^{2} \approx \log(1 - p) \Rightarrow \\ + n(p,h) \approx \sqrt{2h\log(\frac{1}{1 - p})} \approx \sqrt{2h}. + \end{array}\] Funkcija \(\sqrt{\log(\frac{1}{1 - p})}\) zelo počasi narašča, ko se \(p\) približuje \(1\), zato jo lahko zanemarimo. Če je zgoščevalna @@ -343,25 +356,25 @@ podatkovne strukture. \section{Posnetki stanja} -Osnovna enota v Gitu je \textbf{vnos} (angl. \textbf{commit}). Vnos je +Osnovna enota v Gitu je \emph{vnos} (angl. \emph{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 \emph{drevo}, je tudi -vnos objekt v vsebinsko naslovljivi shrambi, ki ima določeno -\textbf{zgostitev vnosa}. Zgostitev vnosa je natanko določena z vsebino +vnos objekt v vsebinsko naslovljivi shrambi in ima določeno +\emph{zgostitev vnosa}. Zgostitev vnosa je natanko določena z vsebino shranjenih datotek in metapodatkov vnosa. \begin{table} - \begin{Verbatim}[frame=single] + \begin{Verbatim}[frame=single] tree 65c47feec7465e80492620a48206793e078702e0 parent 16f2994757f1213935b8edb9ae7fee3a8e9ec98d author MV 1765235698 +0100 committer MV 1765235698 +0100 Dodaj bla -\end{Verbatim} -\caption{Vnos v Gitu je shranjen v podatkovno shrambo pod imenom, -ki je zgostitev vsebine vnosa: \gitobject{8d}{d6d4bdaeff93016bd49474b54a911131759648}.} + \end{Verbatim} + \caption{Vnos v Gitu je shranjen v podatkovno shrambo pod imenom, + ki je zgostitev vsebine vnosa: \gitobject{8d}{d6d4bdaeff93016bd49474b54a911131759648}.} \end{table} Vsak vnos je povezan s točno določenim posnetekom vsebine korenskega @@ -373,22 +386,22 @@ prvi vnos. Povezave v grafu povezujejo vnose z njihovimi starši. \begin{figure} -\centering -\includegraphics[width=0.6\linewidth]{slike/commit-history.pdf} -\caption{Vnosi v Gitu kot usmerjen graf. Vsak vnos(razen prvega) ima -povezavo na vnose iz katerih izhaja.} + \centering + \includegraphics[width=0.6\linewidth]{slike/commit-history.pdf} + \caption{Vnosi v Gitu kot usmerjen graf. Vsak vnos(razen prvega) ima + povezavo na vnose iz katerih izhaja.} \end{figure} Git hrani zgodovino sprememb v \emph{vsebinsko naslovljivi shrambi -objektov}, ki hrani tri vrste objektov: + objektov}, ki hrani tri vrste objektov: \begin{itemize} -\item - \texttt{blob}: vsebina datotek, -\item - \texttt{tree}: vsebina mape, -\item - \texttt{commit}: posnetek vsebine v določenem trenutku. + \item + \texttt{blob}: vsebina datotek, + \item + \texttt{tree}: vsebina mape, + \item + \texttt{commit}: posnetek vsebine v določenem trenutku. \end{itemize} Objekti so poevazni v \emph{usmerjen aciklični graf}. Podgraf na vnosih @@ -396,13 +409,13 @@ določa zgodovino sprememb. Naslovi objektov so \emph{zgostitve} vsebine objekta, zato je zagotovljena verodostojnost shranjenih podatkov. \begin{figure} -\centering -\includegraphics[width=0.6\linewidth]{slike/object-storage.pdf} -\caption{Vsebinsko naslovljiva shramba objektov v Gitu. Naslovi so -zgostitve vsebine. Shramba vsebuje dva vnosa. V prvem vnosu smo dodali -dve datoteki \protect\texttt{bla.txt} in \protect\texttt{blabla.txt}, v -drugem vnosu pa smo spremenili le vsebino datotoeke -\protect\texttt{bla.txt}.} + \centering + \includegraphics[width=0.6\linewidth]{slike/object-storage.pdf} + \caption{Vsebinsko naslovljiva shramba objektov v Gitu. Naslovi so + zgostitve vsebine. Shramba vsebuje dva vnosa. V prvem vnosu smo dodali + dve datoteki \protect\texttt{bla.txt} in \protect\texttt{blabla.txt}, v + drugem vnosu pa smo spremenili le vsebino datotoeke + \protect\texttt{bla.txt}.} \end{figure} \section{Kazalci: veje in značke} @@ -412,10 +425,10 @@ Poleg objektov kot so \emph{vnosi}, \emph{posnetki map} in določenim imenom na posamezen vnos. \begin{figure} -\centering -\includegraphics[width=0.6\linewidth]{slike/branches-tags.pdf} -\caption{Veja (angl. branch) ali značka(angl. tag) je preprost kazalec -na posamezen vnos(angl. commit).} + \centering + \includegraphics[width=0.6\linewidth]{slike/branches-tags.pdf} + \caption{Veja (angl. branch) ali značka(angl. tag) je preprost kazalec + na posamezen vnos(angl. commit).} \end{figure} Referenc git ne hrani v skladišču objektov, temveč posebej v mapi @@ -430,22 +443,20 @@ trenutno aktivna veja premakne na novo ustvarjeni vnos. ne premika več, ko jo enkrat ustvarimo. \begin{figure} -\centering -\includegraphics[width=0.6\linewidth]{slike/branch-move.pdf} -\caption{Ko ustvarimo nov vnos, se aktivna veja \protect\texttt{main} -premakne naprej, značka \protect\texttt{v-1.0} pa ostane tam, kjer je -bila.} + \centering + \includegraphics[width=0.6\linewidth]{slike/branch-move.pdf} + \caption{Ko ustvarimo nov vnos, se aktivna veja \protect\texttt{main} + premakne naprej, značka \protect\texttt{v-1.0} pa ostane tam, kjer je + bila.} \end{figure} -Opomba\\ Veje in značke nimajo v Gitu nobenega posebnega pomena, razen tega, da so reference na vnose. Pomen posamenznih vej je stvar dogovora med uporabniki. Tako se pogosto uporablja različne veje za različne namene: \texttt{main} ali \texttt{master} je navadno glavna veja razvoja, veje z imeni \texttt{stable}, \texttt{production}, \texttt{development} in podobno označujejo različne stopnje razvoja programske opreme, veje s -predpono \texttt{feature-} označujejo razvoj novih funkcionalnosti. - +predpono \texttt{feature-*} označujejo razvoj novih funkcionalnosti. Vse te pomene damo vejam ljudje, ki sodelujemo v nekem Git repozitoriju. Za Git so vse veje in značke zgolj preprosti kazalci na določen vnos. @@ -454,10 +465,10 @@ Vnos, na katerega kaže \emph{HEAD} bo starševski vnos naslednjeg vnosa, ki ga bomo dodali. \begin{figure} -\centering -\includegraphics[width=0.6\linewidth]{slike/head-index.pdf} -\caption{\textbf{HEAD} je referenca na trenutno aktiven vnos. -\emph{Index} vsebuje spremembe, ki bodo zabeležene v naslednjem vnosu.} + \centering + \includegraphics[width=0.6\linewidth]{slike/head-index.pdf} + \caption{\textbf{HEAD} je referenca na trenutno aktiven vnos. + \emph{Index} vsebuje spremembe, ki bodo zabeležene v naslednjem vnosu.} \end{figure} \section{Povzetek} @@ -468,51 +479,50 @@ v repozitoriju skupaj z metapodatki o spremembah. Najpomembnejša pojma sta: \begin{itemize} -\item - \textbf{Vnos} (angl. \textbf{commit}) je posnetek trenutnega stanja - projekta, shranjen kot vozlišče v zgodovinskem grafu, ki vsebuje - posnetek stanja datotek ter metapodatke (avtor, čas, sporočilo). -\item - \textbf{zgostitev vnosa} (angl. \textbf{commit hash}) je 40-mestna - heksadecimalna vrednost, izračunana s SHA-1, ki enolično identificira - vnos na podlagi vsebine posnetka in metapodatkov. + \item + \textbf{Vnos} (angl. \textbf{commit}) je posnetek trenutnega stanja + projekta, shranjen kot vozlišče v zgodovinskem grafu, ki vsebuje + posnetek stanja datotek ter metapodatke (avtor, čas, sporočilo). + \item + \textbf{zgostitev vnosa} (angl. \textbf{commit hash}) je 40-mestna + heksadecimalna vrednost, izračunana s SHA1, ki enolično identificira + vnos na podlagi vsebine posnetka in metapodatkov. \end{itemize} Izven shrambe objektov hrani Git še reference na posamezne vnose. Poznamo dve vrsti referenc: \begin{itemize} -\item - \textbf{Veja} (angl. \textbf{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. -\item - \textbf{Oznaka} (angl. \textbf{tag}) je statična referenca, ki trajno - kaže na določen vnos. Za razliko od veje se oznaka, nikoli ne premika - samodejno, zato se uporablja predvsem za označevanje pomembnih točk v - zgodovini, kot so izdaje ali stabilne verzije. -\item - \textbf{HEAD} je posebna oznaka, ki kaže na trenutno aktiven vnos v - delovni kopiji. + \item + \textbf{Veja} (angl. \textbf{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. + \item + \textbf{Oznaka} (angl. \textbf{tag}) je statična referenca, ki trajno + kaže na določen vnos. Za razliko od veje se oznaka, nikoli ne premika + samodejno, zato se uporablja predvsem za označevanje pomembnih točk v + zgodovini, kot so izdaje ali stabilne verzije. + \item + \textbf{HEAD} je posebna oznaka, ki kaže na trenutno aktiven vnos v + delovni kopiji. \end{itemize} Omenimo še dva pojma, ki jih uporabljamo pri delu z Gitom: \begin{itemize} -\item - \textbf{Delovna kopija} (angl. \textbf{workout copy}) je mapa v kateri - urejamo datoteke, ki jih nato vnesemo v Git. V delovni kopiji imajo na - začetku datoteke isto vsebino kot je vsebina trenutno aktivnega vnosa - (\texttt{HEAD}). Spremembe, ki jih naaredimo na delovni kopiji lahko - zabeležimo v nov vnos. -\item - \textbf{Oddaljen repozitorij} (angl. \textbf{remote}) je povezava(url) - na isti repozitorij na drugem računalniku(ponavadi strežniku), s - katerim lahko izmenjujemo vsebino. + \item + \textbf{Delovna kopija} (angl. \textbf{workout copy}) je mapa v kateri + urejamo datoteke, ki jih nato vnesemo v Git. V delovni kopiji imajo na + začetku datoteke isto vsebino kot je vsebina trenutno aktivnega vnosa + (\texttt{HEAD}). Spremembe, ki jih naaredimo na delovni kopiji lahko + zabeležimo v nov vnos. + \item + \textbf{Oddaljen repozitorij} (angl. \textbf{remote}) je povezava(url) + na isti repozitorij na drugem računalniku(ponavadi strežniku), s + katerim lahko izmenjujemo vsebino. \end{itemize} -Opomba\\ Gitov podatkovni model omogoča, da je večina operacij v Gitu obrnljivih. To pomeni, da lahko repozitorij povrnemo v prejšnje stanje. Običajne operacije le dodajajo nove vnose in starih ne brišejo. Prav tako se v @@ -532,8 +542,6 @@ Ko smo opremljeni z razumevanjem podatkovnega modela Gita, razložimo kaj pomenijo posamezne operacije, ki jih Git omogoča. Ukazov ne bom prevajal, ampak jih bom navedel kot jih pozna program \texttt{git}. -\section{Checkout} - Ukaz \begin{verbatim} @@ -541,13 +549,11 @@ git checkout referenca \end{verbatim} spremeni datoteke v delovni kopiji tako, da se ujemajo z vnosom, na -katerega kaže referenca. Poleg tega prestavi oznako \texttt{HEAD} na +katerega kaže \texttt{referenca}. Poleg tega prestavi oznako \texttt{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. \emph{deteached HEAD}). -\section{Commit} - Ukaz \begin{verbatim} @@ -559,8 +565,6 @@ index). V zgodovinskem grafu ustvari novo vozlišče, ki je povezano s prejšnjim vnosom. Poleg tega prestavi aktivno vejo in oznako \texttt{HEAD} na novo ustvarjeni vnos. -\section{Add} - Ukaz \begin{verbatim} @@ -572,8 +576,6 @@ spreminja zgodovinskega grafa, pač pa doda novo vsebino in datotečna drevesa, ki vsebujejo spremembe v shrambo objektov. Vsebina čakalnice bo zabeležena v naslednjem vnosu. -\section{Pull} - Ukaz \begin{verbatim} @@ -587,8 +589,6 @@ oddaljene, se lokalna veja enostavno prestavi, da kaže na isti vnos, kot oddaljena veja. V nasprotnem primeru, mora uporabnik posredovati in razrešiti morebitne konflikte. -\section{Push} - Ukaz \begin{verbatim} @@ -599,8 +599,6 @@ potisne novo vsebino na oddaljeni repozitorij. Push deluje obratno kot \texttt{pull}. Ukaz je uspešno izveden le, če je oddaljena veja prednica lokalne veje in ni konflikotov. -\section{Fetch} - Ukaz \begin{verbatim} @@ -612,19 +610,16 @@ Pri tem ne more priti do konfliktov, ker git preprosto doda nove objekte v shrambo in obstoječih objektov nikakor ne spreminja. Oddaljenim vejam in oznakam preprosto doda predpono z imenom oddaljenega repozitorija. -\section{Reset} - Ukaz \begin{verbatim} git reset referenca \end{verbatim} -spremeni kam kaže trenutno izbrana veja. Ukaz ne spremeni zgodovinskega +spremeni kam kaže trenutno izbrana veja. Trenutno izbrano vejo prestavi na isti vnos, na +katerega kaže dana \texttt{referenca}. Ukaz ne spremeni zgodovinskega drevesa, ampak le to, na kateri vnos kaže trenutno izbrana veja. -\section{Merge} - Ukaz \begin{verbatim} @@ -636,8 +631,6 @@ referenco). Nov vnos ima dva starša: vnos na katerega kaže trenutna veja in vnos, na katerega kaže referenca. Če pride do konfliktov, jih mora uporabnik sam razrešiti, preden se ustvari nov vnos. -\section{Rebase} - Ukaz \begin{verbatim} @@ -651,25 +644,25 @@ nove vnose in prestavljajo reference. Zato je večina ukazov v Gitu varna, v smislu, da jih lahko kasneje prekličemo in pridemo nazaj na prejšnje stanje. Ukaz \texttt{rebase} pa spremeni zgodovino in ga ne moremo preklicati, saj trenutne vnose nadomesti z novimi in stare vnose -pobriše\footnote{Obstaja enostaven način, da tudi \texttt{rebase} lahko - prekličemo. Na zadnji vnos, ki ga želimo prestaviti preprosto - postavimo novo referenco(vejo ali oznako). To povzroči, da se stari - vnosi ne pobrišejo tudi, ko se izvede ukaz \texttt{rebase}.}. +pobriše\footnote{Obstaja enostaven način, kako \texttt{rebase} izvedemo tako, da ga lahko + kasneje prekličemo. Na vnos, ki ga želimo prestaviti z \texttt{rebase}, preprosto + postavimo novo vejo ali oznako. To povzroči, da se stari + vnosi ne pobrišejo, ko se izvede ukaz \texttt{rebase}.}. \section{Zaključek} -Spoznali smo, kako deluje Git in s katere matematičnime pojme uporablja -za model. Opis dela z Gitom presega namen tega dokumenta, zato vas raje -usmerim na uradno dokumentacijo: +Spoznali smo, kako deluje Git in s katerimi matematičnimi pojmi lahko opišemo njegov podatkovni model. +Upam, da boste s tem znanjem bolj samozavestno uporabljali Git. Opis dela z Gitom presega namen tega +dokumenta, zato vas raje usmerim na uradno dokumentacijo: {\url{https://git-scm.com/cheat-sheet}} Pri pisanju tega članka sem sevada uporabljal Git. V \href{https://git.fri.uni-lj.si/martin.vuk/git-intro}{javno dostopnem -repozitoriju} \cite{vuk_git-intro_nodate} si lahko ogledate celotno + repozitoriju} \cite{vuk_git-intro_nodate} si lahko ogledate celotno zgodovino nastajanja tega članka. -Pri pripravi dokumenta sem uporabil Gemini 3. Vse odgovore sem preveril +Pri pripravi dokumenta sem uporabil Gemini 3, a sem vse odgovore njegove odgovore skrbno preveril in uredil po svoje. \bibliographystyle{plainurl}