V tomto článku zhrnieme spôsoby, akými je možné riešiť rozličné nečakané situácie pri používaní SCM softvéru Mercurial. Článok čerpá z Mercurial: The Definitive Guide Bryana O’Sullivana.
hg rollback
Príkazom hg rollback je možné vrátiť ostatnú transakciu. Za transakcie v Mercuriali považujeme operácie commit, pull, import, unbundle a push (ak sme na strane príjímateľa).
Typickým použitím je odstránenie poslednej revízie z histórie repozitára, ak sme zistili, že v nej chýba nejaký súbor, alebo sú v nej iné chyby. Rollback nezmení aktuálny obsah súborov – jednoducho len zmení status súborov aktualizovaných v poslednej revízii a revíziu odstráni z histórie. Napríklad:
$ hg status M changed_file ? myfile $ hg commit -m "zla revizia" $ hg status ? myfile $ hg log changeset: 16:b58daaf482f0 tag: tip user: Richard Laffers <rlaffers@gmail.com> date: Fri Jul 15 17:52:38 2011 +0200 summary: zla revizia changeset: 15:e54ac6044913 user: Richard Laffers <rlaffers@gmail.com> date: Fri Jul 15 11:39:20 2011 +0200 summary: predchadzajuca revizia
Typické, zabudol som do revízie 16 pridať súbor myfile. Pridávať ho ďalšou revíziou by bolo obludné riešenie. Na pomoc prichádza rollback:
$ hg rollback rolling back to revision 15 (undo commit) $ hg status M changed_file ? myfile
Ako vidieť, rollback vrátil repozitár do stavu pred chybnou revíziou 16. Teraz môžeme zabudnutý súbor pridať, a nanovo vykonať commit.
$ hg add adding myfile $ hg commit -m "opravena revizia" $ hg log changeset: 16:b82c3968a13d tag: tip user: Richard Laffers <rlaffers@gmail.com> date: Fri Jul 15 18:00:49 2011 +0200 summary: opravena revizia changeset: 15:e54ac6044913 user: Richard Laffers <rlaffers@gmail.com> date: Fri Jul 15 11:39:20 2011 +0200 summary: predchadzajuca revizia
História obsahuje len dobrú revíziu; chybná revízia z nej bola odstránená.
Rollback má však dve dôležité obmedzenia (!):
- funguje len 1 krok dozadu
- je nanič, ak sa chybná revízia už propagovala do iných repozitárov (napr. cez hg pull, hg push)
hg revert
Týmto príkazom môžeme vrátiť individuálne súbory na stav z ľubovoľnej revízie v histórii. Ak ho zavoláme bez prepínačov
hg revert myfile
Súbor bude zmenený do podoby v akej bol po poslednom commite (čiže v čase vytvorenia poslednej revízie).
hg revert -r 5 myfile
Súbor bude aktualizovaný na špecifikovanú verziu z revízie 5.
Pri operácii revert nám Mercurial zálohuje aktuálny stav do súboru myfile.orig.
Dôležité je uvedomiť si, že revert nevytvára ani neodstraňuje z histórie žiadne revízie, ani nemení aktuálny working directory. Revertnutý súbor má príznak M (modifikovaný) a do histórie bude pridaný až pri ďalšom commit-e.
Revertovaním je možné súbory odstrániť, resp. nanovo pridať do repozitára. Súbor sa odstráni z repozitára, ak revertujeme na revíziu, v ktorej ešte neexistoval. Získa príznak R (removed) – z disku sa však nevymaže, ostáva tam ako súbor nesledovaný Mercurial-om.
Naopak, ak revertujeme odstránený súbor naspäť do revízie, kedy ešte v repozitári existoval, súbor sa nanovo vytvorí, a bude mať príznak A (added).
hg update
Ak potrebujeme celý projekt vrátiť do stavu určitej revízie v minulosti, použijeme
hg update 14
Kde 14 je číslo revízie, na ktorú sa chceme vrátiť. Pred vykonaním update odporúčam najprv spraviť commit, pre uloženie všetkých aktuálnych zmien – inak sa premiešajú s verziou na ktorú budeme aktualizovať, alebo o ne úplne prídeme. Užitočné je volať update s prepínačom -c:
$ hg update -c 14 abort: uncommitted local changes
Mercurial nás upozorní, ak sa našiel ne-commitnuté zmeny.
Je dôležité si uvedomiť, že na rozdiel od operácie revert, update mení aktuálny working directory:
$ hg update -c 14 4 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg summary parent: 14:c30fe3356fc4 stara revizia branch: default
Ak by sme teraz zmenili súbory, vytvorí sa tým nová vetva repozitára (ktorú možno neskôr bude treba zlúčiť s predchádzajucou vetvou – to nechám na rozhodnutie developera podľa konkrétnej situácie).
$ echo zmena >> myfile $ hg commit -m "nova vetva" created new head $ hg glog @ changeset: 17:72c3062c8d1e | tag: tip | parent: 14:c30fe3356fc4 | user: Richard Laffers <rlaffers@gmail.com> | date: Fri Jul 15 18:44:42 2011 +0200 | summary: nova vetva | | o changeset: 16:b82c3968a13d | | user: Richard Laffers <rlaffers@gmail.com> | | date: Fri Jul 15 18:00:49 2011 +0200 | | summary: posledna revizia | | | o changeset: 15:e54ac6044913 |/ user: Richard Laffers <rlaffers@gmail.com> | date: Fri Jul 15 11:39:20 2011 +0200 | summary: predposledna revizia | o changeset: 14:c30fe3356fc4 | user: Richard Laffers <rlaffers@gmail.com> | date: Fri Jul 15 11:38:04 2011 +0200 | summary: stara revizia
Poznámka: Príkaz hg glog je dostupný len ak si aktivujeme rozšírenie Graph log.
Hocikedy je možné vrátiť sa na ostatnú revíziu príkazom
hg update
hg backout
Na nápravu chýb celej revízie, ktorá je už staršia (nemožno použiť hg rollback), použijeme príkaz
hg backout --merge -m "odstranenie zlej revizie 14" 14
Príkaz backout zlú revíziu z histórie neodstráni; namiesto toho vytvorí ďalšiu revíziu, ktorá neobsahuje zmeny zo zlej revízie.
Backout je už pomerne zložitá operácia, najmä ak medzi súčasným stavom a zlou revíziou v histórii prebehli i nejaké zlučovania (merge). Je potrebná opatrnosť a kontrola, či Mercurial vyriešil všetky konflikty správne.