Kolumna Igora Rumihe: Mercurial DVCS (dio drugi)

Kolumna Igora Rumihe: Mercurial DVCS (dio drugi)

Nekoliko osnovnih naredbi Mercurial version control sustava opisao sam ukratko prošli mjesec.

Naravno, potpuni popis naredbi je mnogo veći i pokriva svu funkcionalnost koju bi korisnik jednog version control sustava mogao poželjeti. Samo zbog svojstava uobičajenih za svaki drugi VCS Mercurial vjerojatno nebi bio nikome zanimljiv za prelazak. Osnovna razlika zbog koje biste poželjeli prijeći na Mercurial (ili neki drugi, sličan VCS) jesu njegova distribuirana svojstva.

1.1 Distribuirani VCS

Klasični, centralizirani VCS ima jednostavnu strukturu: jedan, centralni server na kojeg se spajaju svi sudionici u projektu. Tipično postoji podrška za "grananje" koda, najčešće grane predstavljaju fiksirane, stabilne verzije koda a uz njih postoji i glavna verzija koda - nju se često naziva "master" ili "trunk" (deblo), u koju se pohranjuju najnovije izmjene i dodaci u kodu, a iz koje onda prema nekakvom prije dogovorenom pravilu nastaju stabilne grane. Svaki "commit" odmah se sinkronizira s glavnim serverom i kad ostali sudionici u projektu pokrenu naredbu "update" odmah će vidjeti najnovije izmjene u njihovim kopijama repozitorija.

Mercurial radi drugačije: postoji jedan repozitorij kojeg možemo nazvati izvornim repozitorijem, a uz njega postoji jedan ili više kloniranih repozitorija. Klonovi ne moraju svi poticati direktno iz izvornog repozitorija, moguće je stvarati klonove klonova. Svaki repozitorij ima u sebi zapisano koji repozitorij je njegov "izvor" ili "roditelj" tako da je moguće stvarati složene hijerarhije repozitorija. Iako Mercurial ima podršku za više grana unutar jednog repozitorija, tipična upotreba kloniranih repozitorija je upravo grananje koda. Sudionici u projektu rade na svojim privatnim kloniranim repozitorijima i kad pokrenu naredbu "commit" izmjene se spremaju samo u njihovim lokalnim repozitorijima. Kad se pojavi potreba za sinkroniziranjem naredbama "push" i "pull" postiže se razmjena podataka s repozitorijem koji je njihovom radnom repozitoriju direktni roditelj.

Kako organizirati hijerarhiju repozitorija ovisi o dogovoru sudionika projekta. Mercurial ne postavlja nikakva pravila ni zahtjeve po tom pitanju. Ta fleksibilnost je naravno dobrodošla ali treba paziti da se ne pretjera jer previše složene hijerarhije repozitorija mogu dovesti do toga da ih sudionici u projektu ne koriste kako su zamišljene jer im je to jednostavno prekomplicirano.

1.2 Primjer

1.2.1 Osnovna organizacija

Zamislimo tročlani tim mladih entuzijasta koji su odlučili promijeniti svijet svojom najnovijom TODO aplikacijom. Naši junaci Ante, Pero i Marko svaki ima specifična znanja koja će uložiti u projekt: Ante se razumije u baze podataka i backend sustave, Pero ima Android programiranje u malom prstu, a Marko je dobar dizajner i programer web korisničkih sučelja. Školski praznici su tek počeli a oni su odlučili zamijeniti jedno ljetovanje za mogućnost ranog umirovljenja. Novčana ulaganja su minimalna, imaju 3 jeftina laptopa s Linux operativnim sustavom i jedan wireless router.

TODO aplikacija će osim centralne komponente koja čuva podatke (Antina specijalnost) imati i online web sučelje (Marko) te mobilno sučelje za Android telefone (Pero). Ne žele trošiti mnogo vremena na održavanje infrastrukture pa su za version control uzeli Mercurial bez instalacije njegovog centralnog servera. Sva će komunikacija između repozitorija ići preko SSH protokola.

Ante, kao programer centralnog dijela sustava, na svojem laptopu ima zadatak čuvati glavni repozitorij cijelog projekta te repozitorije za komponente sučelja. On na svojem laptopu otvara dva korisnička računa za svoje kolege koje će oni koristiti za slanje svojih izmjena na Antin laptop. Zatim na prikladnoj lokaciji (recimo "/") kreira direktorij "projekt", pozicionira se u njega i pokreće naredbu "hg init master". Rezultat je novi direktorij, "master", koji sadrži svježe inicijalizirani prazan Mercurial repozitorij. To je glavni repozitorij koji će biti "roditelj" svim ostalima. Ante zatim pokreće naredbe "hg clone master core", "hg clone master android" i "hg clone master web". Time je napravio tri grane u kojima će se primarno raditi razvoj samo određene komponente sustava. Vlasništvo datoteka u grani "core" ostaje Antino dok grane "android" i "web" potpadaju pod vlasništvo korisnika "pero" i "marko". Struktura direktorija sad izgleda ovako (vlasništva nad datotekama navedena su na početku svake linije):

:ante:      /projekt/
:pero:        |-android/
:ante:        |-core/
:marko:       |-web/
:ante:        `-master/

Da bi radili svaki na svojem dijelu sustava Pero i Marko na svojim laptopima pokreću naredbe:

[pero] /projekt >
hg clone ssh://pero@antin-laptop//projekt/android 
[marko] /projekt >
hg clone ssh://marko@antin-laptop//projekt/web

Logički, hijerarhija repozitorija sad izgleda ovako:



1.2.2 Svakodnevni rad

Naši junaci su sad slobodni početi pisati kod, dokumentaciju i bilo kakav drugi sadržaj i dodavati ga u vlastite repozitorije. Uobičajeno je doduše da se ove glavne cjeline podijele na podsustave i da svaki podsustav ima svoj klon repozitorija. Jedna od mogućih organizacija izgledala bi ovako:



Dok se radi na izmjenama ili pisanju novog koda ipičan slijed događaja u jednom repozitoriju bio bi:



U ovoj fazi te izmjene vidi samo njihov autor. Naredba "commit" ne sinkronizira sadržaj vašeg repozitorija s centralnim. Isto tako druge naredbe koje ćete možda poželjeti pokretati (npr. "log" koja pokazuje povijest promjena) ne trebaju vezu s glavnim repozitorijem. Sve je pohranjeno na vašem računalu.

Kad su članovi tima završili neku cjelinu potrebno je izmjene podijeliti s ostatkom tima. Postoji nekoliko načina kako prenijeti izmjene iz jednog repozitorija u drugi ali ovdje ću se koncentrirati samo na naredbe "pull" i "push". U konfiguraciji kao što ju ima naš pokazni projekt promjene je potrebno "pogurati" sve do "master" repozitorija da bi se onda mogle "pull" naredbama dostaviti do svih repozitorija kojima su te promjene potrebne. Na primjer, pretpostavimo da je Pero završio mrežni dio svoje Android aplikacije. Običaj je u Mercurial svijetu najprije povući najnovije promjene iz nadređenih repozitorija i razriješiti bilo kakve konflikte s vašim promjenama prije nego naredbom "push" pošaljete svoje promjene "prema gore".

[pero] /projekt/network >
hg pull -u ssh://pero@antin-laptop//projekt/master 
[pero] /projekt/network >
hg merge
[pero] /projekt/network >
hg commit -u pero -m "Najnovije promjene iz master"
[pero] /projekt/network >
hg push
[pero] /projekt/network >
cd ../android
[pero] /projekt/android >
hg push



Ovo je možda malo komplicirani niz naredbi no potreban je da bi se sve promjene ispravno prenijele na prava mjesta. Kratki opis bio bi:

Promjene iz "master" repozitorija prebačene su u "network" repozitorij i razriješeni svi sventualni konflikti postojećeg i novog koda.

Promjene iz "network" repozitorija su pogurnute u Perin glavni "android" repozitorij (još uvijek na njegovom laptopu)

Sadržaj Perinog "android" repozitorija je pogurnut u "android" repozitorij na Antinom laptopu.

Kao rezultat ovog postupka "android" repozitorij na Antinom laptopu sadrži najnovije Perine izmjene. Ostali članovi tima mogu testirati interakciju novog Perinog koda s njihovim kodom tako da naprave privremeni klon svojeg repozitorija, pokrenu "pull" naredbu iz centralnog "android" repozitorija i naprave testove koji ih zanimaju. Kad su svi zadovoljni Ante može ući u direktorij s "android" repozitorijem na svojem laptopu i pokrenuti "hg push" naredbu s kojom će pomaknuti Perine izmjene u centralni "master" repozitorij.

1.2.3 Nekoliko primjedbi

Poželjno je da članovi tima što češće sinkroniziraju svoje repozitorije s "master" repozitorijem ili nekim drugim nadređenim repozitorijem, ovisno o dogovoru. Na taj način se smanjuje vjerojatnost za noćnu moru svakog programera zvanu "merge conflict". Drugi razlog za česte sinkronizacije je backup. Ako se Antinom računalu desi havarija ostali članovi tima će imati kompletne kopije glavnog repozitorija koji uključuju kompletnu povijest svih izmjena. Naravno, to nije isprika da se ne koristi pravi backup sustav ali je jedno od zgodnih svojstava distribuiranih version control sustava.

Ova priča pokriva samo jedan, prilično jednostavan scenarij i uz to pokriva samo osnovne elemente iz života jednog programerskog tima. Ipak, nadam se da sam dao dobar uvod u način kako bi se mogao organizirati jedan projekt koji koristi Mercurial kao DVCS.

1.3 Što dalje?

Ovaj i prethodni članak ne mogu nikako poslužiti kao kompletan vodič za rad s Mercurial sustavom. Svaki sustav ove namjene je jednostavno previše složen da bi se mogao opisati u nekoliko odlomaka. Ovdje ću staviti dva korisna linka koja bi vam mogla pomoći s osnovnim konceptima i usmjeriti vas dalje.

http://mercurial.selenic.com/wiki/QuickReferenceCardsAndCheatSheets
http://hgbook.red-bean.com/

Igor Rumiha nezavisni je konzultant koji se u svojoj IT karijeri od 2000. godine do danas bavio izradom sustava za mrežni nadzor, provisioning sustavima u ISP i mobile telekom okolinama i automatizacije testova na embedded platformama. U pauzama između tih poslova bavio se administracijom Oracle i MSSQL baza, billing sustava pa čak i izradom billing sustava.

Kolumna Igora Rumihe: Ostati programer ili prijeći u IT management?

Sadržaje rep.hr-a od ovog mjeseca obogatit ćemo novim kolumnama, a jedna od njih bit će kolumna iskusnog programera Igora Rumihe, koji će svaka četiri tjedna pisati o IT temama.

Kolumna Igora Rumihe: Stari programski jezici temelj su shvaćanja novih

Prije nekoliko godina u ruke mi je dopala knjiga "The Pragmatic Programmer" od Andrewa Hunta i Davida Thomasa.

Kolumna Igora Rumihe: Kratki prikaz Mercurial version control sustava

Postoji nekoliko grupa alata koje bi svi trebali koristiti ali se dosta malo koriste. Radi se o version control sustavima, o sustavima za internu dokumentaciju i praćenje grešaka, te o code review alatima.

Kolumna Igora Rumihe: Mercurial iskustva u praktičnom radu, savjeti i trikovi

Vrijeme je za nekoliko opažanja i trikova u praktičnom radu s Mercurialom. Teorija je zgodna stvar ali praksa je često malo drugačija.