Výlet do říše verzí

27. 2. 2003
Doba čtení: 7 minut

Sdílet

Nástrojů, které umí udržovat přehled o verzích projektů a vracet se do historie, není zrovna málo; my si v tomto seriálu nejdříve ukážeme, co je to a jak funguje RCS, poté se ponoříme do světa CVS, který důkladně prozkoumáme, a v závěru se doufejme opět vynoříme, zhluboka se nadechneme a řekneme si, proč CVS není vlastně zdaleka ideální a co s tím.

Předpokládám, že pokud nejste zrovna grafik nebo hudební skladatel, obvykle pracujete na něčem, co nabývá podoby textových souborů, ať už je to zdroják, skript, konfigurační soubor, webová stránka, článek pro roota nebo román. Nezřídka se pak zvláště při dlouhodobějším udržování souboru ukáže, že by nebyl až tak špatný nápad udržovat si přehled, jak se soubor s časem měnil, případně možnost se vrátit k jeho starší verzi.

Pokud vás zajímá, na jakém principu funguje CVS a jak se s ním pracuje, čtěte dále, i když se dnes budeme bavit pouze o RCS — ono totiž CVS je ve skutečnosti v zásadě RCS hezky zabalené tak, aby se v něm rozumně daly dělat projekty sestávající z více souborů, a to ve více lidech a případně i přes síť. Společné věci (například systém číslování revizí, větvení apod.) vysvětlím už u RCS a nebudu je později příliš opakovat.

RCS (Revision Control System, česky Systém pro správu revizí) je nástroj, který umožňuje udržovat si přehled ve vývoji určitého souboru — kdy jsme v něm co změnili, jak vypadal tehdy a tehdy, kdo měl jakou změnu na svědomí (i když pravda je, že podpora pro více uživatelů se dá nazvat mnoha přívlastky, ovšem rozhodně ne komfortní) apod. RCS pracuje s jednotlivými soubory, nikoliv s celými adresáři či projekty, proto sice pro správu větších projektů není příliš vhodný, ovšem naopak pro údržbu jednotlivých souborů může být užitečnější než CVS právě díky své výjimečné jednoduchosti a efektivnosti. Obecně CVS použijeme tam, kde často děláme změny v mnoha souborech, které na sobě navzájem závisejí (typicky měníme výrazněji zdrojové kódy), RCS pak je lepší používat, když změny, které děláme, nejsou provázány se změnami v jiných souborech (např. konfigurační soubory nebo jednoduché skripty).

Abyste se ve změnách, které budete postupně dělat, vyznali, bylo by dobré si každou revizi souboru nějak označit. Obvykle to dělá RCS automaticky, každé revizi přiřadí určité jednoznačné číslo; začíná na 1.1 a postupně zvyšuje druhé číslo (1.2, 1.3, …, 1.859, 1.860, …). První číslo obvykle zůstává 1, zvětšit ho můžete ručně, pokud jste například dosáhli nějakého důležitého milníku a chcete, aby to na číslech revizí bylo jasně vidět; například jste zásadně přeorganizovali celý obsah souboru, konfiguračnímu souboru jste upgradovali balík, který ho využívá apod. — bereme si dle chuti, avšak střídmě. Ještě poznamenám, že se v praxi často můžete setkat i s čísly revizí, které jsou numericky o něco bohatší (1.1.2.3.2.41) — vysvětlíme si je příště, až si budeme povídat o větvení vývoje.

Vlastní používání RCS je poměrně triviální. Obvykle se používají zejména dva příkazy: pomocí příkazu ci (Check In) dostáváme data dovnitř (‚checkinujeme je‘; méně zvrhle to můžeme nazvat registrací změn) a příkazem co (Check Out) dostáváme data ven (‚checkoutujeme je‘). Přitom nemusíme před registrací souboru do RCS nic zvláštního nastavovat, stačí pouze použít standardním způsobem příkaz ci.

Je na čase tedy konečně zkusit RCS k něčemu použít. Nuže, vytvoříme si nějaký jednoduchý soubor:

pasky@machine:~/rcstest$ cat >ahoj <<EOF
Ahoj
Zdravím
Dobrý den
EOF

A teď ho zaregistrujeme — ci po nás bude chtít nějaký stručný popis, co je tento soubor zač (všechny podobné eseje, které budeme kdy zadávat, ukončíme tečkou umístěnou na zvláštním řádku):

pasky@machine:~/rcstest$ ci ahoj
ahoj,v  <--  ahoj
enter description, terminated with single '.' or end of file:
NOTE: This is NOT the log message!
>> Soubor s pozdravy.

>> Na každém řádku je jeden pozdrav, každý pozdrav začíná velkým
>> písmenem a nekončí ničím zvláštním.
>> .
>> initial revision: 1.1
>> done

Výborně, odteď máme již tuto verzi v RCS (jako 1.1) a můžeme se k ní kdykoliv vrátit. Ale ouha! Soubor ahoj nám zmizel, místo něho se nám sice objevil soubor ahoj,v, jeho obsah je však nějaký podivný. Co se stalo? Ke každému souboru, se kterým pracujeme pomocí RCS, se vytvoří ještě jeden pomocný soubor, který obsahuje kompletní historii vaší práce na onom souboru — najdeme zde kromě administrativních informací i log, originální obsah souboru a popis změn mezi jednotlivými revizemi v tzv. delta formátu (pro nás zhýčkané unified diffy lehce hrůzostrašném); podrobný popis naleznete v manuálové stránce rcsfile(5). Pokud vás adresář pocukrovaný těmito RCS soubory děsí, stačí vytvořit podadresář RCS/ a ,v soubory do něj přesunout; všechny RCS utility se při vyhledávání těchto souborů nejdříve podívají do tohoto podadresáře a pak teprve do aktuálního adresáře.

Nu dobrá, ovšem proč nám zmizel náš milý původní soubor? Aby RCS umožnilo sdílení souborů mezi několika uživateli, používá mechanismus zamykání souborů — v jednom čase tak obvykle může na souboru pracovat pouze ten jeden uživatel, který má soubor zamknutý, jemu jedinému totiž RCS dovolí zaregistrovat změny, které provedl. Přitom se samozřejmě vypaří uživatelův zámek a s ním i pracovní kopie souboru; pokud se nám mizení souborů nelíbí, můžeme příkazu ci přidat parametr -l (pokud chceme, aby soubor zůstal uzamčený) nebo -u (pokud chceme zámek odstranit). Blíže si o těchto temných záležitostech sdílení a zamykání souborů povíme příště, nyní nám stačí se ještě zmínit, jak si pracovní kopii poslední revize souboru vytáhnout zpět do reálného světa. Přichází tedy čas na druhý základní příkaz, co.

pasky@machine:~/rcstest$ co ahoj
ahoj,v  -->  ahoj
revision 1.1
done

Ejhle, opět se nám náš soubor vyloupl na světlo boží, dokonce ve své původní podobě. Nicméně soubor není zamčený, takže v něm nemůžeme dělat změny; tedy můžeme, ale nemůžeme je poté zaregistrovat. Náš soubor zamkneme příkazem rcs -l ahoj, ovšem je často asi praktičtější zamknout soubor rovnou při checkoutu, stačí přidat příkazu co parametr -l.

Je moc pěkné, že už soubor umíme dostat do RCS a zpátky ven, ale asi by už bylo na čase RCS konečně k něčemu využít. Nejdříve si vytvoříme další verzi souboru a zaregistrujeme ji:

pasky@machine:~/rcstest$ echo Dobrý večer >>ahoj
pasky@machine:~/rcstest$ ci -l ahoj
ahoj,v  <--  ahoj
new revision: 1.2; previous revision: 1.1
enter log message, terminated with single '.' or end of file:

>> Přidán pozdrav "Dobrý večer".
>> .
done

Tak, nyní už je poslední revize souboru ahoj 1.2, do které jsme přidali řádek s dalším pozdravem. Pokud bychom náhodou revizi chtěli přiřadit jiné číslo (pokud se nechcete dostat do vážných psychických problémů, doporučuji používat pouze ke zvyšování prvního čísla revize; a samozřejmě při větvení, o tom však později), můžeme přidat parametr ve stylu -r2.1. Není ovšem na škodu některým verzím přiřadit symbolická jména, abychom se k nim mohli dobře vracet: určitě pro většinu z váš bude příjemnější psát ‚redhat7_2‘ místo 2.394, pokud se chcete vrátit k verzi konfiguračního souboru, která byla aktuální po upgrade systému na RedHat 7.2. Stačí na příkazovou řádku dopsat -nredhat7_2.

Každá revize má přiřazenu tzv. log message, tedy stručný souhrn změn oproti předchozí verzi — záleží jenom na vás, co všechno budete do tohoto souhrnu psát, ovšem je dobré být dostatečně deskriptivní; možnost zběžného prohlížení, co všechno se v minulosti se souborem dělo, právě pomocí soupisu těchto zpráv je často velmi užitečná. Log message můžete zadat i přímo na příkazový řádek, stačí příkazu ci přidat parametr -m"Přidán pozdrav \„Dobrý večer\“.".

K vypsání kompletní zprávy o stavu a historii souboru nám poslouží příkaz rlog, který si bere za parametry opět jména souborů, o kterých se chceme něco dozvědět. Obvykle obdržíme o souboru základní informace a seznam všech revizí, včetně autorů změn a log messages (vida, už jsou užitečné). Parametrem -r můžeme omezit výpis jenom na určitý rozsah revizí, čísla revizí pak oddělíme dvojtečkou: tedy například -r1.2:1.15 vypíše informace od revize 1.2 po revizi 1.15. Dalšími parametry můžeme nechat vypsat jenom určité údaje, omezit výpis pouze na uzamčené soubory apod. Podrobné prostudování možností tohoto příkazu přenechám laskavému čtenáři, který může veškeré relevantní informace najít v manuálové stránce rlog(1).

Poslední základní funkcí RCS je generování diffů (popisů rozdílů) mezi libovolnými dvěma revizemi souboru. Je libo si prohlédnout rozdíly například mezi revizí 1.1 a 1.2? Stačí říci…

ict ve školství 24

pasky@machine:~/rcstest$ rcsdiff -u -r1.1 -r1.2 ahoj
==============================================================
RCS file: ahoj,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ahoj        2003/02/14 02:20:27     1.1
+++ ahoj        2003/02/19 20:15:32     1.2
@@ -1,3 +1,4 @@
 Ahoj
 Zdravím
 Dobrý den
+Dobrý večer

Příkaz rcsdiff kromě parametru -r (pokud vynecháme ten druhý, porovná danou revizi s aktuálním stavem souboru, pokud vynecháme i ten první, porovná s aktuálním stavem souboru poslední revizi) přijímá téměř všechny parametry příkazu diff. Mimochodem přímo výstup příkazu rcsdiff můžeme použít jako patch, stejnojmenný program totiž ignoruje (nebo se o to alespoň snaží) cokoliv před i za samotným diffem (což je nepříliš využívaná, i když velmi užitečná vlastnost).

Příště si povíme něco více o zamykání souborů a spolupráci více uživatelů, také se dozvíte, proč a jak větvit vývoj souboru, a určitě se dostane i na nahrazování klíčových slov (aneb co je to $Id: versions1,v 1­.2 2003/02/19 21:52:45 pasky Exp pasky $).