Hlavní navigace

Výlet do říše verzí: větvení a slučování

2. 2. 2004
Doba čtení: 5 minut

Sdílet

Pojďme si opět poodkrýt některé další taje CVS. Dnes by to mohlo být zajímavé, prozradíme si totiž něco o větvení a slučování.

Občas je vhodné vytvořit si ve vývoji projektu jakousi větev, na které budeme pokračovat ve vývoji nezávisle na hlavním „kmenu“ historie souboru. Mezi nejtypičtější případy patří, pokud vydáme stabilní verzi produktu a hodláme ji nějakou dobu opatrovat a opravovat v ní chyby, zároveň však chceme pokračovat v normálním vývoji produktu. Pro stabilní verzi si tedy vytvoříme zvláštní větev, do které budeme pouštět pouze bugfixy. Druhý častý případ bývá, že chceme třeba implementovat nějakou velmi experimentální featurku, ale neradi bychom tím rozhodili celý ostatní vývoj. Vše tedy děláme ve vlastní větvi, kterou po pečlivém odladění sloučíme zpět do „kmenové“ větve.

Nutno předeslat, že CVS konkrétně operace větvení a slučování implementuje dosti nešťastně. Větvení má zejména problémy s efektivitou implementace — zvláště u velkých RCS souborů (tzn. velkých souborů s dlouhou a pohnutou historií) můžou být hlavně větve oddělivší se v dobách dávnějších poměrně náročné na checkout. Hlavní vývojovou větví by tedy vždy měla pokud možno být ta kmenová, neboli HEAD. Co je zase špatného na slučování, si povíme příště.

Větvení

Tagy, o kterých jsme dosud hovořili, pouze vyjadřovaly určitý okamžik v dějinách vašeho modulu. Ovšem existují ještě takzvané branch tagy, skrze které se realizuje právě výše popsané větvení. Branch tagy jsou – zjednodušeně řečeno – podobně jako obyčejné tagy v každém souboru asociovány s určitým číslem revize, ovšem v tomto případě je to ve skutečnosti číslo větve (to znamená, že tag NORMÁLNÍ může být asociován např. s 1.3 nebo 1.2.3.4, ovšem tag VĚTVOVÝ bude asociován třeba s 1.2.3 nebo 1.9.2). Branch tag vytvoříme příkazem cvs tag -b.

Pokud vycheckoutujeme z CVS strom s určitým branch tagem, samozřejmě bude stejně jako obyčejný tag sticky, tedy veškeré další akce se budou dít na dané větvi, které se budeme držet. To znamená, že každý další update nás nevrátí zpět na „kmenovou větev“, ovšem přinese nám případné další změny na naší aktuální lepkavé větvi.

Doufám, že jsem vás nyní již dostatečně zmátl, nastal tak asi čas na něco praktického. Nejdříve si tedy vytvoříme novou větev, nazvěme ji imaginativně například VETEV:

pasky@machine:~/test$ cvs tag -b VETEV
cvs tag: Tagging .
T ahoj
T zpivanky

Ovšem pokud teď chceme pracovat na této větvi, musíme se na ni přenést pomocí cvs update -r. Sice se jakoby nic nezmění, ovšem tag VETEV se stane sticky, tudíž všechny další operace budeme dělat na této větvi, nikoliv na HEADu.

pasky@machine:~/test$ cvs -Q status ahoj
==============================================================
File: ahoj Status: Up-to-date

Working revision: 1.2 Thu Apr 10 21:10:49 2003

Repository revision: 1.2 /home/pasky/cvsrepo/test/ahoj,v

pasky@machine:~/test$ cvs update -r VETEV
cvs update: Updating .
pasky@machine:~/test$ cvs -Q status ahoj
==============================================================
File: ahoj Status: Up-to-date

Working revision: 1.2 Thu Apr 10 21:10:49 2003
Repository revision: 1.2 /home/pasky/cvsrepo/test/ahoj,v
Sticky Tag: VETEV (branch: 1.2.2)

Globální parametr -Q způsobí, že výstup CVS je podstatně stručnější a obsahuje opravdu jen ty nejzajímavější údaje (takže článek bude kratší a já si vydělám méně peněz). Nyní bychom tedy měli pracovat v rámci větve, to si ostatně hned můžeme ozkoušet:

pasky@machine:~/test$ echo cau >>ahoj
pasky@machine:~/test$ cvs ci -m"Cau."
cvs commit: Examining .
Checking in ahoj;
/home/pasky/cvsrepo/test/ahoj,v  <--  ahoj
new revision: 1.2.2.1; previous revision: 1.2
done

Skutečně! Lajdavé čtenáře, kteří si opomněli prostudovat popis RCS, může zaskočit neobvyklé číslo verze, tak tedy pouze stručně: liché prvky v čísle revize jsou čísla větví, zatímco sudé prvky jsou čísla jednotlivých revizí „po cestě“. Tedy 1.2.4 znamená větev č. 4, vycházející z revize č. 2 na větvi č. 1. Čísla všech větví jsou sudá a nula se vynechává, jenom první větev je speciální a vlastně se jako větev ani moc nechová.

Slučování

Poté, co jsme si takhle hezky náš projekt rozvětvili, se často hodí mít možnost zase sloučit změny v určité větvi do jiné větve (například jsme si vytvořili z HEADu větvi VETEV a teď bychom změny chtěli sloučit zpět do HEADu).

Samozřejmě, že bychom mohli zkombinovat cvs diff a patch, ovšem to by bylo až příliš nešikovné. Proto CVS přichází s lokálním parametrem-j, který je k dispozici u příkazů checkout a update. Stačí tedy na HEADu provést cvs update -j VETEV a na náš pracovní strom budou aplikovány všechny změny z větve VETEV (od poslední revize, která byla společná pro obě větve). Tyto změny samozřejmě máme v ten okamžik pouze v naší lokální kopii a stále je musíte ručně commitnout.

Parametr -j je však chytřejší. Můžete je totiž uvést dva, a poté se na vaši aktuální kopii projektu aplikují pouze změny mezi revizemi specifikovanými parametry -j. Tedy příkaz cvs up -j VETEV1_1 -j VETEV1_2 do aktuálního stromu aplikuje veškeré změny mezi tagem VETEV1_1 a VETEV1_2 (samozřejmě můžeme pracovat i přímo s čísly revizí, ovšem to má opět smysl pouze, pokud se veškeré naše snažení týká jen jednoho souboru).

Co by se ale stalo, kdybychom jako první parametr -j uvedli pozdější verzi než u druhého parametru? Ano, najednou naše úžasné CVS umí i „undo“. Pokud jsme se tedy náhle rozhodli veškeré změny mezi VETEV1_1 a VETEV1_2 zahodit, stačí cvs up -j VETEV1_2 -j VETEV1_2. Ovšem takto lze napravit například i odstranění souboru. Pokud jsme vytvořili soubor (který byl tedy v revizi 1.1) a posléze ho odstranili (a tak jsme vytvořili virtuální revizi1.2), příkaz cvs up -j 1.2 -j 1.1 soubor nám ho opět vzkřísí k plné síle.

CS24_early

To ovšem není vše, parametr -j pro nás skrývá ještě jedno překvapení. Pokud totiž slučujeme změny z nějaké větve, za její jméno můžeme připojit dvojtečku a údaj o čase. Tedy například -jVETEV:yesterday zajistí, že budeme slučovat verzi VETEV ze včerejška. Formát časového údaje je přitom stejný jako u parametru -D, tedy skýtá poměrně bohaté vyjadřovací schopnosti.


Do příště si jistě větvení a slučování řádně procvičíte, a tak narazíte na spoustu problémů, se kterými se snad vypořádáme příště. Pak se ještě dozvíme o tom, jak si v CVS pohodlně udržovat cizí zdrojové kódy a své změny oproti nim (tedy tak pohodlně, jak jen nám to CVS dovolí).

Byl pro vás článek přínosný?