Subversion

V kaptiole o verzování jste se dozvěděli co to jsou verzovací systémy a k čemu jsou dobré. V této kapitole popíšu jeden z nich – Subversion.

Vytvoření repozitáře

První, co musíte udělat, pokud chcete používat SVN, je vytvořit repozitář a nahrát do něj váš adresář. Tím vytvoříte první verzi.

Subversion

Architektura Subversion

Jako příklad projektu použiji zdrojové soubory k programu Známky a kredity (ver. 4.01) (je součástí zdrojových kódů). Po rozbalení zdrojových kódů uvidíte v adresáři 11subversion adresáře var/svn, Windows a znamky4.01.

Verze 4.01 obsahuje chyby, kvůli kterým nepracuje správně s češtinou. Pokud byste chtěli studovat zdrojový kód tohoto programu, stáhněte si prosím jeho aktuální verzi. Se studováním ale raději počkejte, až se naučíte - z dalších lekcí - pracovat s DBM a ncurses.

Adresář var/svn budu používat pro uložení repozitářů. Normálně se v Linuxu používá adresář /var/svn/, ale repozitář můžete mít uložený kdekoliv. (Já třeba ukládám svoje repozitáře do adaresáře ~/.svnRepository.)

V adresáři znamky4.01 je uložený neverzovaný projekt (to se ale brzo změní). Adresář Windows představuje nějaký jiný počítač, kde budu pracovat s druhou kopijí projetku.

Krok číslo 1 je vytvoření repozitáře.

$ svnadmin create ./var/svn/znamky
$ $ ls var/svn/znamky/
conf  db  format  hooks  locks  README.txt

A to je celé. svnadmin je program, který se používá pro administraci repozitáře. Umí toho víc než jen vytvořit repozitář, ale v tomto kurzu se sním už nesetkáte :-).

Co budete používat hlavně, je příkaz svn.

Krokem číslo 2 bude vytvoření adresáře v rámci repozitáře, do kterého vložíte projekt. K práci se soubory v repozitáři musíte používat přikaz svn. Soubory v repozitáři jsou totiž komprimované a navíc, jak budete přidávat, měnit a odstraňovat soubory a adresáře, budou se ukládat do repozitáře pouze změny (ne celý projekt). Příkazy svn jsou naštěstí dost podobné příkazům linuxové příkazové řádky, takže si na ně rychle zvyknete.

Jak už jsem psal, k SVN můžete přistupovat lokálně, nebo přes internet. Pokud přistupujete lokálně, musíte příkazu svn říct cestu k repozitáři absolutní cestou, která začíná na file:///. Teď záleží na tom, kde máte uložený repozitář. Já si jeho obsah mohu vypsat pomocí následujícího příkazu:

$ svn ls file:///home/petr/resource/c/linux/zdrojaky-linux/11subversion/var/svn/znamky/

Tentokrát se nevypíše nic, protože ještě v repozitáři znamky nic není.

Vytvořím si tedy adresář trunk. Adresář trunk se běžně používá pro název hlavní větve projektu. O tom, co jsou to větve a k čemu jsou dobré bude řeč později. Teď mi věřte, že trunk je ten jediný správný název :-).

$ svn mkdir file:///home/petr/resource/c/linux/zdrojaky-linux/11subversion/var/svn/znamky/trunk -m "Zalozeni vetve trunk"

Committed revision 1.
$ svn ls file:///home/petr/resource/c/linux/zdrojaky-linux/11subversion/var/svn/znamky/
trunk/

Tadáá, máte svojí první verzi projektu. Text argumentu -m "..." je zpráva, která se uloží spolu s ukládanou verzí. Kdykoliv přidáváte nějakou novou verzi, SVN po vás chce komentář. Pokud byste -m neuvedli, otevře se vám editor, do kterého můžete komentář zapsat (to se hodí pro delší, víceřádkové komentáře).

Stažení projektu

Teď máte repozitář s projektem a s větví trunk. Abyste s projektem mohli pracovat, musíte si ho stáhnout do nějaké pracovní kopie. K tomu se používá svn checkdout.

Pracovních kopií si můžete udělat kolik chcete. Pro začátek udělám jednu. A udělám jí v adresáři znamky4.01. Za chvilku uvidíte proč.

Pro některé příkazy poskytuje svn zkratky, například místo checkout stačí napsat co.

$ cd znamky4.01/
$ svn co file:///home/petr/resource/c/linux/zdrojaky-linux/11subversion/var/svn/znamky/trunk .
Checked out revision 1.

Všiměte si, že na konci cesty je trunk.

Příkaz svn co má jako argument cestu k repozitáři a adresář, kam se má trunk stáhnout. Tím je tečka, tj. aktuální adresář.

V aktuálním adresáři teď najdete adresář .svn. To je všechno, co odlišuje pracovní kopii SVN od neverzované kopie projektu.

$ ls .svn
entries  format  pristine  tmp  wc.db

Adresáře .svn a jeho obsahu si nemusíte více všímat.

Vložení souborů do projektu

Příkazem svn status se můžete podívat na to, v jakém stavu je váš projekt (předpokládám, že jste v adresáři pracovní kopie, tj. v adresáři znamky4.01).

$ svn st
?       Makefile
?       create-gdbm.sh
?       curses.c
?       curses.h
?       jmeno_adr.c
?       lib.h
?       lib_dbm.h
?       main.c
?       menu.c
?       pbadresar.c
?       statistika
?       struktury.h
?       struktury_dbm.h
?       trideni
?       trunk
?       vpismena.c
?       zaznam
?       znamky

Příkaz vypsal všechny soubory, které se liší od poslední uložené verze/revize. Protože poslední revize je prázdný adresář (trunk), vypsali se všechny soubory. Otazník na začátku znamená „tento soubor neznám“.

Pro SVN neznámé soubory a adresáře označíte k verzování příkazem svn add.

$ svn add *
A         create-gdbm.sh
A         curses.c
A         curses.h
A         jmeno_adr.c
A         lib_dbm.h
A         lib.h
A         main.c
A         Makefile
A         menu.c
A         pbadresar.c
A         statistika
A         statistika/kreditu.c
A         statistika/udelano.c
A         statistika/prumer.c
A         statistika/Makefile
A         statistika/hranice25.c
A         struktury_dbm.h
A         struktury.h
A         trideni
A         trideni/trideni_vsemestru.c
A         trideni/Makefile
A         trideni/trideni_znamka.c
A         trideni/trideni_semestr.c
A         vpismena.c
A         zaznam
A         zaznam/smaz_zaznam.c
A         zaznam/zaznam_novy.c
A         zaznam/Makefile
A         zaznam/zaznam_editace.c
A         zaznam/zaznamenej.c
A         zaznam/prepis.c
A         zaznam/zjisti_info.c
A  (bin)  znamky

Z výpisu je vidět, že se přidali (A) všechny soubory, včteně souborů v adresářích. Hvězdička v příkazu funguje tak, jak je v příkazovém řádku obvyklé – nahrazuje všechny soubory. Můžete samozřejmě přidávat jeden soubor za druhým jejich vyjmenováním, tj. něco jako svn add create-gdbm.sh curses.c statistika ….

Soubor znamky je binární soubor, tj. SVN v něm nedokáže zobrazit změny řádek po řádce.
Je to zkompilovaný program, který jsem přidal do SVN omylem. Zkompilovaný program verzovat nepotřebuji, tak ho smažu. Co nato SVN?

$ rm znamky
$ svn st znamky
!M      znamky

SVN píše, že je něco v nepořádku (!) a že se soubor znamky změnil (M). Smazání je taky změna :-). V nepořádku je proto, protože jsem ho smazal příkazem rm, a ne pomocí svn. To neva, to pořád moho napravit.

$ svn del znamky
D         znamky

Prozatím jsem nic neodeslal do repozitáře, takže smazaný soubor znamky je navždy ztracen.

Podívejte se, jak by vypadalo, kdybych použil svn. V příkladu vytvořím prázdný soubor znamky (příkazem touch), přidám ho do SVN a zase smažu.

$ touch znamky
$ svn add znamky
A         znamky
$ svn del znamky
svn: E195006: Use --force to override this restriction (local modifications may be lost)
svn: E195006:
'/home/petr/resource/c/linux/zdrojaky-linux/11subversion/znamky4.01/znamky' has local modifications -- commit or revert them first

A chyba je tu. SVN si stěžuje, že chci smazat soubor, který má lokální modifikace (nový soubor se považuje za celý zmondifikovaný) a proto ho odmítne smazat, dokud modifikace nepošlete do repozitáře. Když si ale jste jistí, že modifikace chcete nadobro ztratit, můžete použít přepínač --force.

$ svn del --force znamky
D         znamky

A teď konečně odešlu všechno do repozitáře příkazem svn commit.

$ svn ci -m "Vložení zdrojových souborů verze 4.01 do repozitáře"
Adding         Makefile
Adding         create-gdbm.sh
...
Adding         zaznam/zjisti_info.c
Transmitting file data .............................
Committed revision 2.
$ svn st

Hurá. Vytvořil jsem revizi 2. Jak vidíte, číslo revize stoupá při každé změne v repozitáři (První revize byla vytvoření adresáře trunk). Příkaz svn status už nic nevypíše, protože jsou teď všechny soubory v pracovním adresáři schodné s tím, co je v repozitáři.

Práce se soubory

svn nabízí několik příkazů pro práci se soubory, které byste měli používat. Můžete je používat jak v pracovním adresáři, tak přímo v repozitory!

svn del
Smazání souboru. Ten už znáte.
svn mkdir
Vytvoření adresáře. Vzpomínáte na vytváření adresáře trunk?. To byl příklad použití příkazu přímo v repozitáři.
svn copy
Kopírování souborů. Subversion si bude pamatovat, že nový soubor pochází z toho původního (bude udržovat jeho historii). Pokud byste zkopírovali soubor bez svn a pak ho přidali do repozitáře, subversion by o tuto informaci přišlo.
svn mv
Přesun souborů a adresářů.

Řekněme, že se rozhodnu vytvořit soubor README. Něco do něj zapíšu a pošlu ho do repozitáře.

$ touch README
# neco do nej zapisuji
$ svn add README
A         README
$ svn commit -m "Přidan sobor README"
Adding         README
Transmitting file data .
Committed revision 3.

Teď jsem si ale vzpoměl, že by bylo lepší ho pojmenovat README.txt

$ svn mv README README.txt
A         README.txt
D         README
$ svn st
D       README
        > moved to README.txt
A  +    README.txt
        > moved from README

Příkaz svn move se tváří, jako by přidal README.txt a smazal README, ale svn status ho usvědčuje, že si i zapamatoval, že soubor README.txt pochází z README (znak plus vedle A říká, že jde o přidání nového soubor, který má ale navíc nějakou historii).

$ svn commit -m "Přejmenování README na README.txt"
Deleting       README
Adding         README.txt

Committed revision 4.

Slučování změn

Teď ukáži, co se stane, když měníte jeden soubor v různých praconvích kopiích. Pro začátek si vytvořím novou pracovní kopii v adresáři Windows.

$ cd ../Windows
$ svn co file:///home/petr/resource/c/linux/zdrojaky-linux/11subversion/var/svn/znamky/trunk znamky
A    znamky/curses.h
A    znamky/lib.h
...
A    znamky/menu.c
Checked out revision 4.

Stáhla se mi poslední verze projektu. Teď se rozhodnu upravit soubor statistika/kreditu.c a smazat z něj nepoužívanou proměnnou nacteno.

$ cd znamky
# edit statistika/kreditu.c
$ svn st
M       statistika/kreditu.c

Vidíte, že je soubor modifikovaný (M). Co se v něm ale změnilo? Na to vám odpoví příkaz svn diff.

$ svn diff statistika/
Index: statistika/kreditu.c
===================================================================
--- statistika/kreditu.c        (revision 4)
+++ statistika/kreditu.c        (working copy)
@@ -8,7 +8,6 @@
 void
 kreditu (DBM * dbm_ptr)
 {
-  struct zaznam nacteno;
   struct dbm_info inf;
   WINDOW *new_win;
   wint_t ch;

Nechal jsem si vypsat všechny změny z adresáře statistika. Změněná je jen jedna řádka v jednom souboru. Řádka začíná mínusem, jako že je smazaná. Kromě toho je vypsáno několik řádek nad a po, abyste se lépe zorientovali.
@@ -8,7 +8,6 @@ říká, že výpis začíná na řádku 8 a zobrazuje 7 řádků pro revizi 4, tj. tu z repozitáře a pro pracovní kopii (working copy) začíná také na řádku 8, ale vypisuje jen 6 řádek (nepočítá se ta řádka s mínus).

Teď se ještě rozhodnu změnit něco v souboru README.txt. Podtrhnu nadpisy Popis a Instalace. Nadpis Instalace ještě odsadím o řádek.

# edit README.txt
$ svn diff README.txt
Index: README.txt
===================================================================
--- README.txt  (revision 4)
+++ README.txt  (working copy)
@@ -1,4 +1,5 @@
 Popis
+.....
 
 Tento program je určen (nejen) pro studenty vysokých škol. Ukáže Vám, jak
 poctivě studujete. Zaznamenáte si do něj své předměty a on vám na oplátku
@@ -6,7 +7,9 @@
 kreditů jste již získali za semestr.
 Zvýrazňuje předměty, u nichž jste ještě zkoušku neudělali, můžete si
 vyhledávat předměty dle názvu nebo kódu (viz. obrázek) atd.
+
 Instalace
+.........
 
 Program je vytvořen pro OS Linux a byl testován v distribuci Ubuntu a
 OpenSuSE. Stačí jej rozbalit a spustit. Dodává se včetně zdrojových kódů,

Tentokrát jsem řádky jen přidával, takže vidíte jen řádky s plusem …

Je na čase práci uložit do repozitáře.

$ svn commit -m "Podtržení nadpisů v README.txt a smazání nepoužité proměnné"
Sending        README.txt
Sending        statistika/kreditu.c
Transmitting file data ..
Committed revision 5.
$

Teď se přesunu do druhé pracovní kopie a rozhodnu se aktualizovat adresář statistika/

$ cd ../../znamky4.01/
$ svn up statistika/
Updating 'statistika':
U    statistika/kreditu.c
Updated to revision 5.

No vida, soubor statistika/kreditu.c se updatoval (U). (Neupdatoval se ale soubor README.txt, protože ten není v adresáři statistika.)

Konflikty

Protože jsem ale zapoměl, že jsem už nadpisy v README.txt podtrhal (nebo tu změnu udělal jakože nějaký můj kolega, co semnou na programu spolupracuje a já o ní nevím), udělám podtržení znovu. Místo teček ale podtrhnu nadpisy pomocí hvězdiček. Nadpis Instalace jsem také odsadil o jeden řádek.

##uprava README.txt
$ svn st
M       README.txt
$ svn commit -m "Podtrzeni nadpisu"
Sending        README.txt
svn: E155011: Commit failed (details follow):
svn: E155011: File '/home/petr/resource/c/linux/zdrojaky-linux/11subversion/znamky4.01/README.txt'
is out of date
svn: E160028: File '/trunk/README.txt' is out of date

Ajaj, soubor se nepodařilo odeslat. Nemůžete poslat do repozitáře soubor, který změnil už někdo jiný. Takže si nejdřív stáhnu aktuální verzi z repozitáře pomocí svn update.

$ svn up README.txt
Updating 'README.txt':
C    README.txt
Updated to revision 5.
Conflict discovered in file 'README.txt'.
Select: (p) postpone, (df) show diff, (e) edit file, (m) merge,
        (mc) my side of conflict, (tc) their side of conflict,
        (s) show all options: p
$ Summary of conflicts:
  Text conflicts: 1
$ svn st
C       README.txt
?       README.txt.mine
?       README.txt.r4
?       README.txt.r5
Summary of conflicts:
  Text conflicts: 1
 

Ajaj, další problém. SVN zjistil konflikt. Tj změny, které jsem udělal v README.txt a změny, které byli v repozitáři jsou na stené řádce a SVN nedokáže rozhodnout, co z toho je platný. Dává mi na výběr několik možností. Vybral jsem si p jako postpone, tj. odložení řešení problému na později.

Soubor README.txt je teď v konfliktu (C). Subversion vytvořil několik jeho kopií, README.txt.mine je kopie souboru, který jste měli v pracovní adresáři. README.txt.r4 je kopie souboru, který jste naposledy stáhli (tj vezre naposledy stažená do vašeho pracovního adresáře) a README.txt.r5, cože je kopie verze, kterou jste se snažili stáhnout teď.

Soubor README.txt obsahuje teď něco takového:

Popis
<<<<<<< .mine
*****
=======
.....
>>>>>>> .r5

Tento program je určen (nejen) pro studenty vysokých škol. Ukáže Vám, jak
poctivě studujete. Zaznamenáte si do něj své předměty a on vám na oplátku
spočítá vážený průměr, kolik trojek vám chybí do hranice 2.5 a kolik
kreditů jste již získali za semestr.
Zvýrazňuje předměty, u nichž jste ještě zkoušku neudělali, můžete si
vyhledávat předměty dle názvu nebo kódu (viz. obrázek) atd.

Instalace
<<<<<<< .mine
*********
=======
.........
>>>>>>> .r5

Program je …

Všechny řádky, které nedokázal svn sloužit jsou označeny pomocí <<<<<<< a >>>>>>>.

Po >>>>>>> .mine následují konfliktní řádky (v příkladu jen jeden řádek s hvězdičkama), pak =======, pak řádky z revize, kterou jsem se snažil aktualizovat a pak >>>>>>> .r5.

Teď je na mě, abych upravil soubor do stavu, který mi vyhovuje. Řekněme, že chci ponechat podtržení s hvězdičkami, tak všechno výše zmíněné smažu a nechám jen hvězdičky.

## edit README.txt
$ svn diff README.txt
Index: README.txt
===================================================================
--- README.txt  (revision 5)
+++ README.txt  (working copy)
@@ -1,5 +1,5 @@
 Popis
-=====
+*****
 
 Tento program je určen (nejen) pro studenty vysokých škol. Ukáže Vám, jak
 poctivě studujete. Zaznamenáte si do něj své předměty a on vám na oplátku
@@ -9,7 +9,7 @@
 vyhledávat předměty dle názvu nebo kódu (viz. obrázek) atd.
 
 Instalace
-=========
+*********

 Program ...

README.txt je ale stále ve stavu konfliktu, tak musím svn říct, že už jsem problém vyřešil (příkazem svn resolved).

$ svn st
C       README.txt
?       README.txt.mine
?       README.txt.r4
?       README.txt.r5
Summary of conflicts:
  Text conflicts: 1
$ svn resolved README.txt
Resolved conflicted state of 'README.txt'
$ svn st
M       README.txt
$ svn commit -m "Změna podtržení z teček na hvězdičky"
Sending        README.txt
Transmitting file data .
Committed revision 6.

Cestování časem

Příkaz svn log zobrazí uložené revize s popisem. S přepínačem -v zobrazí i soubory, keré se změnili.

svn log -v
------------------------------------------------------------------------
r1 | petr | 2014-08-22 10:56:47 +0200 (Pá, 22 srp 2014) | 1 line
Changed paths:
   A /trunk

Zalozeni vetve trunk
------------------------------------------------------------------------

Ale co to? Že bych měl jen jednu revizi? Subversion umožňuje, abyste měli v pracovní kopii různé verze souborů. Proto se po odeslání (commitu) automaticky nestáhne nejnovější verze celého adresáře. Takže je to potřeba udělat ručně.

$ svn up
Updating '.':
At revision 6.

Zdánlivě se nic nestalo (nezměnil se žádný soubor), ale teď už je celý pracovní adresář v revizi 6 a podle toho se bude chovat i svn log. Parametrem -l 3 jsem omezil výpis na poslední 3 revize.

$ svn log -v -l 3
------------------------------------------------------------------------
r6 | petr | 2014-08-22 10:56:51 +0200 (Pá, 22 srp 2014) | 1 line
Changed paths:
   M /trunk/README.txt

Změna podtržení z teček na hvězdičky
------------------------------------------------------------------------
r5 | petr | 2014-08-22 10:56:50 +0200 (Pá, 22 srp 2014) | 1 line
Changed paths:
   M /trunk/README.txt
   M /trunk/statistika/kreditu.c

Podtržení nadpisů v README.txt a smazání nepoužité proměnné
------------------------------------------------------------------------
r4 | petr | 2014-08-22 10:56:49 +0200 (Pá, 22 srp 2014) | 1 line
Changed paths:
   D /trunk/README
   A /trunk/README.txt (from /trunk/README:3)

Přejmenování README na README.txt

Za domácí úkol vyzkoušejte svn log -v README.txt. Hádejte, zobrazí se vám i historie souboru README, ze kterého README.txt vzešel? Následující příklad napoví.

Další cestování v čase umožňuje příkaz svn diff. Můžete si zobrazit rozdíl v souborech v libovolných verzích.

$ svn diff -r3:6 README.txt
Index: README
===================================================================
--- README      (.../README)    (revision 3)
+++ README      (.../README.txt)        (revision 6)
@@ -1,9 +1,12 @@
 Popis
+*****
 
  Tento program je určen (nejen) pro studenty vysokých škol. Ukáže Vám,
jak poctivě studujete. Zaznamenáte si do něj své předměty a on vám na
 oplátku spočítá vážený průměr, kolik trojek vám chybí do hranice 2.5 a
kolik kreditů jste již získali za semestr.
  Zvýrazňuje předměty, u nichž jste ještě zkoušku neudělali, můžete si
vyhledávat předměty dle názvu nebo kódu (viz. obrázek) atd.
+
 Instalace
+*********
 
  Program je vytvořen pro OS Linux a byl testován v distribuci Ubuntu a
OpenSuSE. Stačí jej rozbalit a spustit. Dodává se včetně zdrojových kódů,
 takže si jej můžete i přeložit.

Nechal jsem si zobrazit rozdíl mezi 3 a 6 verzí. Z výpisu vidíte, že verze 6 má oproti verzi 3 navíc podtržené nadpisy hvězdičkami. Mezi těmito verzemi je ještě verze s podtržením tečkami, ale já chtěl jen rozdíl verzí 3 a 6.

A nejlepší na konec. Příkazem svn up s volbou -r si mohu stáhnou z repozitáře libovolnou verzi dokumentu, nebo i celého adresáře. Jak vypadal můj projekt po druhém commitu?

$ svn up -r 2
Updating '.':
D    README.txt
U    statistika/kreditu.c
Updated to revision 2.

Soubor README.txt tehdy ještě neexistoval (ani README). Vrátili se i změny provedené v souboru statistika/kreditu.c. A teď zase z5 na aktuální verzi.

$ svn up
Updating '.':
A    README.txt
U    statistika/kreditu.c
Updated to revision 6.

Větve (branches) a tagy

Teď už umíte všechno co je potřeba k tomu, abyste mohli subversion používat. Pokud ale chcete, můžete číst dále :-).

Už víte, že si můžete zkopírovat celý projekt do jiného adresáře v repozitáři. Tím vytvoříte tzv. větev (branch). K čemu je to dobré? Můžete pracovat v této jiné větvi na nějakém úkolu, aniž byste ovlivnili hlavní větev (trunk). Na hlavní větvi mezi tím může váš kolega provádět jiné změny, aniž byste mu narušoval práci svými změnami. Pokud se vám změny líbí, můžete je snadno sloučit do hlavní větve (merge). Pokud se vám nelíbí, prostě větev smažete.

Než ukážu typický proces větvení, ještě se zmíním o tagování. Tag se používá k nějakému lidskému označení revize. Když se rozhodnete zveřejnit novou verzi svého programu, většinou ho nějak pojmenujete a dáte mu číslo verze (ale asi jiné, než používá subversion).

Subversion žádný speciální nástroj pro tagování nemá, místo toho existuje taková „nepsaná“ dohoda, že se tagování provádí kopií projektu do adresáře tags.

Subversion vytváří tzv. levné kopie. Když mu řeknete, že má (v repozitáři) vytvořit kopii, subversion si jenom poznamená z které verze kopie vychází a jak se jmenuje. Není vůbec důvod, aby fyzicky data zkopíroval, takže taková levná kopie nezabírá skoro žádné místo.

Větve, ve kterých chcete něco měnit, se ukládají do adresáře branches. Jedná se zase o „nepsanou“ dohodu, ale rozhodně doporučuji se tohoto postupu držet. Některé nástroje, které umí s SVN pracovat, na tento způsob pojmenování větví a tagů spoléhá.

$ svn mkdir ^/branches -m "Adresář pro pracovní větve"

Committed revision 7.
$ svn mkdir ^/tags -m "Adresář pro tagování"

Committed revision 8.

Teď si otaguji aktuální větev. Je na čase vydat verzi znamky4.02 :-) Kopii můžu udělat rovnou v repozitáři.

Protože jsem v adresáři znamky4.01, mohu si dovolit použít zkrácený zápis k repozitáři pomocí stříšky ^. Stříška se nahradí plnou cestou k repozitáři file:///home/petr/resource/c/linux/zdrojaky-linux/11subversion/var/svn/znamky/.

$ svn copy ^/trunk ^/tags/znamky4.02 -m "Verze 4.02"

Committed revision 9.
$ svn ls ^/
branches/
tags/
trunk/
$ svn ls ^/tags
znamky4.02/

^/tags/znamky4.02/ je vlastně také větev. Ale tuto větev byste už nikdy neměli měnit. Je tu přece jako odraz stavu toho, co jste zveřejnili lidem.

Teď budu pokračovat ve vývoji hlavní větve (trunk), kterou mám pořád v pracovní kopii. Upravím například soubor Makefile, aby příkazy rm měli argument -f a v souboru curses.h změním knihovnu ze staré <curses.h> na novou <ncurses/curses.h>. A změny odešlu do SVN.

## editace souboru
$ svn st
M       Makefile
M       curses.h
$ svn commit -m "Vylepšní makefile a změna knihovny cures na ncurses"
Sending        Makefile
Sending        curses.h
Transmitting file data ..
Committed revision 10.

Ale moment! Teď mi došlo, že jsem zapoměl změnit číslo verze v souborech README.txt a struktury.h, takže ve verzi 4.02 je pořád zapsáno 4.01. Jak už jsem psal, jednou vydaná verze by se neměla měnit. Jako že jsem ale naštěstí ještě nic nezveřejnil, takže si to můžu dovolit.

Potřebuju nějak upravit větev ^tags/znamky4.02. Mohou si ji pomocí svn checkout celou stáhnout, ale mám i lepší možnost – pomocí svn switch se do ní „přepnout“. Příkazem svn info se pak můžete podívat, s jakou větví pracujete.

$ svn switch ^/tags/znamky4.02
U    curses.h
U    Makefile
Updated to revision 10.
$ svn info
Path: .
Working Copy Root Path: /home/petr/resource/c/linux/zdrojaky-linux/11subversion/znamky4.01
URL: file:///home/petr/resource/c/linux/zdrojaky-linux/11subversion/var/svn/znamky/tags/znamky4.02
Relative URL: ^/tags/znamky4.02
Repository Root: file:///home/petr/resource/c/linux/zdrojaky-linux/11subversion/var/svn/znamky
Repository UUID: 36c47b24-bcaa-4063-9b01-284b1bcfb08a
Revision: 10
Node Kind: directory
Schedule: normal
Last Changed Author: petr
Last Changed Rev: 9
Last Changed Date: 2014-08-22 11:30:35 +0200 (Pá, 22 srp 2014)

$
Nenechte se zmást tím, že pracovní kopie je znamky4.01. Tak se jmenuje adesář, ve kterém pracujeme, z historických důvodů (pracovní adresář ve Windows se jmenuje inteligentněji – pouze znamky).

Tak jednoduché a rychlé to bylo! Jen 2 soubory se změnili a už pracuji v jiné větvi :-).

Teď provedu požadované změny a odešlu je.

## edit files
$ svn commit -m "Změna čísla verze z 4.01 na 4.02"
Sending        README.txt
Sending        struktury.h
Transmitting file data ..
Committed revision 11.

Tak mě napadlo, co kdybych, ještě než 4.02 zveřejním, přenesl změny z hlavní větve? Není problém, trochu si zamergeujeme …

$ svn merge ^/trunk
svn: E195020: Cannot merge into mixed-revision working copy [10:11]; try updating first

Nojo, zase jsem neupdatoval a tak mám soubory v různé verzi (viz svn st- v). To se dá snadno napravit.

$ svn st -v
                10        9 petr         .
                10        2 petr         Makefile
                11       11 petr         README.txt
                10        2 petr         create-gdbm.sh
                10        2 petr         curses.c
...
                10        2 petr         statistika/udelano.c
                11       11 petr         struktury.h
                10        2 petr         struktury_dbm.h
...
$ svn up
Updating '.':
At revision 11.
$ svn st -v
                11       11 petr         .
                11        2 petr         Makefile
                11       11 petr         README.txt
                11        2 petr         create-gdbm.sh
                11        2 petr         curses.c
...
                11        2 petr         statistika/udelano.c
                11       11 petr         struktury.h
                11        2 petr         struktury_dbm.h
...

První sloupec ukazuje aktuální číslo verze v pracovním adresáři, druhý sloupec ukazuje číslo verze, kdy se soubor naposledy změnil (přesněji řečeno, o jaké poslední změně ví váš pracovní adresář).

$ svn merge ^/trunk
--- Merging r9 through r11 into '.':
U    Makefile
U    curses.h
--- Recording mergeinfo for merge of r9 through r11 into '.':
 U   .

Subversion ví, v jaké revizi se větev znamky4.02 oddělila od větve trunk a přenese změny od tohoto okamžiku (r9) až k té poslední (r11). Navíc zapíše do adresáře (.) informaci o provedeném merge, takže při příštím merge přenese změny od r11 dále. Změny se teď zapsali do vaší pracovní kopie, takže je ještě potřeba poslat je na server.

$ svn st
 M      .
M       Makefile
M       curses.h
$ svn commit -m "Merge změn z trunk"
Sending        .
Sending        Makefile
Sending        curses.h
Transmitting file data ..
Committed revision 12.

Teď se můžu vrátit zpět k větvi trunk.

$ svn switch ^/trunk
U    struktury.h
U    README.txt
 U   .
Updated to revision 12.

Tak mě napadlo, nešlo by přenést změny z znamky4.01 do trunk? Jasně že šlo. A navíc chci přenést jen změnu s číslem verzí. To taky není problém.

$ svn log ^/tags/znamky4.02 -l 3
------------------------------------------------------------------------
r12 | petr | 2014-08-22 12:04:12 +0200 (Pá, 22 srp 2014) | 1 line

Merge změn z trunk
------------------------------------------------------------------------
r11 | petr | 2014-08-22 11:53:17 +0200 (Pá, 22 srp 2014) | 1 line

Změna čísla verze z 4.01 na 4.02
------------------------------------------------------------------------
r9 | petr | 2014-08-22 11:30:35 +0200 (Pá, 22 srp 2014) | 1 line

Verze 4.02
------------------------------------------------------------------------

Z výpisu se dočtu, že mě zajímá rozdíl mezi revizí 9 a 11.

$ svn merge ^/tags/znamky4.02 -r9:11
--- Merging r10 through r11 into '.':
U    struktury.h
U    README.txt
--- Recording mergeinfo for merge of r10 through r11 into '.':
 U   .

Příkazy svn st a svn diff si můžete prohlédnout mergnuté změny a pak je odeslat příkazem svn commit. To už vám nechám za domácí úkol.

Celý proces větvení a mergování z této kapitoly jsem se pokusil znázornil na obrázku:

Subversion - Větve

Větvení

Pamatujte, že větve pro práci byste měli dělat v adresáři branches. To, že jsem ukazoval příklady s větví v tags, bylo jen kvůli zkrácení výukového textu.

Tak jste viděli, jak pracovat s větvemi, jak mezi nimi přepínat a jak přenášet změny z jedné větve do druhé.

Máte už docela slušné základy SVN, ale je toho pořád hodně co nevíte. Nevíte třeba, jak označit některé soubory, aby je SVN ignorovalo (a neverzovalo). Nevíte, jak pracovat se repozitářem na jiném stroji (přes HTTP nebo SSH) a nevíte spoustu dalších drobností. Všechno si můžete nastudovat na svnbook.red-bean.com/. Můžete také použít příkaz svn help pro zobrazení nápovědy. Doufám, že od teď už budou všechny vaše projekty pod dohledem nějakého verzovacím systému.

Ve zdrojových kódech ke stažení máte všechny příkazy z této kapitoly uloženy v souboru Makefile. Což je, myslím, hezká ukázka toho, jak lze využít Makefile také na něco jiného, než jen překlad zdrojového kódu.

Komentář Hlášení chyby
Vytvořeno: 21.8.2014
Naposledy upraveno: 10.10.2014
Tato stánka používá ke svému běhu cookies, díky kterým je možné monitorovat, co tu provádíte (ne že bych to bez cookies nezvládl). Také vás tu bude špehovat google analytics. Jestli si myslíte, že je to problém, vypněte si cookies ve vašem prohlížeči, nebo odejděte a už se nevracejte :-). Prohlížením tohoto webu souhlasíte s používáním cookies. Dozvědět se více..