Revision 18 as of 2012-03-04 15:24:36

Clear message

Varíme z ortuti, zdravo, rýchlo a lacno

Spisovateľ práve zasadol za svoj pracovný stôl. Pravou rukou vytiahol zásuvku a z nej zväzok s materiálmi na ktorých v poslednej dobe pracuje. Našiel ich presne v tom stave, v ktorom ich včera zanechal. Okrem práce, ktorú na nich urobil včera, je v nich vidno celú históriu postupného pripisovania, prepisovania, pridávania a škrtania. V tých papieroch je celá história zmien, ktoré doteraz vykonal. Má to jednu výhodu: ak niekedy nadobudne pocit, že pred mesiacom sa jeho práca nachádzala v lepšom stave než dnes, môže sa k stavu spred mesiaca okamžite vrátiť a nadviazať naň.

Programátor práve zasadol za svoj počítač. V editore otvoril zdrojový kód projektu, na ktorom v poslednej dobe pracuje. Našiel ho presne v tom stave, v ktorom ho včera zanechal. Programátor, na rozdiel od svojho kolegu spisovateľa, nevidí v akom stave sa projekt nachádzal pred týždňom alebo pred mesiacom. Programátor je nervózny: ešte predvčerom bol program funkčný ale včera ho začal živelne modifikovať, v dôsledku čoho program znefunkčnil. Navyše, snažiac sa zachrániť čo najviac, programátor znervóznel a v strese zaniesol do kódu ešte ďalšie chyby. Čo by dal programátor za to, keby sa mohol vrátiť k predvčerajšej verzii kódu. Dalo by sa to spraviť, keby si programátor jednotlivé verzie zálohoval. Lenže zálohovanie je pracné a len málo kto je dostatočne disciplinovaný na to, aby zálohoval denne. Náš programátor by to mal na svete oveľa jednoduchšie, keby používal nejaký systém správy verzií. Napríklad mercurial.

Táto stránka je písaná pre tých, ktorí Mercurial nikdy nevideli v akcii, ale potrebujú ho používať. Hlboké porozumenie ktorémukoľvek systému správy verzií (zďaleka nie len Mercurialu) vyžaduje uchopenie veľkého množstva abstraktných pojmov. Vďaka tomu začiatočník snažiaci sa preniknúť k podstate trpí. Komenský vraj hovorieval, že učiaci sa človek si najprv osvojí prízemné aspekty veci, a až potom (ak vôbec) je pripravený začať o veci rozmýšlať. Pretože s týmto názorom súhlasím, a pretože Mercurial je z môjho hladiska iba nástroj, rozhodol som sa napísať tento tutoriál, ktorý celú problematiku Mercurialu vysvetľuje na niekoľkých jednoduchých receptoch. S takýmto prístupom k vysvetľovaniu vecí polemizuje názor, podľa ktorého je redukcia akéhokoľvek problému na sadu receptov neprípustnou trivializáciou, vhodnou nanajvýš tak pre cvičené opice. Názor je to síce stále menej populárny, je na ňom však veľký kus pravdy. A preto... ak čitateľa tutoriál uráža, je to neklamný znak, že tento text nie je určený pre neho. Jemu odporúčam nazrieť do niektorého spomedzi tisícok iných online textov, ktoré mercurial vysvetľujú na civilizovanej úrovni.

Výber diskutovaných úkonov je rýdzo pragmatický. Tento text vnikol primárne pre potreby mojich študentov a to so zreteľom na moju osobnú skúsenosť s tým, ktorá časť mercurialovskej rutiny robí začiatočníkovi problémy.

Prvotná dichotómia

Naprieč mojou prezentáciou mercurialu vedie deliaca čiara, ktorou sú všetky mercurialovské úkony rozdelené na miestne a nemisetne. Miestne sú také úkony, na ktoré vám stačí počítač pri ktorom sedíte. Sú to aktivity, ktoré prebiehajú na tom mieste, kde ste aj vy. Na rozdiel od aktivít nemiestnych, ktoré do hry nejakým spôsobom zapájajú vzdialené počítače prístupné pomocou počítačovej siete. Pretože každý človek na tomto svete by si mal ponechať nemiestne prejavy na neskôr, začneme aj my aktivitami miestnymi.

Miestne používanie mercurialu dostatočne dobre motivuje a ilustruje príklad z úvodných paragrafov. Miestne používanie je presne to, čo programátorovi stačí k tomu, aby mal k dispozícii celú históriu zmien projektu, aby mohol viesť dve (alebo viac) paralelné histórie zmien a neskôr ich prípadne spájať. Už toto predstavuje dosť dobrý dôvod prečo mercurial používať. Lenže tým sa sila mercurialu zďaleka nevyčerpáva.

Mercurial je obzvlášť silný v kombinácii s možnosťami počítačových sietí. Spolupracujete na projekte s ďalšími programátormi? Mercurial vám umožní skrotiť zmetok spôsobený skutočnosťou, že viacero programátorov pracuje súčasne na tej istej časti kódu. Mercurial vám umožní pracovať za každých okolností s tou najčersvejšou verziou kódu. Pretože vaši kolegovia sedia pri vzdialených počítačoch, musíte svoje mercurialovské aktivity povýšiť na sieťovú úroveň.

Iný príklad nemiestnej aktivity. Na projekte pracuje len jeden programátor, ale programuje zvyčajne pri dvoch počítačoch: doma a v práci. Zakaždým keď odchádza z práce domov, musí aktuálny stav projektu buď nahrať na nejaké sieťové miesto, alebo na prenosný USB kľúč. To preto, aby mohol neskôr stav svojich domácich adresárov synchronizovať so zmenami, ktoré spravil na počítači v práci. Lenže takýto spôsob synchronizácie je krajne nepohodlný - každý kto ho raz skúsil používať na dennej báze velmi dobre vie, koľkokrát stavy pracovných adresárov zabudol zosynchronizovať alebo ich jednoducho nezosynchronizoval z prozaického nedostatku vôle (ktorej na konci šichty nebýva veľa). Mercurial, ak sa používa nemiestne, deleguje celý proces synchronizácie na spustenie jediného jednoduchého príkazu z príkazového riadku.

Predpoklady

Predpokladám, že uživateľ vie, čo je to príkazový riadok a vie s ním pracovať na elemtnárnej úrovni. To znamená, že vie z príkazového riadku blúdiť adresárovou štruktúrou filesystému, vie vytvoriť, editovať alebo zmazať súbor alebo, ak pracuje na unixovskej platforme, zmeniť prístupové práva súboru. Môže sa stať, že niektoré príkazy, ktoré sa v tutoriáli objavia nefungujú pod windowsami. Žial, tento tutoriál bude, aspoň zo začiatku, vychádzať z predpokladu, že čitateľ používa nejaký operačný systém.

Predpokladám, že stroj, za ktorým uživateľ sedí, má funkčnú inštaláciu mercurialu. Otázkou ako mercurial nainštalovať a prípadne spojazdniť sa nezaoberám. Zvyčajne s tým nebýva problém, na väčšine distribúcií linuxu spočíva inštalácia v použití natívneho balíčkovacieho nástroja.

Miestne aktivity

Založenie nového repozitára (init)

Nepríčetný programátor má projekty na ktorých pracuje nahádzané všetky v jednom adresári. Ešte nepríčetnejší programátor ich drží v jednom súbore. Je to vynikajúci nápad - z projektov takto na filesystéme vzniká pôsobivá a chutná bouillabaisse. Nepríčetný programátor už zmysel života našiel a s kľudným svedomím môže v tomto bode prestať čítať. Čokoľvek.

Príčetný programátor má projekty na ktorých pracuje porozdeľované do adresárov. Ešte príčetnejší programátor má aj jednotlivé tieto adresáre ďalej rozdelené na podadresáre. Tieto môžu byť, napríklad, podadresár na všetky zdrojové kódy, špeciálny podadresár na dáta s ktorými program pracuje, alebo podadresár s dokumentáciou. Tu vysvetlíme, čo má príčetný programátor urobiť, aby zabezpečil, že mercurial začne sledovať a pamätať si zmeny a postupný vývin jedného konkrétneho projektu. Ak nie je povedané inak, všetky úkony v tomto tutoriáli spočívajú v spúštaní príkazov z príkazového riadku.

1. V prvom rade treba nastaviť aktuálny pracovný adresár na ten adresár, v ktorom sa nachádza projekt, ktorý chceme mercurialom sledovať. Ak sa napríklad programátor rozhodne, že chce sledovať projekt v adresári aaa/bbb/ccc, prvý úkon v príkazovom riadku by mal vyzerať takto:

cd aaa/bbb/ccc

2. Teraz nastal ten okamih, kedy treba mercurialu oznámiť, že zmeny v tomto adresári má sledovať. Docieli sa to takto (všimnite si, že všetky mercurialovské úkony spočívajú vo volaní príkazu hg):

hg init

Práve ste vytvorili mercurialovský repozitár. Od tohoto okamihu mercurial sleduje všetky zmeny v ktoromkoľvek súbore v tomto adresári alebo jeho lubovoľne hlboko vnorenom podadresári. Ak sa teraz pozriete na obsah aktuálneho adresára, všimnete si, že v ňom pribudol podadresár .hg - tu si mercurial drží všetky potrebné informácie o histórii zmien ale aj konfiguračné informácie, ktoré definujú ako sa má mercurial správať v niektorých situáciach.

3A. Ešte pred tým, než začneme mercurial naplno využívať, oplatí sa investovať trošku času do dvoch kozmetických úprav. Prvá spočíva v doladení už vyššie spomenutých konfiguračných informácií. Predpokladajme, že programátor sa volá Jožko Mrkvička a práve sedí za počítačom, ktorému on, Jožko Mrkvička, hovorí zajax. Programátor zájde do už spomenutého podadresára .hg a vytvorí, edituje a uloží tam súbor hgrc, pričom doň pridá zhruba takéto riadky:

[ui]
username = jozef.mrqicka@zajax
verbose  = True

Nie je nijako extrémne dôležité, ako presne vyzerá reťazec definujúci username. Úplne postačí, ak je z reťazca nejako zrejmé komu repozitár patrí a na ktorom počítači sa repozitár nachádza. Na čo je to celé dobré vysvitne neskôr.

To čo sme tu práve popísali predstavuje nutné minimum nastavení, ktoré treba vykonať na začiatku, hneď po založení repozitáru. Samozrejme, okrem týchto nastavení možno ponastavovať množstvo iných úžasných vecí, o ktorých tento tutoriál mlčí.

3B. Mercurial je dôsledný. Ak mu to nezakážete, bude sa snažiť sledovať zmeny v úplne všetkých súboroch v repozitári. Takéto správanie vie byť v istých situáciach otravné - niekedy vyslovene chcete, aby si niektoré súbory mercurial radšej nevšímal, lebo na ich zmenách vôbec nezáleží. Príkladom takých súborov, ak programujete v jazyku C, sú objektové súbory (tie s koncovkou .o) alebo definitívny výsledok prekladu (výsledný spustiteľný súbor). Tieto veci sledovať netreba, pretože ak máte k dispozícii zdrojové kódy, stačí ich skompilovať a máte aj vyššie spomenuté. Ako mercurialu zkážete sledovať niektoré súbory? Slúži na to konfiguračný súbor .hgignore. Tento súbor sa v repozitári musí nachádzať v jeho najvyššom adresári, hneď vedľa adresára .hg, ktorému sme sa venovali v predchádzajúcom paragrafe. V našom prípade je ním adresár aaa/bbb/ccc. Ukážkový súbor .hgignore by mohol vyzerať napríklad takto:

.*\.o$
bin/hello$
data/

Zdá sa, že náš fiktívny hrdina, Jožko Mrkvička, sa rozhodol ignorovať úplne všetky súbory s koncovkou .o (prvý riadok), ďalej súbor hello v podadresári bin (druhý riadok) a napokon úplne všetko, čo je v podadresári data a v ktoromkoľvek jeho podadresári. Je jasné, že váš súbor .hgignore nemusí vyzerať presne takto. Treba ho prispôsobiť vaším potrebám, čo väčšinou znamená potrebu nazrieť do detailnej dokumentácie.

Zistenie stavu repozitára (status)

Mercurial je pracovitý - dôsledne sleduje zmeny vo všetkých súboroch v repozitári (ak nie je povedané inak) a tieto zmeny vidí. Mercurial je slušne vychovaný - vlastnými múdrymi pozorovaniami vás nebude otravovať. Ak si niečo všimne, nechá si to pre seba. Fajn, lenže z času na čas predsa potrebujeme vedieť, čo si mercurial všimol. Ak by sme sa to nemali ako dozvedieť, nebolo by to celé na nič dobré. Vec sa má tak, že sa na to musíme mercurialu opýtať. Takto:

hg status

Ak sme práve vytvorili čerstvý repozitár podľa receptu v predchádzajúcom paragrafe, mercurial by mal odpovedať takto:

? .hgignore

Týmto nám mercurial hovorí, že v adresári repozitára vidí súbor .hgignore. Otáznikom pred menom súboru nám mercurial oznamuje, že mu nie je jasné, či má zmeny tohoto súboru sledovať alebo ignorovať. Moment... nepovedal som pred chvíľou, že pokiaľ nie je povedané inak, mercurial automaticky sleduje všetky zmeny? No ano, povedal som to, ale to som klamal. Vec je trochu zložitejšia - mercurial sleduje iba zmeny tých súborov, ktoré mu sledovať prikážete. No fajn, lenže aký je potom skutočný význam súboru .hgignore? Takýto: súbory, ktoré sú uvedené v .hgignore vám mercurial sledovať ani len neponúkne. Nám teraz mercurial ponúka sledovať zmeny v súbore .hgignore a pýta sa nás, čo my na to.

Jožko Mrkvička už má hrania sa s mercurialom pre túto chvíľu dosť a začína sa venovať programovaniu. V adresári projektu vytvára prvý zdrojový kód ./src/hello.c a jeho kompiláciou vytvára objektový súbor ./src/hello.o a spustitelný súbor ./bin/hello. Ak teraz spustíme hg status mali by sme uvidieť niečo takéto:

? .hgignore
? hello.c

Vidíte, pribudlo viac súborov, mercurial sa však stará iba o tie z nich, ktoré nemá prikázané ignorovať z titulu .hgignore.

Pridanie súboru do repozitára (add)

Mercurial teda vidí dva súbory o ktorých nevie, či má ich zmeny sledovať alebo nie a pýta sa nás na ne. Povedzme, že Jožko Mrkvička chce sledovať iba súbor hello.c. Docieli to takto:

hg add hello.c

Ak teraz spustí príkaz hg status uvidí toto:

A hello.c
? .hgignore

Mercurial mu takto oznamuje, že v repozitári sú dva problematické súbory, z toho jeden je mercurialom sledovaný a o druhom mercurial stále nevie, či ho sledovať má alebo nie.

Nasleduje terminologická poznámka. Tomu, že mercurial začne sledovať zmeny nejakého súboru hovoríme, že sme tento súbor pridali do repozitáru. Čiže zatiaľ sme pridali do repozitáru súbor hello.c.

Zapamätanie stavu repozitára (commit)

Mercurial už sleduje obsah repozitára a všíma si zmeny v niektorých jeho súboroch. To, že si zmeny všíma však neznamená, že si tieto zmeny aj pamätá. Ak chceme, aby si niektorý stav repozitára zapamätal, musíme mu to prikázať. V predchádzajúcom odseku sme videli, ako Jožko Mrkvička pridal do repozitára prvý súbor. On, Jožko Mrkvička, by teraz chcel, aby si mercurial zapamätal stav, v ktorom sa čerstvo pridaný súbor nechádza. Urobí to takto:

hg commit -m "prvotny stav"

Zapamätaniu stavu repozitára sa hovorí "commit" (en: spáchať) a slúži naň príkaz hg commit.Všimnite si, že príkaz má parameter -m za ktorým nasleduje reťazec. Tento by mal byť nejakým veľmi stručným ale výstižným popisom, z ktorého je jasné, čím je zapamätaný stav význačný. Alebo čím sa líši od prechádzajúceho zapamätaného stavu. Jožko Mrkvička si práve zapamätáva stav repozitáru čerstvo vytvoreného repozitáru a preto sa rozhodol pomenovať ho "prvotny stav". Ak sa teraz mercurialu opýtame na stav repozitára (pomocou hg status), mali by sme dostať takúto odpoveď:

? .hgignore

Mercurial nám stále vyhadzuje na oči, že nevie, či má alebo nemá sledovať zmeny v súbore .hgignore. Nič iné mu už ale nevadí. Stav jediného sledovaného súboru je uložený v poslednom commite a aktuálny stav tohoto súboru sa od zapamätaného stavu nijako nelíši. Všetko je tak ako to bolo v naspoledy zapamätanom stave a mercurial nemá čo robiť.

V tomto okamžiku sa Jožko môže venovať programovaniu. Povedzme, že v súbore hello.c vykonal niekoľko drobných zmien. Ak sa teraz mercurialu opyta na stav repozitara, dozvie sa toto

M hello.c
? .hgignore

Mercurial mu dáva na vedomie, že v repozitári sa nachádzajú dva problematické súbory. Prečo je problematický súbor .hgignore už vieme - mercurial sa stále trápi otázkou, či má alebo nemá sledovať zmeny tohoto súboru. So súborom hello.c má mercurial iný problém - to, že ho má sledovať vie. Písmenom M na začiatku riadku nás mercurial upozorňuje, že tento súbor sa nachádza v inom stave, než v ktorom sa nachádzal po poslednom commite. Zmenil sa. Mercurial nám takto dáva najavo, že aktuálny stav tohoto súboru nie je zapamätaný a ak by sme si ho cheli zapamätať, musíme opäť vykonať commit. Skúsme ho vykonať, a pozrime sa, ako sa zmení stav repozitára:

hg commit -m "vylepsenie programu hello"
hg status
? .hgignore

Samozrejme. Stavy súborov, ktoré mercurial sleduje sú zapamätané a o súbore ".hgignore" mercurial stále nevie, či ho má alebo nemá sledovať. Jožko Mrkvička teraz môže ďalej programovať a commitovať zmeny, ktoré v jeho programe nastanú alebo ísť spať. Zajtra, keď si sadne k počítaču, bude na ňom uložený nie len aktuálny stav projektu, ale celá história jeho zmien.

Zobrazenie histórie repozitára (log)

Deň dva. Jožko Mrkvička si opäť sadá k počítaču. Bude programovať. Pred tým však rád by si pripomenul, na čom pracoval včera. Mercurial mu vie pomôcť. Existuje príkaz, ktorý zobrazí históriu všetkých doposial vykonaných commitov na repozitári. Vyzerá to takto:

hg log

Ak sa história repozitára vyvíjala tak, ako to popisuje tento tutoriál, výstup by mal vyzerať takto:

changeset:   1:1ce4b3736273
user:        jozef.mrqicka@zajax
date:        Thu Mar 01 18:29:48 2012 +0100
files:       pokus.c
description:
vylepsenie programu hello

changeset:   0:83ff949a5b74
user:        jozef.mrqicka@zajax
date:        Thu Mar 01 18:29:10 2012 +0100
files:       pokus.c
description:
prvotny stav

Mercurial nám oznamuje, že stav repozitára bol zapamätaný zatiaľ iba dvakrát. V oboch prípadoch to bol Jožko Mrkvička sediaci za počítačom zajax kto stav repozitáru uložil. Ďalej vidíme, kedy ku commitom došlo, akých súborov sa týkali a vidíme aj krátky popisný reťazec, ktorým sme vysvetlili o čo v danom commite išlo.

Tým, ktorí nemajú radi príkazový riadok dávam do pozornosti grafické rozhrania, ktoré znázorňujú históriu repozitára v prehladnej grafickej podobe. Jedným takým prehliadačom je multiplatformový tortoise hg. Na niektorých Linuxoch býva mercurial nainštalovaný a nakonfigurovaný tak, že príkaz hg view spustí nejaký grafický prehliadač histórie repozitáru.

Úmyselné rozvetvenie histórie (branch)

Úmyselné zvetvenie histórie (merge)

Nemiestne aktivity

Založenie vzdialeného repozitára na bitbuckete

Bitbucket je internetová služba, ktorá umožnuje udržovať na internetovom (a teda viacmenej odvšadial prístupnom) mieste vaše mercurialovské repozitáre. Nie je to zďaleka jediná takáto služba a, s výnimkou tejto časti, sú rady tohoto tutoriálu prenesiteľné na ktorúkoľvek z nich.

Ak chcete mercurial používať, musíte si tam, samozrejme, najprv vytvoriť konto. Ideálne spriahnuté s nejakým mailboxom, ktorý reálne použivate - bitbucket umožňuje emailové zasielanie informácií o zmenách v repozitároch. Ak už konto máte a ste pod svojou identitou nalogovaný, môžete založiť (alebo zrušiť) vzdialený mercurialovský repozitár.

Tu predpokladám, že na miestnom počítači už máte nejaký repozitár, ktorý chcete začať používať nemiestne. Na bitbuckete najprv v menu "Repositories" zvolte položku "create repository". Bitbucket sa následne pýta na meno projektu, či to má byť Gitovský alebo mercurialovský repozitár (samozrejme, zvoľte mercurial). Ak na projekte spolupracujete s viacerými programátormi, je užitočné zvoliť možnosť "Issue tracking". Ďalej môžete nastaviť podstatný programovací jazyk projektu, krátky popis projektu a linku na jeho webstránku (ak nejaká existuje) - tieto informácie sú užitočné, ale nie podstatné.

Po odoslaní týchto informácií objaví sa vám hlavná stránka čerstvo založeného repozitára. Pretože ste doň zatial neposlali žiadne reálne dáta, zobrazuje sa tam akýsi help s niekoľkými jednoduchými receptami. Pre nás je podstatný iný typ informácie. Hlavička stránky sumarizuje meno repozitáru, komu repozitár patrí a hneď pod týmito informáciami vidno internetovú linku, cez ktorú je repozitár prístupný. K repozitáru možno pristupovať dvoma spôsobmi: pomocou SSH kanála alebo pomocou HTTPS linky. Podľa toho, ktorú metódu zvolíte, zobrazuje sa iná linka. Z technického hladiska je jednoduchší prístup pomocou HTTPS protokolu. Prístup pomocou SSH protokolu vyžaduje synchronizáciu verejných šifrovacích kľúčov, o čom tento tutoriál nepojednáva. Preto zvoľte HTTPS. Adresa by mala mať štruktúru

https://LOGIN@bitbucket.org/LOGIN/REPO

kde LOGIN je meno vašej bitbucketoveskej identity a REPO je meno čerstvo založeného bitbucketovského repozitára.

Teraz v príkazovom riadku na miestnom počítači nastavte aktuálny adresár na adresár miestneho repozitáru, ktorý chcete na bitbucket nahrať. Miestnemu repozitáru teraz treba oznámiť, aby sa celá jeho história nahrala na vzdialený repozitár na bitbuckete. Takto:

hg push ADRESA_REPOZITARA

kde ADRESA_REPOZITARA je presné znenie adresy založeného repozitára tak ako ju zobrazuje bitbucket.

Prenos komitov z lokálneho repozitára na vzdialený (push)

Prenos komitov zo vzdialeného repozitára na lokálny (pull)