Druhý důvod proč zvolit Git: Snadné vytváření a slučování větví

V minulém článku jsme ukázali, že Git je nástroj pro správu verzí, který je zároveň velmi jednoduchý i velmi flexibilní. Především nám však nevnucuje pečlivé plánování pracovních postupů a neříká „to jsi nejdřív měl…“ Dnes se podíváme na to, zdali to platí i při práci s větvemi (branch) a jejich slučováním (merge).

Seriál: Pět důvodů, proč zvolit Git (5 dílů)

  1. První důvod, proč zvolit Git: Neříká vám, jak máte pracovat 21.12.2009
  2. Druhý důvod proč zvolit Git: Snadné vytváření a slučování větví 28.12.2009
  3. Třetí důvod proč zvolit Git : Decentralizace 4.1.2010
  4. Čtvrtý důvod proč zvolit Git : Úpravy a opravy historie 11.1.2010
  5. Pátý důvod, proč zvolit Git : Zkušenosti uživatelů Gitu 18.1.2010

Minule jsme si ukázali, že Git se velmi, velmi snaží být užitečným pomocníkem při práci, a ne tupým nebo přechytralým nástrojem na „ukládání historie a sdílení dat“. A neopouští nás ani při základní součásti práce s verzovacím systémem: při vytváření větví a jejich slučování. Už jen při vyslovení slůvka merge může snadno mnoha uživatelům některých jiných verzovacích systémů naskakovat husí kůže a myšlenky na dovolenou.

Efektivní práce s větvemi tvoří naopak samotné srdce Gitu; koncept paralelního vývoje (kód žije v oddělených světech, které se někdy protínají a někdy ne) je pro něj stejně důležitý jako koncept „verzování“. Jak říká Jeff Atwood, pokud používáte verzovací systém a nepoužíváte paralelní vývoj ve větvích, využíváte jeho schopnosti velmi omezeně.

Git vysloveně ponouká k tomu, pracovat paralelně v oddělených větvích, a snaží se takový způsob práce co nejvíce usnadňovat. Mohu tak na rozsáhlejších změnách pracovat několik dní (nebo třeba týdnů), a mohu si přitom vybrat, zda chci tuto práci sdílet s ostatními, či nikoliv. Pomocí příkazugit fetch agit merge (nebo v tomto případě spíše git rebase , ale nepředbíhejme) mohu do takové paralelní větve průběžně začleňovat aktualizace z ostatních sdílených větví.

Paralelní větve si mohu vytvořit pro uvedené rozsáhlejší změny (často nazývané topic branches) nebo pro nezávazné zkoušení divokých nápadů (tzv. experiment branches), ale též pro oddělení různých verzí a vydání (větve deploy či v1, apod.) v rámci release management. Jednotliví členové týmu mohou také publikovat práci do „svých“ větví (tzv. developer branches). Způsobů využití větví je nepřeberně — důležité je, aby bylo možné mezi větvemi snadno a rychle přecházet a sdílet mezi nimi změny. Git je přeborníkem v obou ohledech.

GIT Branches workflow

V Gitu můžeme, tak jako v ostatních systémech, vytvořit branch a přepnout se do ní předtím, než v ní začneme pracovat:

$ git branch new-branch           # Vytvor vetev 'new-branch' ...
$ git checkout new-branch         # ... a prepni se do ni
$ git checkout -b another-branch  # Nebo vyuzij zkracenou variantu v jednom kroku 

Můžeme ale branch vytvořit kdykoliv v průběhu práce, a rozpracovaný obsah si tak do ní „přetáhnout“. K takové situaci dochází typicky tehdy, kdy si (ve volné parafrázi Linuse Torvaldse) řeknu: „Ouha!, tahle věc mi zabere daleko více času a je daleko složitější, než jsem si původně myslel, a raději bych commitoval do zvláštní větve a ne naostro do větve hlavní“. (Jak již víme, Git neříká „to jsi nejdřív měl…“)

Zjednodušená workflow při práci v Gitu může tedy vypadat například takto:

# Vytvorime si branch "msie_fix" jako "sandbox" pro praci
$ git checkout -b msie_fix
# ... Pracujeme, testujeme, klejeme

# Pripravime zmeny v souborech ke commitu
$ git add public/css/msie6.css

# Ulozime revizi do repositare
$ git commit -m "Oprava problemu pri prihlasovani z MSIE6"

# Zaclenime praci z topic branche do master
$ git checkout master
$ git merge msie_fix

# A odeslene do vzdaleneho repositare
$ git push origin master 

Proč „zjednodušená“? Protože nebere v úvahu to, že ve vzdáleném repositáři mohly přibýt změny od někoho jiného, pracujeme-li v týmu. V takovém případě nám Git ohlásí, že nemůže příkaz provést:

! [rejected] master -> master (non-fast forward)
error: failed to push some refs to ... 

Nejjednodušším řešením je stáhnout a začlenit si změny ze vzdáleného repositáře do našeho (v jednom kroku):

$ git pull origin master
Merge made by recursive. 

V případě vývoje v týmu taková „zjednodušená“ (byť zhusta používaná) workflow vede k nepřehledné historii, ohlášené slovy Merge made by recursive. O kousek níže v článku si vysvětlíme, jak se tomu vyhnout.

Důležité je, že hlavní větev (master) máme „čistou“ a změny v obsahu provádíme izolovaně ve větvi jiné. Publikovat je můžeme samostatně i v rozpracovaném stavu (třeba proto, aby je zkontrolovali kolegové) nebo je můžeme začlenit do hlavní větve, jakmile jsou hotové.

Znovu a lépe

To, že Git neříká „to jsi nejdřív měl…“ ale v kontextu větví a slučování znamená ještě víc. V Gitu probíhá všechna práce lokálně, dokud ji výslovně neodešlu (git push ) do sdíleného repositáře. Mohu tedy kód „rozvětvit“ dokonce i v případě, že jsem uložil revizi v hlavní větvi (master) a teprve poté zjistil, „Ouha!, tohle je daleko složitější, než jsem si myslel…“. Uvažujme tuto fiktivní situaci ve větvi master

(časově poslední změny nahoře):

$ git log --oneline

fb00250 Přidána možnost přihlášení přes OpenID
75bc299 [FIX] Oprava přihlašovacího formuláře (validace délky hesla)
c56fb7b Přidán přihlašovací formulář
# ...   (starsi revize) 

Revize c56fb7b je již ve sdíleném repositáři a nasazena v aplikaci na serveru. Revizi 75bc299, která opravuje chybu, jsme právě přidali přímo do větve master a zároveň zpracovali podporu pro OpenID („triviální!“), kterou jsme uložili odděleně, v revizi fb00250. Červíček ale hlodal, a po chvilce manuálního zkoušení se ukázalo, tak jako často, že to není tak úplně triviální, a „bude to chtít více času“. Ale nefunkční funkcionalitu jsme již do hlavní větve uložili ( fb00250). Při práci v centralizovaném verzovacím systému právě nastává fáze zrychleného tepu, frenetického opravování a několika commitů obsahujících slovo „oprava“.

Při práci v Gitu nemáme problém se z takové šlamastyky vymotat. Řekněme, že chceme do sdíleného repositáře poslat opravu v 75bc299  a polo-funkční fb00250 si „přetáhnout“ do soukromé branche, kde se budeme OpenID věnovat v klidu dále. Celý postup by pak vypadal asi takto:

$ git branch openid fb00250   # Vytvorime novou branch "openid" odvozenou z commitu "fb00250"
$ git reset 75bc299 --hard    # Vratime branch "master" na predchozi commit "75bc299 [FIX] ..."
$ git push origin master      # Odesleme FIX do sdileneho repositare

$ git checkout openid         # Prepneme se do branche "openid", kde muzeme pracovat dale 

Když máme konečně OpenID funkcionalitu hotovou, chceme ji začlenit do „master“ branche a poslat do sdíleného repositáře. Uvažujme situaci, kdy ve sdíleném repositáři mezitím přibyly změny od někoho jiného ( 671aada):

$ git fetch                                  # Stahni informaci o novinkach ze serveru
$ git log --oneline master..origin/master    # Jake revize pribyly na serveru?
671aada Zmena na 'serveru' 

Chcete-li se naučit efektivně využívat všechny možnosti Gitu, objednejte si od autora článku školení, nebo si rezervujte místo v kurzech na www.git-fu.cz.

Nyní máme dvě fundamentálně odlišné možnosti, jak pokračovat:git merge a git rebase . Zjednodušeně řečeno, první spojuje paralelní větve s tím, že ukládá informace o samotném sloučení, druhá historii „přeskládává“ a linearizuje; vysvětlení by zabralo celý článek, proto jen odkážeme na velmi hezké vysvětlení s obrázky. Mezi gitstery se vede spor, zda je důležitější zcela přesný záznam historie v repositáři, nebo přehledná a čitelná historie. Autor článku upřednostňuje druhou variantu, připomeňme však, že v Gitu lze velmi snadno při chytré práci s větvemi zachovat obojí. Další informace hledejte v rámečku „Philosophy of Altering History“ v knize Jona Loeligera Version Control with Git.

V našem případě se rozhodneme pro možnost druhou a využijeme přepínače --rebase pro příkaz git pull , kterým si změny ze sdíleného repositáře ( 671aada) „přeskládáme“ a začleníme před naše vlastní změny:

$ git checkout master         # Prepneme se do branche "master",
$ git merge openid            # ... a zaclenime zmeny z branche "openid" do "master"
$ git pull --rebase           # Stahneme a zaclenime si zmeny "ze serveru" do lokalniho repositare
$ git push                    # ... a odesleme "master" na server 

Nevěšte hlavu, jsou-li pro vás uvedené kroky a odkazy typu „a to bychom to mohli udělat ještě jinak!“ matoucí. Práce s paralelními větvemi je základem pracovních postupů v Gitu, a z pohledu koncového uživatele jeho největší výhodou pro efektivitu a produktivitu práce. Je ale třeba se ji učit a zkoušet, pak jde sama od sebe. Největší chybou, které při své konzultační a „osvětové“ praxi vidím, je využívání Gitu jako Subversion 2.0, tedy nekoordinovaná práce v master větvi, která s sebou přináší konflikty a nekonečné „koleje“ merge commitů typu Merge branch 'master' of ..., jak hezky vidíte z obrázku níže.

GITx5

Jak případně poznamenává autor v příslušném článku, „vypadalo by to mnohem lépe, kdybychom využili git-rebase pro přeskládání commitů, místo abychom je slučovali, ale ten, kdo vytvořil takovou historii, to v té době ještě s Gitem moc neuměl“.

V příštím článku se zamyslíme nad tím, co přesně znamená, že Git je „distribuovaný“, resp. „decentralizovaný“ systém na správu verzí, a jaké to má důsledky pro naši každodenní práci s repositáři.

Karel Minařík navrhuje a programuje webové stránky a aplikace, poskytuje konzultace a školení v oblasti vývoje pro web a žije v Praze se svojí ženou a dvěma dcerami.

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 84

Přehled komentářů

xurfa a bez toho „evangelizování“ by to nešlo?
Aleš Roubíček Re: a bez toho „evangelizování“ by to nešlo?
xurfa Re: a bez toho „evangelizování“ by to nešlo?
Michal Re: a bez toho „evangelizování“ by to nešlo?
Karel Minařík Re: a bez toho „evangelizování“ by to nešlo?
xurfa Re: a bez toho „evangelizování“ by to nešlo?
Martin Malý Re: a bez toho „evangelizování“ by to nešlo?
xurfa Re: a bez toho „evangelizování“ by to nešlo?
Martin Malý Re: a bez toho „evangelizování“ by to nešlo?
Renda Re: a bez toho „evangelizování“ by to nešlo?
xurfa Re: a bez toho „evangelizování“ by to nešlo?
Martin Malý Re: a bez toho „evangelizování“ by to nešlo?
Michal Re: a bez toho „evangelizování“ by to nešlo?
lupen číslování revizí
abtris Re: číslování revizí
Aleš Roubíček Re: číslování revizí
Almad Re: číslování revizí
Karel Minařík Re: číslování revizí
Tom Re: číslování revizí
David Majda Re: číslování revizí
rater Re: číslování revizí
Karel Minařík Re: číslování revizí
David Majda Re: číslování revizí
Karel Minařík Re: číslování revizí
Karel Minařík Re: číslování revizí
Tom Re: číslování revizí
Karel Minařík Re: číslování revizí
Martin Soušek subversion 2.0
Karel Minařík Re: subversion 2.0
ondra.novacisko.cz Re: subversion 2.0
Karel Minařík Re: subversion 2.0
ondra.novacisko.cz Re: subversion 2.0
Karel Minařík Re: subversion 2.0
Martin Vanek Re: subversion 2.0
ijacek Re: subversion 2.0
Martin Vanek Re: subversion 2.0
Martin Malý Re: subversion 2.0
Martin Vanek Re: subversion 2.0
Martin Malý Re: subversion 2.0
Martin Vanek Re: subversion 2.0
Martin Malý Re: subversion 2.0
Martin Vanek Re: subversion 2.0
Martin Malý Re: subversion 2.0
Borek Bernard Re: subversion 2.0
Inkvizitor Re: subversion 2.0
ijacek Re: subversion 2.0
Martin Vanek Re: subversion 2.0
ijacek Re: subversion 2.0
František Kučera Mergování
Karel Minařík Re: Mergování
Borek Bernard Re: Mergování
Karel Minařík Re: Mergování
František Kučera Re: Mergování
ondra.novacisko.cz Re: subversion 2.0
Martin Malý Re: subversion 2.0
ondra.novacisko.cz Re: subversion 2.0
Inkvizitor Re: subversion 2.0
uf Re: subversion 2.0
setapoux Re: subversion 2.0
ondra.novacisko.cz Re: subversion 2.0
ijacek Re: subversion 2.0
ondra.novacisko.cz Re: subversion 2.0
ijacek Re: subversion 2.0
Hok Re: subversion 2.0
ondra.novacisko.cz Re: subversion 2.0
ijacek Re: subversion 2.0
Borek Bernard Re: subversion 2.0
Hok Re: subversion 2.0
ondra.novacisko.cz Re: subversion 2.0
vandrovnik Re: subversion 2.0
BostX Re: subversion 2.0
Bretislav Wajtr, ml. GIT vs Perforce
vlk Re: GIT vs Perforce
Karel Minařík Re: GIT vs Perforce
abtris Re: GIT vs Perforce
abtris Re: GIT vs Perforce
kaja47 aee4bd941f8b4d9e39210c06c44fcb71
pr.rybar Bazaar
uf celkove
Almad Re: celkove
Jan Sládek Díky za skvělý článek i seriál
Dundee5 Díky
veros Díky
Michal Mrtvej odkaz
Zdroj: https://www.zdrojak.cz/?p=3141