Koncept tzv. větví či větvení (anglicky branches) je pro Git naprosto esenciální. Jakmile příkazem git init založíte nový lokální repozitář, Git pro vás na pozadí automaticky vytvoří první větev kódu - master.
Koncept větví si můžete jednoduše představit jako strom. Větev master, jakožto první větev, představuje pomyslný kmen a z něj je možné vytvořit neomezené množství větví, a stejně tak z těchto větví je možné vytvořit neomezené množství dalších větví, atd.
Každá větev představuje svůj vlastní prostor, ve kterém probíhá verzování kódu. Tzv. odvětvením přebírá nová větev aktuální stav kódu v původní větvi, nicméně další verzování na této větvi je zcela nezávislé na větvi původní.
Git umožňuje velmi jednoduše větve vytvářet, přejmenovávat, mazat, ale především umožňuje větve (resp. kód z těchto větví) slučovat. Právě možnost slučování kódu má velké praktické využití.
I když web vyvíjí jednotlivec, je velmi bezpečné vyvíjet všechny nové funkce na vlastních větvích a přitom mít v hlavní větvi, masteru, zachovaný funkční kód.
Jakmile pracujete v týmu, je používání větví naprosto nezbytnou záležitostí: jen tak má totiž každý vývojář jistotu, že nepřepisuje kód někomu jinému. V současnosti existuje mnoho metodologií definujících tzv. development workflow, kterými se můžete inspirovat.
Na závěr tohoto teoretického úvodu bych ještě rád zmínil, že kód každé větve lze poslat do vzdáleného repozitáře způsobem, jakým to bylo popsáno v předešlé kapitole, nicméně větev stejného názvu nemůže ve vzdáleném repozitáři existovat vícekrát. To znamená, že pokud budou mít dva nebo více vývojářů lokálně stejně pojmenované větve, bude moci do vzáleného repozitáře tzv. pushnout svou lokální větev jen jeden z nich (ostatní si budou muset své lokální větve přejmenovat). Aby k těmto konfliktům nedocházelo, je vhodné definovat si v rámci týmu určitou jmennou konvenci.
Syntaxe
Pokud volně navážeme na příklad repozitáře test
z první kapitoly, nacházíte se ve stavu, kdy ve výchozí větvi master máte provedených několik commitů. Předpokládejme, že se ve složce projektu (test
) se nacházejí verzované soubory a.txt
, b.pdf
, c.php
.
Rozhodnete se pokračovat ve vývoji, nicméně tentokrát v nové větvi s názvem devel_css
. Novou větev vytvoříte a zároveň se na ni přepnete pomocí příkazu git checkout -b devel_css
.
V rámci nové větve přidáte soubory d.css
a e.js
a provedete commit, a to pomocí příkazů:
> d.css e.js git add . git commit -m “Added files d.css and e.js.”
Po provedení commitu jste tedy v nové větvi devel_css
o jeden commit napřed oproti původní větvi master. Stav můžete zkontrolovat standardně pomocí příkazů git status a git log -n 5
. Přehled všech existujících lokálních větví získáte příkazem git branch
. Případně přehled všech vzdálených větví (větve ze vzdáleného repozitáře) příkazem git branch -r
. Přehled všech větví, tedy lokálních a vzdálených, získáte příkazem git branch -a
.
Přepínat se mezi existujícími větvemi můžete jednoduše příkazem git checkout [název větve]
. V našem případě se zpět na větev master
přepnete pomocí příkazu git checkout master
.
Všimněte si, že po přepnutí na větev master
se ze složky projektu ztratily soubory d.css
a e.js
. Je to jednoduše proto, že tyto soubory ve větvi master
neexistují.
Při přepínání mezi větvemi musí být vaše pracovní složka (working directory) čistá - tedy ve stavu, kdy příkaz git status vrací hlášku nothing to commit, working directory clean
.
Pokud jsou v pracovním adresáři modifikované nebo staged soubory, git vám nedovolí se přepnout na jinou větev, dokud na aktivní větvi neprovedete commit. Příkaz git checkout [název existující větve]
vám v takovém případě vrátí chybovou hlášku Your local changes to the following files would be overwritten by checkout
.
V případě nových, dosud neverzovaných souborů (tzv. untracked files) vám ovšem git přepnutí na jinou větev dovolí. Je to tím, že neverzovaný soubor dosud nepatří do žádné větve, a tudíž na něj přepínání větví nemá vliv.
Ve větvi master
nyní vytvořte další nový soubor s názvem f.yaml
a znovu proveďte commit. Tím se dostanete do stavu, kdy je v obou větvích nový commit, avšak v každé větvi jde o úplně jinou věc, resp. jiný kód.
Předpokládejme nyní, že jste změnili názor a chcete větev devel_css
přejmenovat na devel1
. Provedete to jednoduše příkazem git branch -m [původní název větve] [nový název větve]
. V našem případě git branch -m devel_css devel1
.
V zápětí jste ovšem znovu změnili názor a rozhodli se, že ve větvi devel1
již pokračovat nebudete. Kód z této větve chcete sloučit do větve master
, a následně větev devel1
smazat.
Pro sloučení kódu je nutné, abyste se nacházeli ve větvi master
, což byste nyní měli. Samotné sloučení (merge) kódu provedete příkazem git merge [název slučované větve]
. V našem případě tedy příkaze git merge devel1
.
Jelikož samotný merge představuje pro Git jen další commit, otevře Git po provedení příkazu v rámci příkazové řádky editor (nano, vim), abyste si mohli upravit tzv. commit message. Zároveň pro vás tuto hlášku předepíše - v tomto případě by hláška měla podobu Merge branch 'devel1' into master
. Editaci hlášky ukončíte způsobem standardním pro daný editor. Např. u nano editoru pomocí kláves ctrl-x
.
Pokud nyní zkontrolujete složku projektu, měly by se v ní nově nacházet soubory d.css
a e.js
.
Smazání větve devel1
provedete příkazem git branch -D devel1
.
A to je víceméně vše, co o používání větví obecně potřebujete vědět.
Konflikty při slučování kódu
Možná vás napadlo, co se stane, když je na každé větvi modifikován stejný soubor, anebo když je v každé větvi přidán soubor stejného jména, ale s jiným obsahem? Vznikne tzv. merge conflict.
Jak jsme výše uvedli, sloučení kódu představuje pro Git jen další commit. Git se v této situaci zachová tak, že všechny modifikované či nové soubory, u kterých žádný konflikt není, umístí do stavu staged a konfliktní soubory se pokusí sloučit. Příkaz git status uvádí u konfliktních souborů hlášku “both modified”.
Tato situace může zejména pro začátečníka vypadat velmi složitě a nepříjemně, není však důvod k panice. Jednak se časem naučíte konfliktům z vetší části předcházet, zadruhé není tak těžké konflikt vyřešit. Otevřete si konkrétní soubory, do nichž Git na úrovni jednotlivých řádků umístil vlastní značky - ty říkají, jaký kód byl v souboru původně a jaký je nový. V tuto chvíli je tedy na vás, abyste manuálně prošli dokument, zachovali chtěný kód a smazali zastaralý/nechtěný kód. Jakmile jsou úpravy kódu hotovy, provedete zaverzování klasickým způsobem - to příkazy git add .
a git commit -m “[commit message]”
.
Pozn.: Pro editaci konfilktních souborů doporučujeme používat software typu IDE, např. PhpStorm, který má podporu pro Git a pomocí formátování textu vám vizuálně napovídá, jaké části kódu je potřeba editovat.
Přepínání větví a vývoj Drupalu
Jak již zřejmě víte, Drupal není jen kód, ale také databáze. Přepínání mezi větvemi se týká výhradně kódu, přičemž databáze zůstává stejná.
Po každém sloučení kódu obsahujícího změny v konfiguraci je tedy důležité updatovat také stav databáze, a to příkazem drush cim -y
, který do databáze importuje novou konfiguraci z kódu.
Pozn.: Výše popsaný Import konfigurace se týká výhradně Drupal 8. V Drupal 7 se pro tyto účely používal modul features.
Pokud nový kód přidává nové moduly či upravuje strukturu databáze, je třeba provést také update databáze. K tomu slouží příkaz drush updb -y
.
Pro vývoj na určité větvi může být vhodné vytvořit si duplikát databáze. Jedná se zpravidla o situace, kdy vývojář potřebuje více experimentovat či měnit konfiguraci na různých místech a zároveň chce mít jistotu, že neovlivní stávající funkční konfiguraci. V tomto případě nezapomeňte manuálně upravit údaje pro připojení k databázi v konfiguračním souboru settings.php
.