Do what you have to do
GIT
Minutka s verzovacím systémem GIT #4 – branch, checkout
30. Srp
Pondělí na Initd.cz patří GITu, a i když jsem se dnes trochu zdržel kvůli práci, určitě vás o další kapku z GITu neochudím. Tématem dne budou větve a příkazy branch a checkout. Není to složité, takže to vezmeme rychle.
Verzovací systém GIT je na větvích založen, má pro ně podporu a je připraven jich pojmout hodně a různě mezi nimi přelévat kód. Větev si můžete vytvořit pro různé účely, což je třeba oddělený vývoj různých verzí, dočasné oddělení vývoje jedné vlastnosti programu nebo třeba oddělení vývoje pro několik různých platforem. Žádná větev není hlavní, ale pokud to tak chcete, můžete se k jedné tak chovat. Princip větví oceníte pokud vás na jednom projektu pracuje více. Každý má svůj repositář se svými větvemi. Tam se vývojářům nemíchá kód do sebe. Hlavní vývojář pak může jednotlivé větve (i vzdálené) spojovat do jedné a dát dohromady nové vydání celého zdrojového kódu.
V SVN se větve dělají tak, že se prostě vytvoří nový adresář a vývojář tím prakticky ztratí možnost dostat jednoduše změny z jedné větve do druhé. V GITu to neplatí a větve jsou od sebe odděleny, takže každá má svůj log a víte co se v její minulosti dělo. Jejich spojování a rozdělování lze zobrazit i graficky, ale o tom až jindy.
Větev je v GITu pouze záznam o tom, které commity se mají sloučit. Můžete tedy mít jednu změnu v několika větvích a v repositáři bude fyzicky uložena pouze jednou. Spojování a rozdělování je pak hračkou. Seznam větví získáme napsáním:
-
$ git branch
-
donald
-
* master
Pokud chcete zobrazit i vzdálené větve, uděláte to přidáním parametru -a:
-
$ git branch -a
-
donald
-
* master
-
remotes/origin/HEAD -> origin/master
-
remotes/origin/master
Vzdálené větve jsou takové, které se nenacházejí v lokálním repositáři, ale máte je o nich vytvořený záznam pomocí příkazu remote.
Pro přepínání mezi větvemi použijeme příkaz checkout. Při přepínání si dejte pozor na to, jestli nenecháváte nějaké změny v pracovním adresáři.
-
$ git checkout donald
-
Switched to branch ‘donald’
Pokud potřebujete vytvořit větev novou, založenou na té, ve které se aktuálně nacházíte, použijte parametr -b.
-
$ git checkout -b dev
-
Switched to a new branch ‘dev’
Příště si ukážeme práci s jednotlivými větvemi. To znamená spojování větví a změna jejich základu přes příkazy merge a rebase.
Minutka s verzovacím systémem GIT #3 – remote, clone, push, pull, reset
23. Srp
Ať už používáte GIT ve skupince kolegů nebo pro samotářský vývoj, několika repositářům se nevyhnete. Já mám pro každý projekt jeden repositář na netbooku, na server a nakonec ten hlavní mám na desktopu, kde probíhá většinou nejrušivější vývoj. Je tedy nezbytně nutné, abychom uměli s těmito repositáři komunikovat, přelívat kód z jednoho do druhého a navíc, abychom uměli řešit situaci, kdy pracujeme na nějaké funkci a ve vzdáleném repositáři došlo k nějakým změnám, protože bylo třeba potřeba něco opravit. Hlavně ze začátku, než pochopíte, jak GIT s vaším kódem pracuje, je důležité se držet postupů, které nezničí změny na jednom či druhém místě.
Klíčem ke všem vzdáleným operacím jsou příkazy:
- remote
- push
- pull
- fetch
Začneme tím, že si pojmenujeme všechny vzdálené stroje v repositáři. To se dělá pomocí příkazu remote. GIT umí pracovat téměř se vším, co umí nějak přenášet adresářovou strukturu, ale tento seriál bude zaměřen primárně na SSH a to jak z důvodu jednoduchosti, tak bezpečnosti.
-
git remote add [název] [url]
-
git remote rename [starý název] [nový název]
-
git remote rm [název]
-
git show [název]
Velmi zjednodušený výtažek z manuálu vám pomůže pochopit, jak se s remote pracuje. Jde vlastně o takové aliasy, kterými pojmenujete vzdálené repositáře a pod nimi je pak bude GIT znát. Pokud používáte SSH, je nutné pro přístup k repositáři vyplnit adresu server (v horším případě IP) a pak cestu repositáři. Výsledek může vypadat třeba takhle:
-
git clone cx@100.165.48.51:~/vyvoj/projekt
Všimněte si, že je potřeba vyplnit vcelku nezapamatovatelná IP adresa, jméno uživatele a pak cestu k repositáři, která je v tomto případě ještě docela krátká. Také si všimněte, že jsem použil zatím neznámý příkaz clone. S ním lze naklonovat nějaký vzdálený repositář a pak budete mít na lokálním stroji jeho přesnou kopii. To se samozřejmě dělá jen u vytváření repositářů, takže na existující lokální repositář to nepoužívejte.
Nebudeme dál otálet a vytvoříme si alias pomocí příkazu remote.
-
git remote add repo1 cx@100.165.48.51:~/vyvoj/projekt
Pokračovat dál na příkladu klonování není zrovna dobrý nápad, takže na novém aliasu vyzkoušíme příkaz pull:
-
git pull repo1
Tímto jsme zajistili, že se změny udělané v repositáři repo1 natáhnou k nám. Pokud dojde ke konfliktům, je potřeba je vyřešit, ale o tom bude jeden z dalších dílů. Když takto chudě osázený příkaz pull spustíte, vyběhne vám dlouhý text, který vám mimo jiné oznámí, že se GIT pokusil stáhnout obsah všech větví ve vzdáleném repositáři, jejichž název se shoduje s názvy lokálních větví. O větvích budeme pro změnu mluvit v příštím díle a tuto informaci vám sděluji hlavně proto, abyste nepanikařili.
Když stáhnete změny, musíte si uvědomit, že se nezměnil pracovní adresář jak jste zvyklí třeba z SVN, ale jenom obsah repositáře. Proto je potřeba dávat pozor, abyste měli před použitím pull vše commitlé a pracovní adresář zůstal shodný s obsahem repositáře. To si překontrolujte pomocí příkazu status, o kterém jsme již mluvili. Pokud by se vám náhodou povedlo nejdříve stáhnout změny pomocí pull a až potom jste commitly pracovní adresář, změny, které jste stáhli se smažou, resp. se uloží commit, který udělá jejich přesný opak, takže repositář bude nakonec ve stavu před staženými změnami a bude v něm uložen rozdíl jak pro vytvoření stažených změn, tak pro jejich zrušení.
Víme na co si dát pozor a teď nastal čas uvést pracovní adresář do stavu v jakém se nachází repositář. To uděláme pomocí příkazu reset:
-
git reset –hard
Parametr –hard říká, že se nemá brát na nic ohled a změny, které jsou v pracovním adresáři provedený se tím pádem ztratí. Příkaz reset má ještě jeden velmi užitečný parametr a názvem –merge, který by mohl v příkladu nahradit –hard. Ten se pokusí sjednotit stáhnuté změny a zároveň udržet změny v pracovním adresáři. V této fázi ho nedoporučuji používat, protože byste se mohli dostat do situace, kdy by byl potřeba vyřešit nějaký konflikt a těm je lepší se momentálně vyhýbat. Až si probereme řešení konfliktů, bude ten správný čas hrát si s –merge, zatím platí varování výše.
Když uděláme všechny změny co jsme chtěli, je čas odeslat je do vzdáleného repositáře. Tento postup také moc nedoporučuji a pokud je to možné, spíše se přiklánějte ke stahování změn od vás z druhé strany. Pokud totiž na druhé straně opět došlo k nějakým změnám, commity se neodešlou a budete to muset udělat tak jako tak z druhé strany.
K odeslání změn slouží příkaz push.
-
git push repo1
Nakonec ještě jednu poznámku a tou také skončíme. Jak jsem řekl, GIT používám hlavně přes SSH, ale určitě se setkáte ještě s minimálně jednou formou vzdáleného repositáře a to je jiný lokální repositář. K němu přistupujeme pouhým zadáním cesty, třeba:
-
git clone /home/test/vyvoj/repo2
Můžeme samozřejmě vytvořit i alias:
-
git remote add repo2 /home/test/vyvoj/repo2
A používat pull/push podle libosti:
-
git pull repo2
Příště se podíváme na práci s větvemi, které se nám budou velmi hodit k příkazům push, pull a nakonec i zatím neznámým příkazům merge a rebase.
Minutka s verzovacím systémem GIT #2 – add, commit, log
16. Srp
V minulém díle jsme se seznámili s příkazy init a status, které nám vytvoří repositář a ukáží stav pracovního adresáře. Dnes si vytvoříme první commit a koukneme se na historii všech commitů v repositáři. K tomu budeme používat příkazy add, commit a log.
Nejprve ale musíme začít s trochou teorie. Nejčastější chybou při používání GITu je vytváření commitu po dlouhé době, kdy jste třeba poupravili deset souborů a dalších pět přidali. Správně byste měli commitovat „jak to jen půjde„. Nemám tím na mysli třeba commitnout změnu na dvou řádcích, ale měli byste si rozdělit aktuální problém na několik menších změn a ty udělat. Později budete moct commity upravit a udělat z nich něco lepšího, ale určitě se vám budou špatně rozdělovat. Dělat časté commity vám bude trvat asi déle, než si osvojit ovládání samotného GITu.
Historie pro projekt je důležitá hlavně při práci v týmu. Vy víte co jste udělali před týdnem nebo o tom máte alespoň tušení, ale jiní vývojáři třeba ne a ti potřebují detailní info o tom, kam projekt směřuje. Nebojte se do popisků ke commitům dávat TODO řádky s tím co je potřeba udělat nebo třeba dávat tam také informace o tom co je jak otestováno.
Pro jednodušší rozdělení práce vám poslouží příkaz add. Ten, jak jeho název napovídá, přidá soubory z pracovního adresáře do repositáře. I když se budu možná opakovat, pro pochopení je důležité si uvědomit, že pracovní adresář je ten, ve kterém děláte změny. V pracovním repositáři je pak uložen adresář .git, kde je uložen repositář a všechny soubory, které GIT ke své činnosti potřebuje. Další věc, kterou je potřeba si při práci s GITem pamatovat je, že při změně nějakého souboru, se tento soubor jakoby vyřadí z repositáře nebo spíše přesněji, stará verze v repositáři zůstává, ale změna, kterou jste na souboru udělali v něm není. Když se rozhodnete vytvořt commit, můžete si vybrat pomocí add, které změněné soubory v tomto commitu mají být a které ne.
Příklad:
-
$ pwd
-
~/test_repo
-
$ echo "ahoj světe" > foo.txt
-
$ git add foo.txt
-
$ git commit
-
[master (root-commit) 600330b] První soubor
-
1 files changed, 1 insertions(+), 0 deletions(-)
-
create mode 100644 foo.txt
Tady vás GIT požádá o vyplnění popisu ke commitů, pamatujte, že není důvod být stručný. Také si pamatujte, že první řádek by měl popsat commit souhrně, další řádek by měl být prázdný a pak by měly následovat detaily.
Teď si zkusíme soubor změnit:
-
$ echo "ahoj světe podruhé" >> foo.txt
-
$ cat foo.txt
-
ahoj světe
-
ahoj světe podruhé
-
$ git status
-
# On branch master
-
# Changed but not updated:
-
# (use "git add <file>…" to update what will be committed)
-
# (use "git checkout — </file><file>…" to discard changes in working directory)
-
#
-
# modified: foo.txt
-
#
-
no changes added to commit (use "git add" and/or "git commit -a")</file>
Všimněte si, že GIT zpozoroval, že se něco děje a rovnou napovídá, že můžeme dát git add foo.txt, abychom změnu přidaly do příštího commitu. To můžeme udělat a postupovat stejně jako v minulém příkladu, tedy napsat git add foo.txt a dát git commit, pak vyplníme popis a je nový commit je na světě.
Druhou možností je nestarat se o přidávání jednotlivých souborů, ale commitnout prostě všechny změny pomocí:
-
$ git commit -a
-
[master ef4b9d6] Všechny změny
-
1 files changed, 1 insertions(+), 0 deletions(-)
-
$ git status
-
# On branch master
-
nothing to commit (working directory clean)
-
$ git log
-
commit ef4b9d62d511bfa36714002f3dd9cf7dc77051fa
-
Author: Adam <cx @initd.cz>
-
Date: Sun Aug 1 20:36:52 2010 +0200
-
-
Všechny změny
-
-
Detaily ke všem změnám
-
-
commit 600330b901de9d85cd49dd59a29d31f98187e379
-
Author: Adam </cx><cx @initd.cz>
-
Date: Sun Aug 1 20:32:48 2010 +0200
-
-
První soubor
-
-
Detaily k prvnímu souboru</cx>
Commit všech souborů se dělá přidáním parametru -a k příkazu commit. Zároveň jsme zkusili co vypíše git status a v něm vidíme, že už žádná změna na commitnutí nečeká. Nakonec jsme se podívali na historii změn v logu pomocí git log. Další možnosti výpisu historie jsou třeba tyto:
-
$ git log –shortstat
-
commit ef4b9d62d511bfa36714002f3dd9cf7dc77051fa
-
Author: Adam <cx @initd.cz>
-
Date: Sun Aug 1 20:36:52 2010 +0200
-
-
Všechny změny
-
-
Detaily ke všem změnám
-
-
1 files changed, 1 insertions(+), 0 deletions(-)
-
-
commit 600330b901de9d85cd49dd59a29d31f98187e379
-
Author: Adam </cx><cx @initd.cz>
-
Date: Sun Aug 1 20:32:48 2010 +0200
-
-
První soubor
-
-
Detaily k prvnímu souboru
-
-
1 files changed, 1 insertions(+), 0 deletions(-)
-
$ git log –summary
-
commit ef4b9d62d511bfa36714002f3dd9cf7dc77051fa
-
Author: Adam </cx><cx @initd.cz>
-
Date: Sun Aug 1 20:36:52 2010 +0200
-
-
Všechny změny
-
-
Detaily ke všem změnám
-
-
-
commit 600330b901de9d85cd49dd59a29d31f98187e379
-
Author: Adam </cx><cx @initd.cz>
-
Date: Sun Aug 1 20:32:48 2010 +0200
-
-
První soubor
-
-
Detaily k prvnímu souboru
-
-
create mode 100644 foo.txt</cx>
Teď už byste měli umět pracovat nějak s gitem a zkoušet si do něj nahrávat nějaké zdrojáky. K tomu vám bude nápomocen program man s parametrem git-[příkaz], kde [příkaz] nahradíte příkazem z GITu (init, log, commit, add, …).
Minutka s verzovacím systémem GIT #1 – motivační úvod, init, status
9. Srp
Při své práci mimo Root.cz používám hlavně čtyři technologie/nástroje, bez kterých bych se dnes už asi neobešel. Převážně programuji různé většinou webové aplikace a starám se o servery. Někdy se obě činnosti propojují a když už se do něčeho opravdu pustím, vzniká u toho hromada kódů všech kvalit a je potřeba všechen kód dát nějak dohromady, aby byla možnost ho používat ještě jinde. To krom roků zkušeností a nezdarů vyžaduje i pořádnou správu verzí, abyste věděli, co jste kdy dělali.
Proto chci na svém blogu každé pondělí vydávat krátký post o některé funkci GITu a postupně tak dostat čtenáře do stavu, kdy bude schopen GIT používat taky.
Pokud jste nedočkaví, určitě vám pomůže těchto několik odkazů:
- Domácí stránka GITu
- Pro Git – knížka přeložená do čeština díky CZ.NIC
- Seriál na Root.cz
Pravou sílou GITu je, že všichni vývojáři mají rovná práva. Tím mám namysli, že každý vývojář má jeden či více svých repositářů s několika větvemi vývoje, kde dává dohromady na ostatních nezávislý kód. Ten postupně nahrává do svého repositáře a jednotlivým změnám se říká commit. Každý commit má identifikátor, podle kterého s ním můžete dále pracovat, ale osobně to moc často nedělám, leda ve chvíli, kdy je potřeba najít nějaká chyba, ale o tom až někdy za hodně dlouho, protože tak rozsáhlý kód, abych fičury na hledání chyb potřeboval jsem ještě nedělal.
Levou sílou GITu jsou větve. Znáte takové ty situace, kdy je potřeba udělat nějaká změna na produkční verzi, často oprava nevyhnutelného bugu, ale u sebe máte rozkopanou verzi, která rozhodně nemůže ven a tam ta chyba je taky? S GITem prostě pracujete v nějaké vývojové větvi a na serveru je třeba větev master. Klidně si uděláte několik změn ve větvi master a na vývojovou větev nehledíte. Když máte všechny nové vlastnosti hotovy a odzkoušeny, jednoduše nejdříve změníte základ vaší vývojové větve na větev master a po vyřešení konfliktů (které přijít nemusí) je změna uložena i tam a můžete obě větve hezky spojit.
Ještě než začneme, musíme si GIT nakonfigurovat, přesněji nadefinovat jméno a e-mail, se kterými GIT pracuje:
-
$ git config –global user.name "Adam Strauch"
-
$ git config –global user.email cx@initd.cz
Ve vašem domácím adresáři se vytvoří soubor ~/.gitconfig s obsahem:
[user] name = Adam email = cx@initd.cz
Abych vás nenechal na konci jen tak koukat do země, vytvoříme si náš první repositář:
-
$ mkdir test_repo
-
$ cd test_repo
-
$ git init
Tím jsme vytvořily repositář a poznáme ho tak, že po napsání:
-
$ ls -a
dostaneme něco jako:
-
$ . .. .git
V adresáři .git se budou ukládat všechny vaše změny, které uděláte v adresáři s repositářem, kterému se říká pracovní adresář.
Provedené změny vypíšete pomocí:
-
$ git status
A to je pro dnešek vše, příště se podíváme na vytváření commitů a pamatujte, GIT byl vytvořen pro vývoj jádra a i když se může zdát ze začátku složitý, po prvním pár commitech si ho zamilujete.