Receptár Git-u

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, začal zmetkovať 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 git.

Táto stránka je písaná pre tých, ktorí git nikdy nevideli v akcii, ale potrebujú ho používať. Hlboké porozumenie ktorémukoľvek systému správy verzií (zďaleka nie len git-u) 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 git je z môjho hladiska iba nástroj, rozhodol som sa napísať tento tutoriál, ktorý celú problematiku 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 tento receptár čitateľa uráža, je to neklamný znak, že nie je určený pre neho. Jemu odporúčam nazrieť do niektorého spomedzi tisícok iných online textov, ktoré git vysvetľujú na kultivovanej úrovni.

Výber diskutovaných receptov 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ť git-ovskej rutiny robí začiatočníkovi problémy.

Prvotná dichotómia

Naprieč mojou prezentáciou git-u vedie deliaca čiara, ktorou sú všetky git-ovské úkony rozdelené na miestne a nemiestne. 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 git-u je dostatočne dobre motivované a ilustrované príkladom z úvodných paragrafov. Je to 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ých histórií zmien alebo ich spájať. Už toto predstavuje dosť dobrý dôvod prečo git používať. Lenže tým sa sila git-u zďaleka nevyčerpáva.

Git je obzvlášť silný v kombinácii s možnosťami počítačových sietí. Spolupracujete na projekte s ďalšími programátormi? Gi vám umožní skrotiť zmetok spôsobený skutočnosťou, že viacero programátorov pracuje súčasne na tej istej časti kódu. Git vám umožní pracovať za každých okolností s tou najčersvejšou verziou kódu. Keďže však vaši kolegovia sedia pri vzdialených počítačoch, musíte svoje git-ovské 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. Git, 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 viete, čo je to príkazový riadok a viete s ním pracovať na elementárnej úrovni. To znamená, že viete z príkazového riadku blúdiť adresárovou štruktúrou filesystému, viete vytvoriť, editovať alebo zmazať súbor alebo, ak pracujete 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 používate nejaký poriadny operačný systém.

Predpokladám, že stroj, za ktorým použivateľ sedí, má funkčnú inštaláciu git-u. Otázkou ako git nainštalovať a prípadne spojazdniť sa nezaoberám. Zvyčajne s tým nebýva problém. Na väčšine distribúcií linuxu je git automaticky nainštalovaný, a ak náhodou nie, stačí použiť natívny balíčkovací nástroj.

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 git 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 git-om 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 git-u oznámiť, že zmeny v tomto adresári má sledovať. Docieli sa to takto (všimnite si, že všetky git-ovské úkony spočívajú vo volaní príkazu git):

git init

Práve ste vytvorili git-ovský repozitár. Od tohto okamihu git 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 .git - tu si git drží všetky potrebné informácie o histórii zmien ale aj konfiguračné informácie, ktoré definujú ako sa má git správať v niektorých situáciach.

3A. Ešte pred tým, než začneme git 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. Jožko by mal z ľubovolného podadresára práve založeného repozitára v príkazovom riadku spustiť nasledujúce príkazy:

git config user.name "jozko.mrkvicka@zajax"
git config user.email "jozko.mrkvicka@gmail.com"

Prvým príkazom Jožko nastavil používateľské meno a druhým príkazom používateľovu emailovú adresu asociovanú s práve založeným repozitárom. Nie je nijako extrémne dôležité, ako presne ich nastavil. Napríklad konfiguračný parameter user.name, z ktorého názvu by sa mohlo zdať, že má slúžiť na ukladanie používateľovho mena, nastavil na hodnotu "jozko.mrkvicka@zajax", čo nápadne pripomína emailovú adresu, lenže žiadna emailová adresa to nie je. Rovnako dobre mohol použiť aj akýkoľvek iný reťazec. Jožko zvolil tento reťazec preto, aby z neho bolo zrejmé ako sa on, Jožko Mrkvička, volá a súčasne, aby bolo zrejmé aj to ako sa volá počíťač za ktorým práve sedí. Čoskoro sa dozvieme, na čo je to dobré.

Tak isto aj namiesto svojej emailovej adresy mohol Jožko zadať nejakú vymyslenú adresu. Nič hrozné by sa nestalo. Rovnako tak nemusel emailovú adresu nastaviť vôbec, čo, mimochodom, nie je zlý nápad, i keď sú s tým spojené isté sporadické komplikácie, ale tie sa začnú prejavovať až pri nemiestnom používaní gitu a preto ich zatiaľ odložíme ad acta.

Nutné minimum nastavení v čerstvo vytvorenom repozitári predstavuje riadok, ktorým sa nastaví hodnota parametra user.name čo predstavuje iba smiešny zlomok toho, čo sa ponastavovať dá.

3B. Git 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 git 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 súbory sledovať netreba, pretože ak máte k dispozícii zdrojové kódy, stačí ich skompilovať a máte aj vyššie spomenuté.

Sledovanie súborov možno gitu zakázať pomocou konfiguračného súboru .gitignore. Tento súbor vytvoríme v hierarchicky najvyššom adresári repozitára, hneď vedľa adresára .git, 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 .gitignore by mohol vyzerať napríklad takto:

*.o
bin/hello
data/

Prvým riadkom gitu zakážeme aby svoju pozornosť venoval súborom s príponou "o" a to v celom repozitári, či už sa nachádzajú v hierarchicky najvyššom adresári, alebo v nejakom jeho podadresári. Druhým riadkom gitu zakazujeme, aby sledoval súbor "hello" v podadresári "bin". Treetím riadkom gitu zakazujeme sledovať všetko, čo sa nachádza v podadresári "data". Je jasné, že .gitignore nemusí vyzerať presne takto. Treba ho prispôsobiť konrkétym potrebám, čo väčšinou znamená potrebu nazrieť do detailnej dokumentácie.

Zistenie stavu repozitára (status)

Git je pracovitý - dôsledne sleduje zmeny vo všetkých súboroch v repozitári (ak nie je povedané inak) a tieto zmeny vidí. Súčasne je však slušne vychovaný - sám od seba nás vlastnými múdrymi pozorovaniami nebude otravovať. Ak si niečo všimne, nechá si to pre seba. Dobre, lenže z času na čas predsa potrebujeme vedieť, čo si git všimol. Ak by sme sa to nemali ako dozvedieť, nebolo by to celé na nič dobré. Pretože git nerozpráva sám od seba, ak sa chceme niečo dozvedieť, musíme sa na to opýtať. Robí sa to pomocou gitovského príkazu status takto:

git status

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

On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        .gitignore

nothing added to commit but untracked files present (use "git add" to track)

Týmto nám git hovorí vela rôznych vecí, väčšinu z nich odignorujeme a vrátime sa k nim neskôr. Na tomto mieste sa pristavíme pri hláške: "Untracked files" ktorou nám git oznamuje, že v adresári vidí súbor .hgignore a že tento súbor aktuálne nie je sledovaný. Všetky súbory, ktoré sa nachádzajú v repozitári možno rozdeliť do nasledujúcih piatich skupín:

To, že git považuje súbor ".gitignore" za "Untracked" nám hovorí, že súbor je v stave U. Ak by bol súbor v stave I, git by nám o ňom nehovoril vôbec nič.

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 podadresáre src a bin, 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:

On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        .gitignore
        src/

nothing added to commit but untracked files present (use "git add" to track)

Git nám tým hovorí, že v repozitári je jeden súbor v stave U (je to súbor .gitignore) a ďalej, že je tu jeden adresár, v ktorom sú ďalšie súbory v stave U (je to adresár src). Všimnime si, že o adresári bin, ktorý tiež v repozitári pribudol v dôsledku programovania, git nič nehovorí. Je to preto, lebo všetko čo sa v tomto adresári nachádza je v ignorovanom stave I. Ale buďme presní, v adresári bin sa aktuálne nachádza súbor hello lenže jeho sledovanie je v súbore .gitignore zakázané a to je dôvod, prečo sa nachádza v ignorovanom stave I. Vidíte, pribudlo viac súborov, mercurial sa však stará iba o tie z nich, ktoré nemá prikázané ignorovať z titulu .gitignore.

Príprava súboru na zapamätanie (add)

V tomto momente git vidí viacero súborov v stave U o ktorých nevie, či ich zmeny sledovať má alebo nie a pýta sa nás na ne. Povedzme, že Jožko Mrkvička chce začať sledovať súbor src/hello.c. Docieli to tým, že gitu aspoň raz prikáže prikáže, aby si zapamätal jeho stav. Lenže aby si git stav nejakého súboru zapamätal, musí si najprv súbor na zapamätanie pripraviť. Príprava spočíva v tom, že sa súbor uvedie do stavu S. Súbor možno do stavu S priviesť jednak zo stavu U alebo zo stavu M, v oboch prípadoch s použitím gitovského príkazu add takto:

git add ./src/hello.c

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

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   src/hello.c

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   .gitignore

Git nám týmto oznamuje viacero vecí. Jednak si všimol, že súbor ./src/hello.c je pripravený na zapamätanie, čiže, že je v stave S. Pozná sa to podľa toho, že je uvedený v sekcii "Changes to be committed" aj spolu s návodom, ako ho zo stavu S dostať naspať do prechádzajúceho stavu, ak by sme si to chceli so zapamätávaním súboru rozmyslieť. Súbor .gitignore je stále v stave U, ale git nás tentokrát upozorňuje na niečo iné. Niektoré súbory sú pripravené na najbližšie zapamätanie stavu a niektoré nie sú. Súbor .gitignore je jeden z tých ktoré nie sú. Na toto nás git teraz upozorňuje, to že je súbor .gitignore v stave U teraz gitu nepripadá natoľko dôležité, aby nás o tom informoval. Najbližšie nás o tom začne informovať v momente, keď žiadne iné súbory nebudú v stave S.

Zapamätanie stavu repozitára (commit)

Git 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 pripravil prvý súbor na zapamätanie stavu. On, Jožko Mrkvička, by teraz chcel, aby si git zapamätal stav, v ktorom sa čerstvo pridaný súbor nechádza. Urobí to takto:

git commit -m "prvotny stav repozitara"

Zapamätaniu stavu repozitára sa hovorí "commit" a slúži naň príkaz git commit.Všimnite si, že príkaz má parameter -m za ktorým nasleduje reťazec. Tento by mal byť nejakým viacmenej stručným ale určite 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 čerstvo vytvoreného repozitáru, je to úplne prvý zapamätaný stav v poradí, žiadny predchádzajúci zapamätaný stav neexistuje a preto sa rozhodol pomenovať ho "prvotny stav". Git by mal na spustenie tohto príkazu reagovať takto:

[master (root-commit) dca39c1] prvotny stav repozitara
 1 file changed, 8 insertions(+)
 create mode 100644 src/hello.c

Git nám týmto oznamuje, že úspešne do histórie zmien repozitára úspešne uložil aktuálny stav tých súborov, ktoré boli pripravené na zapamätanie. Ďalej nám oznamuje, že aktuálna vetva repozitáru je vetva master -- čo presne to znamená si možno vysvetlíme neskôr, na tomto mieste to nie je dôležité. Hláškou (root-commit) nám oznamuje, že sme práve vykonali prvé zapamätanie stavu tohto repozitára. Túto hlášku už viac neuvidíme. Záhadný reťazec ktorý nasleduje je fragment (temer) jedinečného čísla, ktorým bude predtavovať meno komitu, ktorý sme práve vykonali. Riadok je uzavretý znením popisného textu, ktorým je komit vysvetlený. Na nasledujúcom riadku sa dozvedáme, že v rámci komitu bol zapamätaný stav jedného súboru a že oproti predchádzajúcemu zapamätanému stavu (ktorý neexistuje) pribudlo v tomto súbore 8 riadkov. To teda znamená, že zdrojový kôd, ktorý Jožko naprogramoval má presne 8 riadkov. Správa je uzavretá ďaľšou technickou hláškou, ktorej sa nebudeme venovať.

Ak sa teraz gitu opýtame na stav repozitára (pomocou git status), mali by sme dostať takúto odpoveď:

On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        .gitignore

nothing added to commit but untracked files present (use "git add" to track)

Týmto nám git oznamuje, že v adresári repozitára sa nachádza jeden súbor, ktorého stav nebol ešte ani raz zapamätaný a nie je ignorovaný. Ide o súbor .gitignore a git nás velmi silno nabáda, aby sme ho začali sledovať. Doslova nám radí, ako to máme spraviť. Git je z tejto situácie trochu nervózny -- najradšej by sledoval všetky súbory v repozitári a tejto ambície sa vzdáva iba vtedy, keď mu explicitne povieme, že si to v prípade niektorého súboru neželáme. Súbor .gitignore sme mu ignorovať neprikázali no a tak ho neignoruje. A vidí, že stav tohto súboru zatiaľ ešte nebol ani raz zapamätaný.

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 gitu opyta na stav repozitara, dozvie sa toto

On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   src/hello.c

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        .gitignore

no changes added to commit (use "git add" and/or "git commit -a")

Git 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 - git sa stále trápi tým, že stav tohto súboru nebol nikdy zapamätaný, a chcel by ho sledovať. So súborom hello.c má git iný problém - to, že ho má sledovať vie. Všimol si však, že tento súbor sa aktuálne líši od stavu, v ktorom bol naposledy zapamätaný a dáva nám na výber z dvoch možností ako s touto situáciou naložiť. Jednak nám hovorí, ako máme postupovať, ak chceme do repozitáru uložiť nový, zatiaľ nezapamätaný stav súboru. Ale dáva nám ešte aj druhú možnosť -- pripúšťa, že zmeny v súbore hello.c sme urobili omylom, a že sa chceme vrátiť k jeho pôvodnému stavu a oznamuje nám, že to sa dá pomocou príkazu git checkout. Povedzme, že Jožko Mrkvička si je zmenami v súbore, ktoré vykonal istý a chce ich zapamätať. Vykoná preto nasledujúce príkazy:

git add ./src/hello.c
git commit -m "vylepsenie programu hello, drobna zmena vo vypise retazca hello world"

No a povedzme, že Jožka už nebaví počúvať git ako sa sťažuje, že v repozitári je nesledovaný súbor a tak začne sledovať aj ten:

git add .gitignore
git commit -m "do repozitara pridane .gitignore"

Ak sa gitu opýtame na stav repozitára teraz, dozvieme sa toto:

On branch master
nothing to commit, working tree clean

Git tým oznamuje, že v repozitári je všetko v stave, s ktorým nemá problém. Konkrétne to znamená, že aktuálna podoba súborov je zapamätaná a že v repozitári sa nenachádza žiaden neignorovaný nesledovaný súbor. Git je spokojný, tu aktuálne nie je čo robiť. Predstavme si, že je spokojný aj Jožko Mrkvička a po dni plnom programovania sa ide poriadne vyspať. Keď na druhý deň ráno vstane a chce pokračovať v programovaní, v repozitári nájde nie len aktuálne podoby zapametaných súborov, ale aj historiu ich 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. Git mu vie pomôcť. Existuje príkaz, ktorý zobrazí históriu všetkých doposial vykonaných commitov na repozitári. Vyzerá to takto:

git --no-pager log

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

commit 478beebe94fc76adca1961447ec16d107f0d5ea7
Author: jozko.mrkvicka@zajax <jozko.mrkvicka@gmail.com>
Date:   Thu Feb 14 02:43:16 2019 -0900

    do repozitara pridane .gitignore

commit 267a0cd0ac29b5572b7ba0f0bd9095d785726a7c
Author: jozko.mrkvicka@zajax <jozko,mrkvicka@gmail.com>
Date:   Thu Feb 14 02:42:56 2019 -0900

    drobna zmena programu hello, vylepsenie vo vypise retazca hello world

commit dcf98f3f6a67e30749f328f2737b6aa9726c90cc
Author: jozko.mrkvicka@zajax <jozko.mrkvicka@gmail.com>
Date:   Thu Feb 14 02:09:52 2019 -0900

    prvotny stav repozitara

Git nám oznamuje, že stav repozitára bol zapamätaný zatiaľ trikrát. Vo všetkých 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, a pri každom komite vidíme aj krátky popisný reťazec, ktorým sme vysvetlili o čo v danom commite išlo. Navyše je každý komit uvedený svojim pomerne dosť neintuitívnym menom.

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čov je linuxovská aplikácia gitk, ak ju spustíte z adresára, ktorý patrí gitovskému repozitáru, okamžite Vám zobrazí historiu jednotlivých komitov v prehladnej grafickej podobe.

Úmyselné rozvetvenie histórie (branch)

Úmyselné zvetvenie histórie (merge)

Zhrnutie miestnej agendy

Nemiestne aktivity

Receptár používania GITu práve píšem. Recyklujem pri tom starší text, ktorý sa týkal inej, podobnej technológie známej ako Mercurial. Až po toto miesto je text už úspešne zrecyklovaný, to znamená prerobený na rozprávanie o GITe. To čo nasleduje za týmto miestom nemožno brať vážne -- je napríklad pravdepodobné, že sa to ešte stále týka Mercurialu.

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 bitbucket 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. O tomto reťazci (celom, vratane prefixu https://) budeme hovoriť ako o ADRESA_REPOZITARA.

Spriahnutie vzdialeného repozitára s miestnym repozitárom

Teraz v príkazovom riadku na miestnom počítači nastavte aktuálny adresár na adresár miestneho repozitáru, ktorý chcete spárovať s repozitárom na bitbuckete. Následne vstúpte do podadresára .hg a editujte súbor hgrc. Konkrétne na jeho začiatok pridajte tieto dva riadky:

[paths]
default = ADRESA_REPOZITARA

kde ADRESA_REPOZITARA je reťacez vysvetlený vyššie. Zmeny uložte. Týmto ste svojmu miestnemu repozitáru vysvetlili, že na internete sa nachádza vzdialený repozitár na ktorom sa budú, ak o to požiadate, zrkadliť jeho zmeny.

S jedným vzdialeným repozitárom možno spriahnuť viacero miestnych repozitárov. Ak napríklad na jednom projekte pracujete na viacerých počitačoch, spriahnite s bitbucketovským repozitárom miestne repozitáre tohoto projektu na všetkých počitačoch kde sa tento nachádza. Ak na jednom projekte pracuje viacero programátorov, každý z nich môže spriahnuť svoj miestny repozitár s dohotnutým spoločným repozitárom na bitbuckete (i keď toto nie je preferovaný spôsob zdielania zmien).

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

Zrkadlenie zmien miestneho repozitára na spárovanom bitbucketovskom repozitári sa nedeje automaticky. Ak vykonáte na miestnom repozitári commit (alebo viac commitov), tento sa neprejaví na jeho bitbucketovskom zrkadle. Ak chcete, aby sa tieto zmeny preniesli aj na bitbucket, musíte to mercurialu prikázať. Takto:

hg push

Mercurial od vás následne žiada prístupové heslo k mercurialu (bolo by nepríjemné, keby vám mohol k repozitáru prihadzovať commity len tak kde-kto) a po jeho úspešnom zadaní sa jednotlivé commity prenášajú po šifrovanej linke na bitbucket. Mercurial tento proces skromne komentuje.

Mercurial neprenáša celú históriu zmien repozitáru. Prenášajú sa iba tie commity, ktorými sa miestna verzia histórie líši od histórie na bitubuckete. Ak sa teraz pozriete na bitbucketovskú stránku svojho repozitára a kliknete kartu "commits" uvidíte tam históriu jednotlivých commitov. Na vrchu tejto histórie by sa mali nachádzať čerstvo prenesené commity.

Môže sa stať, že tento proces sa skončí nezdarom (mercurial v takom prípade frfle). Toto sa stáva ak časť vašej miestnej histórie nie je na bitbuckete a súčasne časť bitbucketovskej histórie nie je u vás. Úplne štandardne k tomu dochádza, ak má k jednému bitbucketovskému repozitáru prístup väčšie množstvo ľudí (kým programujete v miestnom repozitári, váš kolega pushuje na bitbucket svoje zmeny). V takej situácii treba takzvane vyriešiť konflikt. Tento tutoriál o riešení konfliktov zatiaľ nepojednáva.

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

Možnosť prenášania zmien z miestnych repozitárov na bitbucket by nebola na nič, keby sa zmeny nedali prenášať aj opačným smerom, z bitbucketu do miestneho repozitára. Je samozrejmé, že sa to dá - z adresára repozitáru stačí spustiť tento príkaz:

hg pull

Mercurial si od vás vyžiada heslo (opäť, mohlo by byť nebezpečné keby si stav vášho repozitára mohol stiahnuť ktokoľvek) a po jeho úspešnom zadaní sa jednotlivé commity prenášajú po šifrovanej linke do miestneho repozitára. Merciurial tento proces skromne komentuje.

Pro prenesení commitov do miestneho repozitára sa však jeho stav automaticky nenastaví na úroven najčerstvejšieho commitu. Mercurial už novú, čerstvo stiahnutú históriu zmien z bitbucketu úspešne reprezentuje ale aktuálny stav nenastaví na posledný pribudnuvší commit. Aby sa to stalo, musite to mercurialu prikázať. Takto:

hg update

Od tohoto okamžiku sa váš mercurialovský repozitár nachádza v stave, v ktorom sa nachádzal repozitár uživateľa, ktorý ako posledný pushoval na bitbucket.

V prípade, že stav miestneho repozitára medzičasom divergoval od stavu bitbucketovského repozitára, príkaz hg update nezbehne. Problém je, že podobne ako v prípade pushovania na bitbucket, treba najprv vyriešiť konflikty. O tom neskôr.

Vytvorenie miestnej kópie vzdialeného repozitára (clone)

Programujete, v miestnom repozitári si zapamätávate zmeny a tieto zmeny pushujete na bitbucket. Zatial sú v hre dva repozitáre - jeden miestny a jeden na bitbuckete. Čo ak chcete na projekte pracovať pri dvoch rôznych počítačoch? Hodilo by sa, keby ste vedeli kompletne celú históriu projektu stiahnuť z bitbucketu na počítač, na ktorom nikdy žiadny miestny repozitár s projektom nebol. Robí sa to pomocou príkazu:

hg clone ADRESA_REPOZITARA

kde reťazec ADRESA_REPOZITARA je bitbucketovská adresa, ktorú sme diskutovali už vyššie. Po zbehnutí tohoto príkazu vám na disku pripudbe nový adresár a v ňom presná kópia stavu, ktorý je uložený na bitbuckete, vrátane celej histórie jeho zmien. Až na jeden detail - do konfiguračného súboru hgrc v adresári .hg treba pridať riadky, ktoré už poznáme. Ak sa vrátime k príbehu našeho fiktívneho programátora, Jozefa Mrkvičku, mohli by tieto riadky vyzerať napríklad takto:

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

Všimnite si jednu zmenu. Kým pôvodne Jozef tvrdil, že pracuje na počítačí zajax, teraz tvrdí, že pracuje na počítačí medvex. Je to pravdepodobné - veď sedí za iným počítačom, než na ktorom pôvodne repozitár založil. Toto rozlišovanie počítačov má jednu výhodu. Keď sa pozrie na históriu zmien, hneď vidí, pri ktorom počítači vykonal ten ktorý commit. Nemusím vysvelovať, prečo môže byť pohodlné mať takúto informáciu k dispozícii.

KMaDGWiki: GitReceptar (last edited 2019-02-18 13:32:09 by sarkoci)