Systémy na údržbu verzí

Martin Vejnár, xvejnar1@fi.muni.cz

Obsah

Přehled

Důvody, proč používat některý z nástrojů pro správu verzí, jsou hned dva.

Repository

Všechny dnešní systémy na údržbu verzí ukládají svoje data do repository. Repository není nic jiného, než uložiště seznamu změn (neboli commitů, changesetů nebo revizí), které byly v projektu učiněny. Do repository se data pouze přidávají, díky tomu lze z repository získat libovolně starou revizi projektu.

Repository může být pro projekt jen jedno, potom hovoříme o centralizovaném systému, nebo může být rozděleno na více částí (třeba tak, že každý vývojář má své vlastní repository), potom mluvíme o distribuovaném systému na správu verzí.

Commity nejsou v repositoru uloženy libovolně, mají mezi sebou vztahy. Například každý commit, kromě toho úplně prvního, má svého předka. V některých systémech mohou mít commity i více předků, to v případě, že došlo ke sloučení dvou vývojových větví.

Verzovací systém většinou umožňuje commity pojmenovat, neboli přiřadit jim tagy (tags).

Řešení současného vkládání změn

Pokouší-li se dva vývojáři modifikovat stejnou jednotku informace (to může být soubor, nebo třeba řádek textového souboru), nastává konflikt a obě změny nemohou uspět. Systémy pro správu verzí tento problém řeší dvěma možnými způsoby.

Lock-modify-unlock. Chce-li uživatel modifikovat nějaký soubor, musí jej nejprve v repository uzamknout. Potom provede změny, uloží je do repository a soubor odemkne. Tímto se druhému uživateli zabrání v dělání modifikací, které by potom bylo nutné zahodit. Tento přístup má výhodu v tom, že nikdy nedojde ke konfliktům. Systémy jako Visual SourceSafe nebo Perfoce používají tento přístup.

Copy-modify-merge. Oba uživatelé mohou v souboru dělat změny současně. Tomu rychlejšímu se podaří změny do repository uložit, tomu druhému commit selže, je nutné nejprve sloučit změny prvního uživatele. Verzovacímu systému se může podařit změny sloučit automaticky, občas však slučování vyžaduje uživatelův zásah. Tento přístup mnohem lépe scaluje na větší počet uživatelů. Většina dnešních verzovacích systémů včetně CVS, Subversion, git, Mercurial, ClearCase atd. používá tuto strategii.

CVS

CVS (Concurrent Versioning System) je klasický centralizovaný systém na správu verzí. V repository je uložen souborový strom a každý soubor je verzován zvlášť (tedy pro každý soubor existuje v repository graf commitů).

V dnešní době je CVS vytlačováno systémem Subversion.

Subversion

Subversion je alternativa k CVS. Tyto dva systémy si jsou v mnoha ohledech podobné, ale najdeme i významné rozdíly.

Subversion spravuje revize stromů, nikoliv jednotlivých souborů. Každému stromu je přiřazeno číslo revize, první (prázdný) strom, který vzniká při vzniku repository, má číslo 0. Strom může být libovolným způsobem strukturován, může obsahovat textové i binární soubory a dokonce i symbolické linky. Commity jsou atomické: dojde-li ke dvěma konfliktním commitům současně, uspěje pouze jeden. V tom se Subversion liší od CVS, kde commity byly atomické pouze pro jednotlivé soubory. Commit celého adresáře tedy mohl uspět jen částečně.

Kopírování podstomů je levná operace, v Subversion se proto kopírování používá na vytváření větví a tagů. Subversion větve ani tagy explicitně nepodporuje.

Každý soubor může mít kromě svého obsahu připojené pojmenované atributy. Některé z nich mohou ovlivňovat chování SVN, takové atributy mají jméno začínající na svn:. Příkladem může být atribut svn:eol-style, který určuje, jak bude SVN nakládat s konci řádků.

Domovská stránka Subversion je http://subversion.tigris.org. Výborná dokumentace je dostupná na adrese http://svnbook.org

Instalace na gentoo

emerge -v subversion

Všechny administrativní úkony se provádějí programem svnadmin. Vytvoříme pomocí něj repository.

svnadmin create /path/to/repository

Nyní můžeme nakonfigurovat server apache, aby toto repository zpřístupnil pomocí modulu mod_dav_svn. Potom bude možné k repository přístupovat protokolem http. Nechceme-li kvůli subversion instalovat apache, můžeme použít program svnserve, který je dodávaný se subversion. Jde o jednoduchý, nenáročný server, který se konfiguruje pomocí souboru /path/to/repository/conf/svnserve.conf.

[general]
realm = My First Repository
password-db = passwd

anon-access = read
auth-access = write

Takto dáme anonymním uživatelům přístup pro čtení a autentikovaným uživatelům přístup pro zápis. Soubor passwd musí mít stejný formát, který používá server apache a je možné ho vytvořit utilitou htpasswd2.

Chceme-li mít nad autorizací větší kontrolu, můžeme použít následující konfiguraci.

[general]
realm = My First Repository
password-db = passwd
authz-db = authz

Soubor authz může vypadat například takto.

[/]
* = r
avakar = rw

[/junk]
* = rw

Tako bude mít uživatel avakar přístup k celému repository pro zápis, ostatní uživatelé (včetně těch anonymních) budou moct repository číst a zapisovat do adresáře /junk.

Přístup k repository

Uživatel s repository pracuje pomocí programu svn. Nápovědu k tomuto programu lze získat příkazem help.

svn help

Uživatel může pracovat se vzdáleným repository přímo a dělat administrativní úkony jako vytváření adresářů nebo kopírování souborů.

svn mkdir svn://thoe-alpha/trunk -m "Inicializace repository"

Tímto se vytvoří nová revize, ve které bude oproto předchozí revizi navíc přidán adresář /trunk. Každý commit má přiřazený komentář, který se zadává pomocí parametru -m.

Cesta k repository se programu svn předává ve formě url. Protože používáme server svnserve, používáme k přístupu protokol svn. K repository je možné přistupovat i přes zabezpečený tunel, v tom případě k protokolu připojíme jméno tunelu, napřiklad svn+ssh. Alternativami jsou protokoly http a https, které ale vyžadují server apache. Máme-li repository přístupné lokálně, můžeme k němu přistupovat pomocí protokolu file.

Naimportujme nyní projekt do repository.

svn import ~/my-project svn://thoe-alpha/trunk/my-project -m "Import projektu my-project"

Jiný uživatel si může projekt z repository vytáhnout pomocí příkazu checkout (nebo co).

svn co svn://thoe-alpha/trunk/my-project

Takto se v aktuálním adresáři objeví adresář my-project s pracovní kopií projektu. Čas od času (a zejména před uskutečněním commitu) je potřeba stáhnot z repository změny do pracovní kopie pomocí příkazu update.

svn up

Při updatu může dojít ke konfliktu lokálních změn a začleňovaných změn z repository. V takovém případě se v souborech konflikty označí. Uživatel je ručně opraví a konflikt označí za vyřešení (příkaz svn resolve). Po uložení změn se použije příkaz commit.

svn ci -m "Kamera nyní umí režim cool-cam."

Mercurial

Mercurial je distribuovaný systém na správu verzí. Vzniká ve stejné době jako git (ten je používán pro správu verzí linuxového jádra) -- tedy po komercializaci systému BitKeeper. Mercurial používá například Mozilla.

Na Gentoo nainstalujeme Mercurial snadno.

emerge -v mercurial

Protože je Mercurial distribuovaný verzovací systém, repository bude umístěné na lokálním počítači.

hg init ~/my-project

Nevytváříme-li nový projekt, budeme chtít vytvořit kopii jiného repository. Zde je několik možností, jak to udělat.

hg clone ~kas/my-project
hg clone http://project.server.cz/my-project
hg clone ssh://avakar@thoe-beta/my-project

Mercurial se v mnoha ohledech chová podobně jako subversion. Soubory můžeme přidávat, odebírat, přesouvat pomocí příkazů hg add, hg remove a hg move. Po repository se můžeme volně pohybovat pomocí příkazu hg update. Na rozdíl od subversion se všechny commity budou ukládat do lokálního repository a nebudou nikým jiným viditelné. Repository je potřeba navzájem synchronizovat.

hg pull path/to/another/repository

Tento příkaz zkopíruje všechny nové commity z druhého repository do našeho vlastního. V tuto chvíli se může stát, že máme v repository dva commity, které nemají žádné potomky (těm se říká heads) -- jeden je náš poslední commit a druhý je poslední commit z druhého repository. Nyní budeme chtít tyto dva commity sloučit, použijeme k tomu příkaz merge.

hg merge

Podobně jako subversion i Mercurial se pokusí změny sloučit automaticky (ve skutečnosti Mercurial použije nějaký z programů na slučování, který najde na lokálním počítači nainstalovaný) a pokud se mu to nepodaří, nechá nás konflikty vyřešit ručně. Následující commit pak bude mít dva předky.

Kromě modelu pull je možné změny propagovat i metodou push.

hg push path/to/another/repository

V takovém případě však musíme mít ke vzdálenému repository přístup pro zápis.

Na rozdíl od Subversion, Mercurial explicitně větve a tagy podporuje. Commit označíme pomocí příkazu hg tag, s větvemi můžeme pracovat pomocí příkazu hg branch. Podobně jako v Subversion ale bývá zvykem místo větví vytvářet copie celých repository.

Chceme-li repository zveřejnit, můžeme buď repository nasdílet lokálně (případně přes ssh), nebo použít http server a program hgweb.cgi.

Mercurial má rozsáhlou dokumentaci dostupnout na adrese http://hgbook.red-bean.com/, domovská stránka projektu je http://www.selenic.com/mercurial/wiki.

Literatura