Větvení (branching) je jednou z nejmocnějších a nejméně pochopených zbraní verzovacích systémů.
Okamžité větvení a slučování jsou jedny z nejsmrtonosnějších zbraní Gitu.
Problém: Vnější události si nevyhnutelně vynutí změnu kontextu. Četné chyby v právě vydané verzi bez varování. Deadline nějaké nové funkce se blíží. Vývojář, jehož pomoc potřebujete pro kritickou sekci projektu, se chystá odejít. Ve všech těchto případech musíte ihned zanechat toho, co jste doposud dělali, a zaměřit se na naprosto odlišnou úlohu.
Přerušování vašeho toku myšlenek může být zhoubné pro vaši produktivitu a čím více je změna kontextu nepohodlná, tím větší jsou ztráty. S centralizovaným verzovacím systémem musíme stáhnout úplně novou kopii z centrálního serveru. Distribuované systémy jsou na tom lépe, jelikož stačí provést kopii pouze lokálně.
Ale klonování je stále o tom, že se musí zkopírovat celý pracovní adresář společně s celou historií projektu. I když Git zmenšuje nároky na tuto operaci sdílením souborů a používáním hard linků, soubory samy o sobě musí být celé znovu vytvořeny v novém pracovním adresáři.
Řešení: Git má pro tyto situace něco lepšího, co je mnohem
rychlejší a prostorově méně náročné než klonování: git
branch
.
Pomocí těchto magických slov se soubory ve vašem pracovním adresáři zčistajasna přetransformují z jedné verze na druhou. Tato proměna toho umí víc než jít dozadu či dopředu v čase. Vaše soubory se mohou změnit z posledního vydání, přes experimentální verzi a současnou vývojovou verzi až k verzi vašeho kamaráda atd.
Boss key
Hráli jste již někdy takovou tu hru, která se po zmáčknutí jistého tlačítka (tzv. „boss key“) zastaví a ihned zobrazí nějaký tabulkový editor či podobně, takže kdyby šéf procházel kanceláří, mohli byste hru rychle schovat?
V nějakém adresáři:
$ echo "Jsem chytřejší než můj šéf!" > mujsoubor.txt $ git init $ git add . $ git commit -m "Počáteční commit"
Vytvořili jsme Gití repozitář, který sleduje jeden textový soubor obsahující jistou zprávu. Nyní napište:
$ git checkout -b boss # nevypadá to, že by se cokoli změnilo $ echo "Můj šéf je mnohem chytřejší než já." > mujsoubor.txt $ git commit -a -m "Další commit"
Vypadá to, jako bychom právě přepsali soubor a provedli commit. Ale je to jen klam. Napište:
$ git checkout master # přepne na originální verzi souboru
A voila, textový soubor je obnoven. A jestli se šéf rozhodne čmuchat kolem, prostě napište:
$ git checkout boss # přepne na verzi vhodnou pro šéfa
Můžete přepínat mezi těmito dvěma verzemi souboru podle libosti a commity provádět naprosto nezávisle.
Špinavá práce
Řekněme, že pracujete na nějaké funkci a z nějakého důvodu potřebujete přejít na starší verzi a přidat pár příkazů pro vytištění obsahu proměnné, abyste se podívali, jak něco funguje:
$ git commit -a $ git checkout SHA1_HASH
Nyní můžete přidávat ošklivý dočasný kód kamkoli chcete. Dokonce můžete provést commit těchto změn. A když jste hotovi:
$ git checkout master
k návratu k původní práci. Všimněte si, že všechny necommitnuté změny jsou přeneseny.
Co kdybychom ale přeci jenom chtěli ty dočasné změny uložit? Jednoduché:
$ git checkout -b fuj
a commitněte před přechodem zpátky do větve master. Kdykoli se chcete vrátit k těmto nelibým změnám, prostě napište:
$ git checkout fuj
Dotkli jsme se tohoto příkazu v předchozí části, kdy jsme probírali navracení se k předchozím stavům. Teď už můžeme říci celý příběh: soubory se změní do požadovaného stavu, ale musíme nechat větev master. Všechny změny na souborech se budou ubírat jiným směrem, který může být pojmenován později.
Jinými slovy, po checkoutu vás Git automaticky umístí do nové
bezejmenné větve, která může být pojmenována a uložena později s
git checkout -b
.
Rychlé opravy
Právě něco děláte, když v tom je vám řečeno, abyste všeho nechali a opravili nově nalezenou chybu:
$ git commit -a $ git checkout -b oprava SHA1_HASH
Pak, když je chyba opravena:
$ git commit -a -m "Chyba opravena" $ git push # na centrální server $ git checkout master
A můžete opět pracovat na tom, na čem jste pracovali původně.
Nepřetržité pracovní nasazení
Některé projekty vyžadují, aby byl kód prohlédnut před tím, než ho můžete odeslat. Abyste těm, co budou kód prohlížet, ulehčili život, pokud se chystáte udělat nějakou velkou změnu, můžete ji rozdělit na dvě a více částí a nechat každou z nich zkontrolovat zvlášť.
Co když ale druhá část nemůže být napsána bez toho, aby byla první schválena a začleněna? S mnoha verzovacími systémy budete muset poslat ke schválení nejdříve první část a pokud bude schválena, pak teprve pracovat na další.
I když to není zas tak pravda, ale pravdou je, že upravovat část 2 před odesláním části 1 v sobě zahrnuje velké trápení. S Gitem je větvení a slučování větví bezbolestné (terminus technicus pro rychlé a lokální). Takže poté, co jste odeslali první část ke zhlédnutí:
$ git checkout -b cast2
Dále pracujte na druhé části velké změny bez toho, abyste čekali na to, až bude první část přijata. Když je první schválena a začleněna:
$ git checkout master $ git merge cast2 $ git branch -d cast2 # už tuhle větev nepotřebujeme
a druhá část změny je zralá ke zhlédnutí.
Ale moment! Co kdyby to nebylo tak jednoduché? Řekněme, že jste udělali chybu v první části, která musí být opravena před začleněním. Žádný problém! Nejdříve se přesuňte zpět do větve master:
$ git checkout master
Opravte chybu první části změny a doufejte, že bude schválena. A pokud ne, prostě tento krok zopakujte. Asi budete chtít přidat opravu části 1 i do části 2:
$ git checkout cast2 $ git merge master
Nyní je to již stejné jako předtím. Jednou, jak byla první část schválna a začleněna:
$ git checkout master $ git merge cast2 $ git branch -d cast2
A opět, druhá část je hotova k začlenění.
Je jednoduché rozšířit tento trik pro jakýkoli počet částí.
Všehochuť
Možná že rádi pracujete na všech aspektech projektu v jedné větvi, chcete udržovat všechny průběžné práce jen pro sebe a ostatním ukázat až elegantní výsledek. Nejdříve si připravte pár větví:
$ git checkout -b osetreno $ git checkout -b vsehochut
Dále pracujte podle libosti: opravujte chyby, přidávejte nové vychytávky, dočasný kód atp. s tím, že postupně commitujete. A potom:
$ git checkout osetreno $ git cherry-pick SHA1_HASH
aplikuje změny commitu do větve osetreno. Se správnými cherry-picky můžete vytvořit větev, která obsahuje pouze stálý kód a má související commity seskupeny pohromadě.
Uspořádávání větví
Výpis všech větví získáte pomocí:
$ git branch
Vždycky uvidíte větev nazvanou master, která je výchozí. Někteří obhajují nechávat větev master netknutou a vytvářet nové větve pro vlastní úpravy.
Přepínače -d
a -m
vám umožní mazat, resp.
přesunovat (přejmenovávat) větve. Viz git help branch
.
Větev master je užitečná konvence. Ostatní mohou předpokládat, že váš repozitář má větev právě s tímto jménem a ta obsahuje oficiální verzi vašeho projektu. Můžete přejmenovat větev master a zbavit se jí tak, ale měli byste tento zvyk respektovat.
Dočasné větve
Po chvíli zjistíte, že často děláte větve s krátkou dobou působnosti pro podobné důvody: všechny ostatní větve pouze slouží k uložení momentálního stavu, takže můžete jednoduše skočit zpátky ke staršímu stavu, abyste přednostně opravili nějakou chybu či podobně.
Je to podobné jako přepínat TV stanice, abyste viděli, co je jinde. Ale místo toho, abyste zmáčkli nějaké tlačítko, vytváříte, aktualizujete a mažete dočasné větve a commity. Naštěstí má Git zjednodušení, které je podobné TV ovladači:
$ git stash
Toto uloží současný stav na dočasné místo (do tzv. „skrýše“ /angl. stash/) a obnoví stav předchozí. Váš pracovní adresář teď vypadá přesně jako předtím, než jste začali upravovat soubory, a můžete opravovat chyby, natahovat změny z hlavního repozitáře atd. Pokud se chcete vrátit do „skrytého“ stavu, napište:
$ git stash apply # můžná bude potřeba vyřešit nějaké konflikty
Můžete mít více skrýší a různě s nimi manipulovat. Viz git
help stash
. Jak jste asi uhodli, Git k docílení tohoto triku používá v zákulisí větve.
Pracujte, jak chcete
Aplikace jako Mozilla Firefox vám umožují, abyste měli otevřených více tabů a více oken. Přepnutím tabu dostanete jiný obsah ve stejném okně. Větve v Gitu jsou jako taby vašeho pracovního adresáře. Když budeme v této analogii pokračovat, klonování je jako otevření nového okna. Možnost obojího zlepšuje uživatelovy zážitky.
Trochu na vyšší úrovni, mnoho Linuxových okenních manažerů podporuje více ploch. Větve v Gitu jsou jako přepnutí na jinou plochu, zatímco klonování je podobné připojení dalšího monitoru k získání další plochy.
Dalším příkladem může být GNU Screen. Tohleto udělátko
vám dá možnost vytvořit, odstranit a přepínat mezi více terminálovými
sezeními v jednom terminálu. Místo otevírání nových terminálů
(klonování) můžete používat jeden a ten samý podobně jako ve
screen
u (větve). Popravdě se toho se screen
em dá
dělat o hodně víc, ale to by bylo téma na samotný článek.
Klonování, větvení a slučování je v Gitu rychlé lokální a podporující to, abyste pracovali, jak vám to nejvíce vyhovuje. Git vás nechá pracovat přesně tak, jak chcete.
Tento článek je překladem čtvrté kapitoly – Branch Wizardry – z GitMagic od Bena Lynna. V další kapitole se bude psát o práci s historií.