Git
Chapters ▾ 2nd Edition

3.1 Větve v systému Git - Větve v kostce

Nějakou formu větvení podporují téměř všechny systémy pro správu verzí. Větvení znamená, že se můžete odloučit od hlavní linie vývoje a pokračovat v práci, aniž byste do hlavní linie zasahovali. V mnoha nástrojích pro správu verzí jde o poněkud náročný proces, který často vyžaduje vytvoření nové kopie adresáře se zdrojovým kódem, což může u velkých projektů trvat dlouho.

Někteří lidé mluví o modelu větvení Gitu jako o „převratné vlastnosti“ a mezi systémy pro správu verzí se jím Git určitě odlišuje. V čem je tak zvláštní? Způsob, jakým Git větvení provádí, je neuvěřitelně snadný a operace větvení probíhají téměř okamžitě. A stejně rychlé je většinou i přepínání mezi větvemi. Na rozdíl od ostatních systémů pro správu verzí vybízí Git ke způsobu práce, kdy se větvení a slučování provádí často, dokonce i několikrát za den. Pochopení a zvládnutí tohoto rysu vám dává do rukou výkonný a jedinečný nástroj a může zcela změnit způsob, jakým budete realizovat vývoj.

Větve v kostce

Abychom skutečně pochopili, jak v Gitu funguje větvení, musíme poodstoupit a podívat se, jak Git ukládá data.

Jak si možná vzpomínáte z kapitoly Úvod, Git neukládá data jako sérii změn nebo rozdílů, ale jako sérii snímků.

Když zapíšete revizi, uloží Git objekt revize (commit object), který obsahuje odkaz na snímek obsahu, který jste připravili k zapsání. Tento objekt obsahuje také jméno a e-mail autora, zprávu, kterou jste napsali, a odkazy na jeden nebo víc objektů revize, které této revizi přímo předcházely (jeho rodiče): na žádného rodiče pro počáteční revizi, na jednoho rodiče pro běžnou revizi a na více rodičů pro revizi, která je výsledkem sloučení dvou nebo více větví.

Pro ilustraci předpokládejme, že máte adresář s třemi soubory, které připravíte k zapsání a následně zapíšete. Při přípravě souborů k zapsání je pro každý z nich vypočítán kontrolní součet (o otisku SHA-1 jsme se zmínili v kapitole Úvod), daná verze souborů se uloží v repozitáři Gitu (Git jim říká bloby [10]) a přidá jejich kontrolní součet do oblasti připravených změn:

$ git add README test.rb LICENSE
$ git commit -m 'The initial commit of my project'

Když příkazem git commit vytváříte revizi, vypočítá Git kontrolní součet každého podadresáře (v tomto případě pouze kořenového adresáře projektu) a uloží tyto objekty stromu (tree) do repozitáře Gitu. Poté Git vytvoří objekt revize (commit) s metadaty a s ukazatelem na kořen stromu projektu, aby mohl v případě potřeby tento snímek obnovit.

Váš gitovský repozitář nyní obsahuje pět objektů: jeden blob pro obsah každého z vašich tří souborů, jeden strom, který zaznamenává obsah adresáře a udává, které názvy souborů jsou uloženy jako který blob, a jeden objekt revize s ukazatelem na kořenový objekt stromu a se všemi metadaty revize.

Objekt revize a jeho strom.
Figure 9. Objekt revize a jeho strom

Jestliže v souborech provedete změny a zapíšete je, další objekt revize uloží ukazatel na bezprostředně přecházející objekt revize.

Objekty revize a jejich rodiče.
Figure 10. Objekty revize a jejich rodiče

Větev je v Gitu jen snadno přemístitelným ukazatelem na jeden z těchto objektů revize. Výchozím názvem větve v Gitu je master (hlavní větev). Když vytváříte objekt revize, máte k dispozici větev master, která ukazuje na váš minulý objekt revize. Pokaždé, když zapíšete novou revizi, větev se automaticky posune vpřed.

Note

Větev „master“ se v Gitu nechápe jako speciální větev. Je úplně stejná jako všechny ostatní. Jediným důvodem, proč ji najdete skoro v každém repozitáři, je to, že ji standardně vytváří příkaz git init a většina lidí se nezatěžuje tím, že by to změnili.

Větev a historie jejích objektů revize.
Figure 11. Větev a historie jejích objektů revize

Vytvoření nové větve

Co se stane, když vytvoříte novou větev? Znamená to vytvoření nového ukazatele, s nímž můžete pohybovat. Řekněme, že vytvoříte novou větev a nazvete ji testing. Učiníte tak příkazem git branch:

$ git branch testing

Vytvoří se tím nový ukazatel na stejný objekt revize, na kterém se právě nacházíte.

Dvě větve ukazují na stejnou sérii objektů revize.
Figure 12. Dvě větve ukazují na stejnou sérii objektů revize

Jak Git pozná, na jaké větvi se právě nacházíte? Používá speciální ukazatel zvaný HEAD. Poznamenejme, že tento koncept HEAD se velmi liší od těch, na které můžete být zvyklí z jiných systémů pro správu verzí, jako jsou Subversion nebo CVS. V Gitu se jedná o ukazatel na lokální větev, na níž se právě nacházíte. V tomto případě jsme stále na větvi master. Příkaz git branch pouze vytvořil novou větev — nepřepnul do ní.

HEAD ukazující na větev.
Figure 13. HEAD ukazující na větev

Snadno to můžeme zviditelnit spuštěním příkazu git log, který vám ukáže, kam reference větví ukazují. Potřebná volba se jmenuje --decorate.

$ git log --oneline --decorate
f30ab (HEAD -> master, testing) add feature #32 - ability to add new formats to the central interface
34ac2 Fixed bug #1328 - stack overflow under certain conditions
98ca9 The initial commit of my project

Vedle otisku revize f30ab vidíte větve master a testing.

Přepínání větví

Chcete-li přepnout na existující větev, spusťte příkaz git checkout. Přepněme se na novou větev testing:

$ git checkout testing

Tím se HEAD se přesune a ukazuje na větev testing.

HEAD ukazuje na aktuální větev.
Figure 14. HEAD ukazuje na aktuální větev

A jaký to má význam? Dobře, zapišme další revizi:

$ vim test.rb
$ git commit -a -m 'made a change'
Větev HEAD se při zápisu revize posune vpřed.
Figure 15. Větev HEAD se při zápisu revize posune vpřed

Výsledek je zajímavý z toho důvodu, že se větev testing posunula vpřed, zatímco větev master stále ukazuje na revizi, na níž jste se nacházeli před přepnutím větví příkazem git checkout. Přepněme zpět na větev master.

$ git checkout master
Při checkout se HEAD přesune.
Figure 16. Při checkout se HEAD přesune

Příkaz provedl dvě věci. Přemístil ukazatel HEAD zpět, takže nyní ukazuje na větev master, a vrátil soubory ve vašem pracovním adresáři zpět ke snímku, na který ukazuje větev master. To také znamená, že změny, které od tohoto okamžiku provedete, vedou k odklonu od starší verze projektu. V podstatě vrátíte změny, které jste provedli ve větvi testing, takže se můžete vydat jiným směrem.

Note
Přepnutí větví mění soubory ve vašem pracovním adresáři

Považuji za důležité poznamenat, že v Gitu se při přepnutí větví změní soubory ve vašem pracovním adresáři. Pokud se přepnete na starší větev, váš pracovní adresář bude změněn do podoby z doby, kdy jste v oné větvi zapsali poslední revizi. Pokud by se to Gitu nemělo podařit čistě, nedovolí vám přepnout vůbec.

Proveďme pár změn a zapišme další revizi:

$ vim test.rb
$ git commit -a -m 'made other changes'

Nyní se historie vašeho projektu rozdělila (viz obrázek Rozbíhající se historie). Vytvořili jste novou větev, přepnuli se na ni, provedli změny a poté jste přepnuli zpět na hlavní větev, v níž jste provedli další změny. Oboje tyto změny jsou oddělené na samostatných větvích. Můžete mezi nimi přepínat tam a zpět, a až uznáte za vhodné, můžete je sloučit. To vše jste provedli pomocí jednoduchých příkazů branch, checkout a commit.

Rozbíhající se historie.
Figure 17. Rozbíhající se historie

Můžete si to snadno zviditelnit příkazem git log. Když spustíte git log --oneline --decorate --graph --all, zobrazí se historie revizí, která ukazuje polohu ukazatelů na větve a jak se historie rozdělila.

$ git log --oneline --decorate --graph --all
* c2b9e (HEAD, master) made other changes
| * 87ab2 (testing) made a change
|/
* f30ab add feature #32 - ability to add new formats to the
* 34ac2 fixed bug #1328 - stack overflow under certain conditions
* 98ca9 initial commit of my project

A protože větev je v Gitu ve skutečnosti obyčejným souborem, který obsahuje 40 znaků kontrolního součtu SHA-1 revize, na kterou větev ukazuje, dají se větve snadno vytvářet i odstraňovat. Vytvořit novou větev je právě tak snadné a rychlé jako zapsat 41 bytů do souboru (40 znaků plus jeden pro nový řádek).

Ostře to kontrastuje se způsobem větvení ve většině starších systémů pro správu verzí, který zahrnoval kopírování všech souborů projektu do druhého adresáře. To může zabrat několik sekund nebo dokonce minut — v závislosti na velikosti projektu --, zatímco v Gitu tento proces proběhne vždy okamžitě. A protože při zapisování objektů revize zaznamenáváme i jeho rodiče, probíhá automaticky i vyhledání správných zdrojů pro slučování, které se pak většinou dělá velmi snadno. Tyto vlastnosti pomáhají k tomu, aby se vývojáři nebáli větve často vytvářet a používat.

Podívejme se, proč byste to měli dělat také tak.