Proč je Git lepší než X?

where "x" is one of
Tyto stránky vznikly proto, že v poslední době musím stále obhajovat Gitstery vůči obvinění z podléhání módě a slepého sledování toho, co je „cool“. Shromáždil jsem tedy několik dobrých důvodů, proč lidé používají Git a nikoliv „X“, a proč byste to měli taky udělat. Stačí kliknout na některý z důvodů a začíst se do něj.
hg bzr svn perforce

Snadná práce s lokálními větvemi (branches)

Pravděpodobně nejlákavější vlastností Gitu, která jej skutečně odlišuje od ostatních verzovacích nástrojů (SCM), je jeho přístup k „větvím“ (branches) zdrojového kódu. Radikálně se liší od ostatních přístupů, s nimiž jej zde srovnáváme a které zpravidla chápou branch jako klon celého repositáře v novém adresáři.
Git funguje jinak. Git vám dovoluje mít několik lokálních branches zdrojového kódu, které na sobě mohou být zcela nezávislé. Vytváření, spojování a mazání těchto „větví“, resp. „verzí“ obsahu je otázka sekund.
To vám umožňuje provádět zajímavé věci:
  • Zkoušíte si nějaký nápad, pro který vytvoříte zvláštní branch. Můžete do ní průběžně commitovat. Můžete se přepnout zpět do předchozí branche, provést opravu části kódu a commitnout ji. Poté můžete pokračovat v práci na nápadu, a když jste hotovi, mergovat vaši práci do původní branche.
  • Můžete mít branch, která vždy obsahuje pouze to, co nasazujete v produkční verzi aplikace. Jinou, kam mergujete věci k otestování a pak několik menších branchí pro každodenní práci.
  • Můžete vytvářet branch pro každý nový úkol, na němž pracujete. Mezi takovými branchemi můžete volně přecházet, po dokončení úkolu separátní branch mergovat do hlavní větve a smazat ji.
  • Můžete si vytvořit branch, ve kterém zkoušíte nějaké řešení, a když zjistíte, že to nebude fungovat, prostě tuto branch smažete, aniž by se kdokoliv dozvěděl, co jste prováděli — i když jste mezitím pushnuli jiné branche.
branches flowchart
Důležité je, že když pushujete do vzdáleného repositáře, nemusíte pushovat všechny branche. Můžete sdílet s ostatními jen některé z nich. To vám umožňuje si zkoušet různé nápady, aniž byste si dělali starosti tím, jak a kdy je budete mergovat nebo sdílet s ostatními.
Samozřejmě, je možné pracovat podobně i v ostatních nástrojích. Ale vyžaduje to daleko více práce a je to náchylnější k chybám. Git tento proces neuvěřitelně usnadňuje a když se jej naučíte, úplně změní způsob vaší práce.
jamis twitter trevorturk twitter thillerson twitter boblmartens twitter mathie twitter
svn perforce

Vše je lokální

To samozřejmě platí pro všechny distribuované verzovací systémy – pro Git však dvojnásob. Téměř všechny jeho příkazy kromě fetch, pullpush si povídají jen s vaším diskem.
Díky tomu probíhá většina operací daleko rychleji, než jste asi zvyklí, především však můžete pracovat offline. Může se vám zdát, že to není tak důležité, ale pořád mně překvapuje, jak často je to potřeba. Možnost pracovat s větvemi, commitovat a prohlížet si historii projektu v letadle nebo ve vlaku zvyšuje vaši produktivitu.
local repo to remote repo flowchart
Dokonce i v Mercurialu běžné příkazy jako incoming a outgoing volají na server, zatímco v Gitu můžete provést fetch všech dat ze serveru předtím, než se odpojíte a porovnávat, mergovat a prohlížet si logy pro data, které jsou na serveru, ale ještě ne ve vašich lokálních branchích.
To znamená, že máte velmi snadný přístup nejen ke svému kódu, ale i ke kódu kolegů, kteří pracují ve stejném repositáři, aniž byste si museli jejich branchemi zaplevelovat vlastní kód.
bzr svn perforce

Git je rychlý

Git je rychlý. Přiznávají to i ti nejzarytější příznivci ostatních nástrojů. Všechny operace v Gitu se provádějí lokálně a tak má obrovskou výhodu oproti SVN a Perforce, které vyžadují přístup k síti, aby vůbec fungovaly. Ale i ve srovnání s ostatními distribuovanými verzovacími nástroji, které také pracují lokálně, je Git zatraceně rychlý.
Jedním z důvodů pravděpodobně bude to, že Git byl vytvořen pro správu Linuxového kernelu, takže se musel efektivně vypořádat s velkými repositáři hned od začátku. Navíc je Git napsán v C, takže má velmi malou režii oproti programovacím jazykům vyšší úrovně. A konečně, Git je tak rychlý, protože vývojáři rychlost stanovili jako jeden z jeho cílů.
Níže jsou zobrazeny výsledky měření, která jsem provedl na třech kopiích zdrojového kódu frameworku Django ve třech různých verzovacích nástrojích: Git, Mercurial a Bazaar. Měření jsem prováděl také v SVN, ale věřte mi, je pomalejší — víceméně se shoduje s čísly Bazaaru, když přičtete latenci danou připojením k vzdálenému serveru.
init benchmarks add benchmarks status benchmarks diff benchmarks branching benchmarks
tag benchmarks log benchmarks large commit benchmarks small commit benchmarks
Výsledkem je, že cokoliv kromě přidávání nových souborů je v Gitu rychlejší. (Platí to také pro hodně velké commity, kde byl Mercurial víceméně stejně rychlý. Commit, na němž jsem testování prováděl, byl ale tak velký, že pravděpodobně takový nikdy dělat nebudete. Běžné commity jsou v Gitu mnohem rychlejší.)
Git Hg Bzr
Init 0.024s 0.059s 0.600s
Add 8.535s 0.368s 2.381s
Status 0.451s 1.946s 14.744s
Diff 0.543s 2.189s 14.248s
Tag 0.056s 1.201s 1.892s
Log 0.711s 2.650s 9.055s
Commit (velký) 12.480s 12.500s 23.002s
Commit (malý) 0.086s 0.517s 1.139s
Branch (studený start) 1.161s 94.681s 82.249s
Branch (teplý start) 0.070s 12.300s 39.411s
Čísla pro „studený“ a „teplý“ start při vytváření branches znamenají první a opakovanou operaci — při druhé operaci již tedy byla branch uložena na disku.
Měl bych dodat, že ačkoliv čísla pro operaci add jsou u Gitu vysoká, jednalo se o masivní opareci — přes 2 000 souborů. Pro většinu toho, co každý z nás běžně dělá, zaberou operace add pouhé zlomky sekund. Všechny ostatní uvedené operace (možná kromě onoho obrovského commitu) jsou při každodenní práci daleko častější.
Tato měření si může každý provést snadno sám: prostě jen naklonujte zdrojového kódy projektu Django v různých verzovacích systémech a vyzkoušejte v každém z nich tytéž operace.
  • git clone git://github.com/brosner/django.git dj-git
  • hg clone http://hg.dpaste.com/django/trunk dj-hg
  • bzr branch lp:django dj-bzr
  • svn checkout http://code.djangoproject.com/svn/django/trunk dj-svn
svn

Git je malý

Git neplýtvá místem na disku. Adresář s Git repositářem nebude ve většině případů o mnoho větší než SVN checkout — a v některých případech bude dokonce menší. Jak se zdá, do všech těch .svn adresářů toho přijde hodně.
Následující čísla jsem získal naklonováním projektu Django z jeho polo-oficiálních repositářů v příslušném verzovacím systému ve stejném bodě jeho historie:
Git Hg Bzr SVN
Samotný repositář 24M 34M 45M
Celý adresář 43M 53M 64M 61M
hg bzr svn perforce

Staging Area

Unikátní vlastností Gitu je tzv. „staging area“ neboli „index“. Jedná se o zvláštní „zónu“, kde můžete připravit detaily commitu ještě před tím, než jej doopravdy commitujete do repositáře.
Na „staging area“ je výborné, že můžete velmi snadno připravit ke commitu soubory na kterých pracujete podle toho, jak jste s nimi hotovi, a pak je commitovat, aniž byste zároveň commitovali i ostatní rozpracované soubory ve vašem projektu a aniž byste je museli výslovně uvádět při commitu. Tohle Git skutečně odlišuje od ostatních nástrojů a systémů, s nimiž ho zde srovnáváme.
add commit workflow diagram
„Staging area“ vám také umožňuje připravit ke commitu pouze určité části změněného souboru. Pryč jsou tedy časy, kdy jste litovali toho, že jste v souboru změnili něco, co nesouviselo s dřívější změnou, aniž byste ji commitovali. V Gitu můžete dřívější změnu připravit ke commitu zvlášť a zvlášť ji tedy commitovat. A v dalším kroku můžete commitovat změnu druhou. Takto můžete pracovat i s těmi nejmenšími změnami v souboru.
Samozřejmě, pokud budete tuto vlastnost chtít ignorovat, můžete k příkazu commit jednoduše přidat -a, a všechny změny ve všech změněných souborech budou přidány do commitu.
commit only workflow diagram
svn perforce

Distribuovaný verzovací systém

Jedna z nejlepších vlastností všech distribuovaných systémů na správu verzí včetně Gitu je to, že jsou … distribuované. Místo toho, abyste provedli „checkout“ poslední verze obsahu, získáte „klon“ celého repositáře.
To znamená, že i když používáte centralizované workflow, každý uživatel má kopii, kompletní zálohu celého serveru. Každá z těchto kopií může nahradit kopii „hlavní“, resp. „centrální“, pokud by došlo ke ztrátě nebo poškození dat. Při práci v Gitu tedy neexistuje ono známé „jedno zranitelné místo“ (angl. single point of failure) — tedy pokud neukládáte data doslova jen na jediné „místo“.
Mohli byste si myslet, že to musí práci zpomalovat, není to ale pravda. Obvykle jsou distribuované systémy na správu verzí jen o málo pomalejší než Subversion. A z distribuovaných systémů, které jsem testoval, byl Git nejrychlejší.
cloning benchmarks
Git 1m 59s
Hg 2m 24s
Bzr 5m 11s
SVN 1m 4s
svn perforce

Jakékoliv workflow

Jedna z nejcennějších věcí na Gitu je to, že díky jeho distribuované povaze a perfektní práci s branchemi můžete snadno používat téměř jakékoliv workflow, které si vymyslíte.

Workflow typu „jako v Subversion“

Velmi obvyklé workflow, speciálně u lidí přecházejících z centralizovaných systémů je právě: centralizované workflow. Git vám neumožní nahrát změny na server, pokud tam mezitím nějaké nahrál někdo jiný, a vy jste si jeho změny nestáhli.
subversion-style workflow

Workflow typu „koordinátor“

Jiným běžným workflow je situace, kdy existuje koordinátor — osoba, která nahrává změny do „požehnaného“ repositáře. Ostatní vývojáři, kteří mají tento repositář naklonovaný, pak nahrávají změny do svých repositářů dostupných přes síť a žádají koordinátora, aby si jejich změny stáhnul a začlenil do „požehnaného“ repositáře. Tento typ workflow je často k vidění u open source projektů nebo u repositářů spravovaných na Githubu.
integration manager workflow

Workflow typu „generál a pobočníci“

Pro opravdu rozsáhlé projekty lze využít infrastrukturu podobnou té, jakou využívá Linuxový kernel. Lidé, kteří se starají o určitou část celého systému („pobočníci“) začleňují do svých repositářů změny od ostatních vývojářů, které se týkají právě této části. Hlavní koordinátor („generál“) si pak od těchto „pobočníků“ stahuje změny a začleňuje je do „požehnaného“ repositáře.
dictator and lieutenants workflow

Git je ale co se workflow týče velmi flexibilní, takže si můžete vytvořit nebo adaptovat workflow zcela podle svých představ a potřeb.
hg svn perforce

GitHub

octocat
Zde se dostávám na tenký led, vzhledem k tomu, že GitHub je můj zaměstnavatel, ale tuto sekci jsem přesto přidal, protože mnoho lidí říká, že GitHub byl důvodem, proč si vybrali Git.
Tím důvodem může být přesněji to, že GitHub je spíše sociální sítí zaměřenou na zdrojový kód než prostým Git hostingem. Najdete zde projekty a programátory, kteří se zabývají něčím podobným jako vy, můžete si snadno vytvořit fork jiného repositáře a podílet se na společné práci. To vytváří kolem Gitu a projektů, které jej využívají, velmi živou komunitu.
Existuje pár dalších podobných služeb, jak pro Git, tak pro ostatní systémy na správu verzí, ale málo z nich je tak silně orientovaných na samotné uživatele a sociální aspekty, a žádná z nich nemá takový počet uživatelů. Git a GitHub jsou tedy ideální pro rychle se vyvíjející open source projekty.
Takovou komunitu zkrátka u jiných verzovacích systémů nenajdete.
perforce

Git se snadno naučíte

V dřívějších fázích života Gitu to rozhodně nebyla pravda. Git býval spíše kolekcí různých nástrojů, které umožňovaly pracovat s verzovaným souborovým systémem distribuovaným způsobem než skutečným systémem na správu verzí. Dnes jsou ale příkazy Gitu a jejich pochopitelnost podobné jako u ostatních nástrojů, a oproti některým nástrojům je na tom Git i lépe.
To je samozřejmě těžké prokázat objektivně, bez toho, abychom provedli podrobnější studii. Proto níže jen ukazuji výchozí nápovědu pro příkazy Mercurialu a Gitu. Příkazy, které jsou shodné nebo velmi podobné u obou nástrojů jsem zvýraznil. (Když napíšete hg help, získáte seznam asi 40 příkazů pro Mercurial.)

Nápověda pro Mercurial

add        add the specified files ...
annotate   show changeset informati...
clone      make a copy of an existi...
commit     commit the specified fil...
diff       diff repository (or sele...
export     dump the header and diff...
init       create a new repository ...
log        show revision history of...
merge      merge working directory ...
parents    show the parents of the ...
pull       pull changes from the sp...
push       push changes to the spec...
remove     remove the specified fil...
serve      export the repository vi...
status     show changed files in th...
update     update working directory

Nápověda pro Git

add        Add file contents to the index
bisect     Find the change that introduce...
branch     List, create, or delete branches
checkout   Checkout a branch or paths to ...
clone      Clone a repository into a new ...
commit     Record changes to the repository
diff       Show changes between commits, ...
fetch      Download objects and refs from...
grep       Print lines matching a pattern
init       Create an empty git repository
log        Show commit logs
merge      Join two or more development h...
mv         Move or rename a file, a direc...
pull       Fetch from and merge with anot...
push       Update remote refs along with ...
rebase     Forward-port local commits to ...
reset      Reset current HEAD to the spec...
rm         Remove files from the working ...
show       Show various types of objects
status     Show the working tree status
tag        Create, list, delete or verify...
Všechny příkazy Gitu bývaly — před verzí 1.6 — v cestě k programům (PATH), a to spoustu lidí mátlo. Ačkoliv všechny tyto příkazy můžete stále používat, v cestě je nyní jediný příkaz: git, takže např. Mercurial a Git mají nyní téměř totožnou nabídku příkazů a nápovědu. Z pohledu záčatečníka je jejich rozhraní skoro stejné.
Dnes již je velmi obtížné věrohodně argumentovat, že Mercurial nebo Bazaar se lze naučit snadněji.