V zásadě lze odlišit dva hlavní způsoby použití systémů RC (Revision Control):
První použití je jednodušší a jediným jeho cílem je mít možnost označit verze souborů v určité fázi vývoje a kdykoli se k jednotlivým fázím vracet.
Druhé použití je především v oblasti vývoje, kde je potřeba skloubit simultánní úpravy prováděné více vývojáři nad stejným zdrojovým kódem. (A mimo to také zdrojové kódy v aktuálním stavu zpřístupnit světu.)
Systémů pro správu verzí existuje mnoho. Porovnání jejich vlastností je nad hranice tohoto referátu (zájemce lze odkázat na tuto wiki page). Uveďme si tedy jen pár nejznámějších:
Zdrojové soubory, které podléhají kontrole verzí jsou ukládány do repository, která obsahuje (především) prvotní verzi + popis změn ve verzích následujících. Je tedy možné z ní vytáhnout libovolnou historickou revizi. Jednotlivé revize jsou označeny komentářem a jednoduchým způsobem lze kontrolovat, kdo, co a kdy změnil. Dnes běžné systémy umožňují přístup po síti - buď pomocí démona (CVS) nebo i bez něj (SVN, klička přez ssh).
Kopie souborů z repository, se kterou uživatel pracuje se nazývá working copy.
CVS je možná nejznámější, má ale některé zásadní nevýhody (přejmenování souborů, potřeba démona pro síťování, commity kompletních dat apod.). Proto si použití RC systému ukážeme na jeho mladším sourozenci SVN.
Scénář našeho příkladu začíná rozhovorem se šéfem...
Šéf: pane Prýmek, zdá se mi, že poslední dobou nějak málo pracujete. Proto jsem se rozhodl, že začnete pracovat na projektu Barbarossa, o kterém jsme mluvili na poradě. Vytvoříte repository na Fíkovníku a do měsíce chci vidět funkční prototyp. Máte k ruce pět lidí.
Nejmenovaný programátor (NP): Ale když správci Fíkovníku jsou strašní flákači, jak je donutím, aby mně tam nainstalovali CVS server?
Šéf: Pochopitelně použijete SVN, ne? Ježkovyvoči!
Nejmenovaný programátor zarputile odchází s poněkud vystrašeným výrazem...
NP po prostudování manuálu SVN začne tím, že si vytvoří repository (pozor na práva!):
[fikovnik ~] svnadmin create /mnt/data/public/svnRepo
Získali jsme adresář svnRepo
s vnitřní strukturou, která je pro repository
potřeba:
[fikovnik ~] cd /mnt/data/public/svnRepo [fikovnik /mnt/data/public/svnRepo] ls README.txt conf dav db format hooks locks [fikovnik /mnt/data/public/svnRepo] cat README.txt This is a Subversion repository; use the 'svnadmin' tool to examine it. Do not add, delete, or modify files here unless you know how to avoid corrupting the repository. If the directory "db" contains a Berkeley DB environment, you may need to tweak the values in "db/DB_CONFIG" to match the requirements of your site. Visit http://subversion.tigris.org/ for more information.
Pro náš jednoduchý příklad je práce "admina" zmíněným jednořádkovým příkazem skončena.
Poté co má NP repository připravenou, může začít pracovat na projektu. (Nehodlá se moc přepracovat, takže začne zlehka.)
[fikovnik ~] mkdir -p delme/Barbarossa/trunk [fikovnik ~] cd delme/Barbarossa/trunk [fikovnik ~/delme/Barbarossa/trunk] echo A > MyFamousWork.txt
NP si projekt drze předem umístil do adresáře delme
, protože jakmile
jej vloží do repository, může jej klidně smazat. Vložení provede takto:
[fikovnik ~/delme] svn import . file:///mnt/data/public/svnRepo/ Adding Barbarossa Adding Barbarossa/trunk Adding Barbarossa/trunk/MyFamousWork.txt
A je to. Před dončením příkazu jej svn vyzvalo doplnit popis vkládané revize projektu pomocí $EDITOR (což tady není vydět, protože se to v HTML ukazuje opravdu obtížně). NP projekt s ulehčením smaže z disku, aby ho na desktopu žádná práce nestrašila... ještě je ovšem potřeba obvolat přidělených pět lidí a říct jim, ať na projektu začnou dělat ...a NP se může věnovat zajímavější činnosti - např. hraní Sid Meier's Civilization :)
[fikovnik ~/delme] rm -rf Barbarossa
...ovšem jen tak dlouho, dokud na chodbě neuslyší přicházet Šéfa. V tom případě potřebuje rychle zdrojáky zpátky a tvářit se, jak usilovně pracuje:
[fikovnik ~/MyMostImportantWork/Barbarossa] svn co file:///mnt/data/public/svnRepo/Barbarossa/trunk A trunk/MyFamousWork.txt Checked out revision 1. [fikovnik ~/MyMostImportantWork/Barbarossa] ls trunk MyFamousWork.txt [fikovnik ~/MyMostImportantWork/Barbarossa] echo "uff..." uff...
Šéf je ale starý programátorský harcovník. Je mu jasné, že se NP fláká. Dělá tedy že nic, NP dál hraje Civilizaci, dokud před koncem pracovní doby Šéf nepřijde k NP-ovu počítači a nenapíše:
[fikovnik ~/MyMostImportantWork/Barbarossa/trunk] svn log ------------------------------------------------------------------------ r1 | prymek | 2006-12-20 22:29:42 +0100 (Wed, 20 Dec 2006) | 2 lines Init import. ------------------------------------------------------------------------ [fikovnik ~/MyMostImportantWork/Barbarossa/trunk] svn status [fikovnik ~/MyMostImportantWork/Barbarossa/trunk] svn up U MyFamousWork.txt Updated to revision 3. [fikovnik ~/MyMostImportantWork/Barbarossa/trunk] svn log ------------------------------------------------------------------------ r3 | vomacka | 2006-12-20 22:54:16 +0100 (Wed, 20 Dec 2006) | 2 lines And even more important C added! ------------------------------------------------------------------------ r2 | vomacka | 2006-12-20 22:49:52 +0100 (Wed, 20 Dec 2006) | 2 lines Most important 'B' added! ------------------------------------------------------------------------ r1 | prymek | 2006-12-20 22:29:42 +0100 (Wed, 20 Dec 2006) | 2 lines Init import. ------------------------------------------------------------------------ [fikovnik ~/MyMostImportantWork/Barbarossa/trunk] svn diff -r 1 Index: MyFamousWork.txt =================================================================== --- MyFamousWork.txt (revision 1) +++ MyFamousWork.txt (working copy) @@ -1 +1,3 @@ A +B +C [fikovnik ~/MyMostImportantWork/Barbarossa/trunk] echo '!?!?' !?!?
Následuje výkřik: No to snad nemyslíte vážně! Tak to teda ne. Prototyp nechci mít za měsíc, ale za týden! Tak začněte sakra něco dělat!
Prvním příkazem totiž Šéf zjistil, že NP poslal na server teprve jednu revizi.
Druhým příkazem zjistil, že od commitu k této verzi NP ještě nic nepřidal.
Třetím příkazem tedy jeho zdrojáky aktualizoval na aktuální revizi.
Čtvrtým příkazem zjistil, že od první NP-ho revize už jiný člen týmu (vomacka
)
vložil dvě revize. A konečně pátým příkazem zjistil, že vomacka
zvládl dvakrát tolik práce co NP (protože NP vložil jen první revizi a diff aktuální revize
oproti první ukázal, že zatímco NP naprogramoval jenom A
, vomacka
zvládl přidat B
a C
).
NP je zdrcen, protože mu sice končí pracovní doba, ale bude si muset vzít práci ssebou domů. Podívejme se tedy, co bude doma dělat (všimněte si, že NP trpí zvláštním druhem konzolové samomluvy a všechny svoje kroky si komentuje).
prymek@mandlon:~/> # protoze mam na Fikovniku ssh ucet, muzu si stahnout aktualni Barbarossu pomoci prymek@mandlon:~/> # svn+ssh - na Fikovniku ani nemusi bezet zadny server tak jako napr. u CVS prymek@mandlon:~/> cd F-ckingWork/Barbarossa prymek@mandlon:~/F-ckingWork/Barbarossa> svn co svn+ssh://fikovnik/mnt/data/public/svnRepo/Barbarossa/trunk Password: A trunk/MyFamousWork.txt Checked out revision 3. prymek@mandlon:~/F-ckingWork/Barbarossa> cd trunk prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> svn info Path: . URL: svn+ssh://portal/mnt/data/public/svnRepo/Barbarossa/trunk Repository UUID: 67c7b1ae-0f25-0410-8d1a-ab94f0aab44b Revision: 3 Node Kind: directory Schedule: normal Last Changed Author: vomacka Last Changed Rev: 3 Last Changed Date: 2006-12-20 22:54:16 +0100 (Wed, 20 Dec 2006) prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> # je to dobry, vomacka uz nic nepridal, trouba jeden! prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> # musim ho trumfnout! prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> echo F >> MyFamousWork.txt prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> cat MyFamousWork.txt A B C F prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> # sakra! melo to byt D! No nic, vratim se zpatky prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> svn revert MyFamousWork.txt Reverted 'MyFamousWork.txt' prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> cat MyFamousWork.txt A B C prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> # ani jsem nemusel zadavat heslo a nic se nestahovalo prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> # jakto? prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> svn help revert revert: Restore pristine working copy file (undo most local edits). usage: revert PATH... Note: this subcommand does not require network access, and resolves any conflicted states. However, it does not restore removed directories. Valid options: --targets arg : pass contents of file ARG as additional args -R [--recursive] : descend recursively -q [--quiet] : print as little as possible --config-dir arg : read user configuration files from directory ARG prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> # uz si vzpominam... prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> cat .svn/text-base/MyFamousWork.txt.svn-base A B C
Nicméně našeho hrdinu čekají další potíže...
prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> echo D >> MyFamousWork.txt prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> svn commit Password: Sending MyFamousWork.txt Transmitting file data .svn: Commit failed (details follow): svn: Out of date: '/Barbarossa/trunk/MyFamousWork.txt' in transaction '4-1' svn: Your commit message was left in a temporary file: svn: '/home/prymek/F-ckingWork/Barbarossa/trunk/svn-commit.tmp' prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> #??? prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> svn up Password: C MyFamousWork.txt Updated to revision 4. prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> cat MyFamousWork.txt A B C <<<<<<< .mine D ======= Stejne jsem lepsi! >>>>>>> .r4 prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> # jakej blbec to tam dal? prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> svn log Password: ------------------------------------------------------------------------ r4 | vomacka | 2006-12-20 23:43:30 +0100 (Wed, 20 Dec 2006) | 2 lines Vomacka's declaration added. ------------------------------------------------------------------------ r3 | vomacka | 2006-12-20 22:54:16 +0100 (Wed, 20 Dec 2006) | 2 lines And even more important C added! ------------------------------------------------------------------------ r2 | vomacka | 2006-12-20 22:49:52 +0100 (Wed, 20 Dec 2006) | 2 lines Most important 'B' added! ------------------------------------------------------------------------ r1 | prymek | 2006-12-20 22:29:42 +0100 (Wed, 20 Dec 2006) | 2 lines Init import. ------------------------------------------------------------------------ prymek@mandlon:~/F-ckingWork/Barbarossa/trunk> # no jo, zas ten vomacka!
A tak se náš hrdina naštval a začal dál studovat manuál - a dokonce zjistil, co je
to tajemné trunk
, o němž návody říkaly, že by za názvem projektu
mělo být....
Adresáře, které je doporučeno vytvořit nad názvem projektu (Projekt/trunk,Projekt/tags,Projekt/branch)
trunk je "Hlavní větev" kódů. Je jen jedna.
tags je adresář obsahující projekt v nějakých podstatných (označených, tagged) stadiích - typicky release verzích (např. "/tags/opensync-0.10" obsahuje trunk ve stavu release 0.10).
branch slouží k umístění "alternativních vývojových verzí". Může sloužit k různým experimentům, které mohou být po otestování spojeny (merge) s trunk větví.
Podstatné je, že SVN (narozdíl od CVS) umí sledovat přesuny souborů apod., takže např. při vzniku nové tagged větve není potřeba nic skutečně kopírovat (úspora místa).
Přidání nového souboru do projektu
Změny se zobrazením autora
[fikovnik ~/MyMostImportantWork/Barbarossa/trunk] svn blame -r 4 MyFamousWork.txt 1 prymek A 2 vomacka B 3 vomacka C 4 vomacka Stejne jsem lepsi!
Změna souborů zařazených do projektu (obrovská výhoda oproti CVS!). Zachovává pouze rozdílové záznamy, zámky apod.
[fikovnik ~/MyMostImportantWork/Barbarossa/trunk] svn move MyFamousWork.txt MyBoringWork.txt A MyBoringWork.txt D MyFamousWork.txt
Vytvoření neverzované kopie projektu (tj. bez adresářů .svn
).
Zamčení části kódu proti změnám jinými uživateli.
Vypsání statusu souborů v aktuální working copy (změněný, zamčený, smazaný apod.)
Možností je spoustu - viz svn help st
Sloučení dvou různých verzí (např. trunk a branch/XY).
Provedeme po (manuálním) vyřešení konfliktních úprav. Odstraní soubory a příznaky týkající se konfliktů.
K souborům můžeme přidávat nejrůznější anotace.
$ svn proplist --verbose foo.c Properties on 'foo.c': svn:mime-type : text/plain svn:keywords : Author Date Rev owner : sally
S programy na kontrolu verzí se nemusí pracovat jen z příkazové řádky. existuje spousta nástrojů, které podporu verzování integrují do IDE, filemanagerů apod. Problém ale můžeme mít s tím, abychom našli pluginy pro ten který systém právě do všech nástrojů, které používáme (ale vzhledem k tomu, že jsou to vždy jen grafické frontendy k příkazům, tak to není taková tragédie.
Příkladem může být Cervisia
nebo scplugin
a spousta dalších pluginů pro netbeans, eclipse apod.
Úplně samostatnou kapitolou jsou nejrůznější webové procházeče repositories, které někdy slouží i pro širší management životního cyklu softwaru (viz např. trac).