-
Notifications
You must be signed in to change notification settings - Fork 30
/
verzioniranje-koda.tex
executable file
·138 lines (90 loc) · 8.71 KB
/
verzioniranje-koda.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
\chapter*{Verzioniranje koda i osnovni pojmovi}
\addcontentsline{toc}{chapter}{Verzioniranje koda i osnovni pojmovi}
\section*{Što je verzioniranje koda?}
\addcontentsline{toc}{section}{Što je verzioniranje koda?}
S problemom verzioniranja koda sreli ste se kad ste prvi put napisali program koji rješava neki konkretan problem.
Bilo da je to neka jednostavna web aplikacija, CMS\footnote{Content Management System}, komandnolinijski pomoćni programčić ili kompleksni ERP\footnote{Enterprise Resource Planning}.
Svaka aplikacija koja ima \textbf{stvarnog} korisnika kojemu rješava neki \textbf{stvarni} problem ima i \textbf{korisničke zahtjeve}.
Taj korisnik možemo biti mi sami, može biti neko hipotetsko tržište (kojemu planiramo prodati rješenje) ili može biti naručitelj.
Korisničke zahtjeve ne možemo nikad točno predvidjeti u trenutku kad krenemo pisati program.
Možemo satima, danima i mjesecima sjediti s budućim korisnicima i planirati što će sve naša aplikacija imati, ali kad korisnik sjedne pred prvu verziju aplikacije, čak i ako je pisana točno prema njegovim specifikacijama, on će naći nešto što ne valja.
Radi li se o nekoj maloj izmjeni, možda ćemo je napraviti na licu mjesta.
Možda ćemo trebati otići kući, potrošiti nekoliko dana i napraviti \textbf{novu verziju}.
Desit će se, na primjer, da korisniku damo na testiranje verziju \texttt{1.0}.
On će istestirati i, naravno, naći nekoliko sitnih stvari koje treba ispraviti.
Otići ćemo kući, ispraviti ih, napraviti verziju \texttt{1.1} s kojom će klijent biti zadovoljan.
Nekoliko dana kasnije, s malo više iskustva u radu s aplikacijom, on zaključuje kako sad ima \textbf{bolju} ideju kako je trebalo ispraviti verziju \textbf{1.0}.
Sad, dakle, treba "baciti u smeće" posao koji smo radili za \texttt{1.1}, vratiti se na \texttt{1.0} i od nje napraviti npr. \texttt{1.1b}.
Grafički bi to izgledalo ovako nekako:
\input{graphs/primjer_s_klijentom}
U trenutku kad je korisnik odlučio da mu trenutna verzija ne odgovara trebamo se vratiti korak unazad (u povijest projekta) i započeti novu verziju, odnosno novu \textbf{granu projekta} te nastaviti projekt s tom izmjenom.
I to je samo jedan od mnogih mogućih scenarija kakvi se događaju u programerskom životu.
\section*{Linearno verzioniranje koda}
\addcontentsline{toc}{section}{Linearno verzioniranje koda}
Linearni pristup verzioniranju koda se najbolje može opisati sljedećom ilustracijom:
\input{graphs/linearni_model}
To je idealna situacija u kojoj točno unaprijed znamo kako aplikacija treba izgledati.
Započnemo projekt s početnim stanjem \emph a, pa napravimo izmjene \emph b, \emph c, \dots sve dok ne zaključimo da smo spremni izdati prvu verziju za javnost i proglasimo to verzijom \texttt{1.0}.
Postoje mnoge varijacije ovog linearnog modela, jedna česta je:
\input{graphs/linearni_model_2}
Ona je česta u situacijama kad nemamo kontrolu nad time koja je točno verzija programa instalirana kod klijenta.
S web aplikacijama to nije problem jer vi jednostavno možete aplikaciju prebaciti na server i odmah svi klijenti koriste novu verziju.
Međutim, ako je vaš program klijentima "spržen" na CD i takav poslan klijentu može se dogoditi da jedan ima instaliranu verziju \texttt{1.0}, a drugi \texttt{2.0}.
I sad, što ako klijent koji je zadovoljan sa starijom verzijom programa otkrije \textbf{bug} i zbog nekog razloga ne želi prijeći na novu verziju?
U tom slučaju morate imati neki mehanizam kako da se privremeno vratite na staru verziju, ispravite problem, izdate "novu verziju stare verzije", pošaljete je klijentu i nakon toga se vratite na prijašnje stanje te tamo nastavite gdje ste stali.
\section*{Grafovi, grananje i spajanje grana}
\addcontentsline{toc}{section}{Grafovi, grananje i spajanje grana}
Prije nego nastavimo s gitom, nekoliko riječi o grafovima.
U ovoj ćete knjižici vidjeti puno grafova kao što su u primjerima s linearnim verzioniranjem koda.
Zato ćemo se na trenutak zadržati na jednom takvom grafu:
\input{graphs/primjer_s_granama_i_spajanjima}
Svaka točka grafa je stanje projekta.
Projekt s gornjim grafom započeo je s nekim početnim stanjem \emph a.
Programer je napravio nekoliko izmjena i \textbf{snimio} novo stanje \emph b, zatim \emph c, \dots i tako sve do $h$, $w$ i $4$.
Primijetite da je ovakav graf stanje povijesti projekta, ali iz njega ne možemo zaključiti kojim su redom čvorovi nastajali.
Neke stvari možemo zaključiti: vidi se, na primjer, da je $d$ nastao nakon $c$, $e$ nakon $d$ ili $z$ nakon $y$.
Ne znamo je li prije nastao $c$ ili $x$.
Ili, čvor \emph 1 je sigurno nastao nakon $g$, no iz grafa se ne vidi je li nastao prije $x$ ili nakon $x$.
Evo jedan način kako je navedeni graf mogao nastati:
\input{graphs/primjer_s_granama_i_spajanjima_1}
Programer je započeo aplikaciju, snimio stanje \emph a, \emph b i \emph c i tada se sjetio da ima neki problem kojeg može riješiti na dva načina, vratio se na \emph b i napravio novu granu. Tamo je napravio izmjene $x$ i $y$:
\input{graphs/primjer_s_granama_i_spajanjima_2}
Zatim se sjetio izmjene koju je mogao napraviti u \emph{originalnoj} verziji, vratio se tamo i dodao \emph d:
\input{graphs/primjer_s_granama_i_spajanjima_3}
Nakon toga se vratio na svoj prvotni eksperiment i odlučio da bi bilo dobro tamo imati izmjene koje je napravio u \emph c i \emph d.
Tada je \emph{preuzeo} te izmjene u svoju granu:
\input{graphs/primjer_s_granama_i_spajanjima_4}
Na eksperimentalnoj je grani napravio još jednu izmjenu \emph q.
Tada je odlučio privremeno napustiti taj eksperiment i posvetiti se izmjenama koje mora napraviti u glavnoj grani.
Vratio se na originalnu granu i tamo napredovao s \emph e i \emph f.
\input{graphs/primjer_s_granama_i_spajanjima_5}
Sjetio se da bi mu sve izmjene iz eksperimentalne grane odgovarale u originalnoj, \emph{preuzeo} ih u početnu granu:
\input{graphs/primjer_s_granama_i_spajanjima_6}
\dots{}zatim je nastavio i napravio još jednu eksperimentalnu granu (\emph 1, \emph 2, \emph 3, \dots).
Na onoj je prvoj eksperimentalnoj grani dodao još i $w$ i tako dalje\dots
\input{graphs/primjer_s_granama_i_spajanjima}
Na svim će grafovima glavna grana biti ona najdonja.
Uočite, na primjer, da izmjena \emph w nije nikad završila u glavnoj grani.
Jedna od velikih prednosti gita je lakoća stvaranja novih grana i preuzimanja izmjena iz jedne u drugu granu.
Tako je programerima jednostavno u nekom trenutku razmišljati i postupiti na sljedeći način: \emph{"Ovaj problem bih mogao riješiti na dva različita načina. Pokušat ću i jedan i drugi, i onda vidjeti koji mi bolje ide."}. Za svaku će verziju napraviti posebnu granu i napredovati prema osjećaju.
Druga velika prednost čestog grananja u programima je kad se dodaje neka nova funkcionalnost koja zahtijeva puno izmjena, a ne želimo te izmjene odmah stavljati u glavnu granu programa:
\input{graphs/primjer_s_dugotrajnom_granom}
Trebamo pripaziti da redovito izmjene iz glavne grane programa preuzimamo u sporednu tako da razlike u kodu ne budu prevelike.
Te su izmjene na grafu označene sivim strelicama.
Kad završimo novu funkcionalnost, u glavnu granu treba preuzeti sve izmjene iz sporedne (crvena strelica). Na taj ćemo način često imati ne samo dvije grane (glavnu i sporednu) nego nekoliko njih.
Imati ćemo posebne grane za različite nove funkcionalnosti, posebne grane za eksperimente, posebne grane u kojima ćemo isprobavati izmjene koje su napravili drugi programeri, posebne grane za ispravljanje pojedinih \emph{bug}ova, \dots
Osnovna ideja ove knjižice \textbf{nije} učiti vas kako je najbolje organizirati povijest projekta, odnosno kako granati te kad i kako preuzimati izmjene iz pojedinih grana.
Osnovna ideja je naučiti vas \textbf{kako} to napraviti s gitom.
Nakon savladanog \textbf{kako} prirodno dolazi i intuicija o tome \textbf{kako ispravno}.
\section*{Mit o timu i sustavima za verzioniranje}
\addcontentsline{toc}{section}{Mit o timu i sustavima za verzioniranje}
Prije nego nastavimo, htio bih srušiti jedan mit.
Taj mit glasi ovako nekako: "\emph{Sustavi za verzioniranje koda potrebni su kad na nekom projektu radi više ljudi}".
Vjerujte mi, ovo nije istina.
\textbf{Posebno} to nije istina za git i druge distribuirane sustave koji su namijenjeni čestom grananju.
Kad o projektu počnete razmišljati kao o jednom usmjerenom grafu i posebne stvari radite u posebnim granama to značajno olakšava samo razmišljanje o razvoju.
Ako imate jedan direktorij s cijelim projektom i u kodu imate paralelno izmjene od tri različite stvari koje radite istovremeno, onda imate problem.
Nemojte pročitati knjigu i reći "\emph{Nisam baš uvjeren}".
Probajte git\footnote{Ako vam se git i ne svidi, probajte barem mercurial.} na nekoliko tjedana.
% \section*{}
% \addcontentsline{toc}{section}{}