GitMagic (7) – tajemství odhalena
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

GitMagic (7) – tajemství odhalenaGitMagic (7) – tajemství odhalena

 

GitMagic (7) – tajemství odhalena

Google       Google       29. 6. 2009       12 022×

Nakoukneme pod kapotu a vysvětlíme si, jak Git uskutečnujě své zázraky. Detaily trochu odbydu. Pro opravdu podrobný popis vás odkazuji na uživatelský manuál.

Neviditelnost

Jak může být Git tak nevtíravý? Krom výjimečných commitů a slučování (ang. merge) můžete pracovat bez vědomí, že nějaký verzovací systém vůbec existuje. Tak to pokračuje, dokud ho nepotřebujete a jste rádi, že na vás Git celý čas dohlížel.

Ostatní verzovací systémy vám nedovolí, abyste na ně zapomněli. Přístupová práva k souborům mohou být jen pro čtení, dokud výslovně neřeknete serveru, na jakých souborech se chystáte pracovat, protože server může potřebovat udržovat informace o tom, kdo a kdy získal jaký kód. Když spadne síť, budete brzy trpět. Vývojáři se neustále byrokraticky mlátí.

Tajemstvím je adresář .git ve vašem pracovním adresáři. Git udržuje historii projektu právě tady. Název začínající tečkou zabraňuje, aby se adresář objevoval ve výstupech příkazů jako ls. Všechny operace kromě push a pull pracují v tomto adresáři.

Máte naprostou kontrolu nad osudem svých souborů, protože Gitu je jedno, co s nimi děláte, a může kdykoli jednoduše znovu vytvořit uložený stav z podadresáře .git.

Integrita

Mnoho lidí si spojuje kryptografii s udržováním informací tajných, ale jiným, stejně důležitým, cílem je udržet informace nepoškozené. Vyhovujícím použitím kryptografické hashovací funkce můžeme předejít náhodnému či záměrnému poškození dat.

O SHA1 hashi můžeme smýšlet jako o jedinečném 160-bitovém ID pro každý řetězec bytů, který kdy v životě potkáme. Vlastně více než to: každý řetězec bytů, který jakýkoli člověk kdy použije.

Jelikož je SHA1 hash sám o sobě řetězec bytů, můžeme hashovat řetězce bytů obsahující ostatní hashe. Tato jednoduchá skutečnost je udivujícně užitečná: hle „hashové řetězce“. Později uvidíme, jak je Git účinně používá k zaručení integrity dat.

Stručně, Git udržuje vaše data v podadresáři .git/objects, kde místo normálních jmen souborů najdete jenom jejich ID. Používáním ID jako jmen souborů, stejně jako pár souborů se zámky a triků s časovými značkami, Git převede jakýkoli skromný filesystém do účinné a robustní databáze.

Chytrost

Jak Git ví, že jste přejmenovali soubor, i když jste to nikdy výslovně nezmínili? Samozřejmě, že můžete spustit git mv, ale to je úplně to samé jako git rm následované git add.

Git chytře vyčmuchá přejmenování a kopie mezi za sebou jdoucími verzemi. Popravdě může najít dokonce kousky kódu přesunuté nebo zkopírované ze souboru do souboru! I když nemůže pokrýt všechny případy, dělá dobrou práci a tato jeho vlastnost se neustále zlepšuje. Pokud vám to nefunguje, zkuste navolit možnosti povolující lepší rozpoznávání kopírování a popřemýšlejte po přechodu na novější verzi.

Indexování

Pro každý sledovaný soubor Git zaznamenává informace jako velikost souboru, jeho čas vytvoření a poslední změny, které jsou známé jako „index“. K určení, jestli se soubor změnil, Git porovná tyto údaje s těmi aktuálními. Pokud se shodují, Git může přeskočit čtení celého souboru.

Poněvadž je získávání informací o stavu souboru považováno za rychlejší než čtení souboru, pokud změníte pouze pár souborů, Git může zaktualizovat svůj stav prakticky okamžitě.

Holé repozitáře

Možná jste se divili, jaký formát používají online Gití repozitáře. Jsou to normální Gití repozitáře, stejně jako podadresář .git, jen s tím rozdílem, že mají jména jako projekt.git a nemají přiřazený žádný pracovní adresář.

Většina Gitích příkazů očekává, že najde index v .git, a skončí chybou při práci na těchto holých repozitářích. Vyřešit to můžete nastavením proměnné prostředí GIT_DIR na cestu k holému repozitáři nebo spuštěním Gitu v samotném adresáři s takovým repozitářem s volbou --bare.

Původ Gitu

Tento příspěvek na Linux Kernel Mailing List vysvětluje řetězec událostí, které vedly ke Gitu, jak ho známe dnes. Celé vlákno je úchvatným archeologickým místem pro Gití historiky.

Databáze objektů

Zde je návod, jak napsat systém podobný Gitu za pár hodin.

Bloby

Nejdříve jedno kouzlo. Vyberte si název souboru, jakýkoli název. A v prázdném adresáři:

$ echo super > NAZEV_SOUBORU
$ git init
$ git add .
$ find .git/objects -type f

Uvidíte .git/objects/16/f5c2d3aa9656fc424352e4cfaa2523c809778b.

Jak to můžu vědět bez toho, abych znal název souboru? Jen to proto, že SHA1 hash z:

"blob" SP "6" NUL "super" LF

je 16f5c2d3aa9656fc42435­2e4cfaa2523c809778­b, kde SP je mezera (ang. space), NUL je nulový byte a LF je odřádkování. Můžete si to ověřit napsáním:

$ echo "blob 6"$'\001'"super" | tr '\001' '\000' | sha1sum

Jen tak mimochodem, předchozí kód je psán s ohledem na Bash; jiné shelly možná jsou schopné pracovat s NULem na příkazové řádce, díky čemuž bychom se zbavili workaroundu s tr.

Git používá adresování podle obsahu: soubory nejsou ukládány podle jména, ale podle hashe dat, která obsahují; a to v souboru, který je nazván jako „blob object“. O hashi můžeme smýšlet jako o unikátním ID obsahu souboru, takže v tomto smyslu adresujeme soubory podle jejich obsahu. Počáteční blob 6 je pouze hlavička sestávající z typu objektu a jeho délky v bytech; zjednodušuje to vnitřní procesy.

Tudíž je jednoduché předpovědět, co uvidíte. Název souboru není důležitý: na vytvoření blob objektu jsou použita jenom data uvnitř.

Možná se můžete divit, co se stane se stejnými soubory. Zkuste přidat kopie vašeho souboru s jakýmkoli názvem souboru. Obsah .git/objects zůstane stejný bez ohledu na to, kolik jich přidáte. Git ukládá data pouze jednou.

Mimochodem, soubory v .git/objectsjsou zkomprimované pomocí zlib, takže se do nich nemůžete koukat přímo. Původní obsah získáte pomocí zpipe -d, nebo napsáním:

$ git cat-file -p 16f5c2d3aa9656fc424352e4cfaa2523c809778b

což hezky vytiskne předaný objekt.

Stromy

Ale kde jsou tedy názvy souborů? Jsou uloženy někde v indexu a Git se o ně postará při commitu:

$ git commit  # napište nějakou zprávu
$ find .git/objects -type f

Teď byste měli vidět 3 objekty. Tentokráte vám již nemohu říct, jaký název budou dva nové soubory mít, protože to závisí na názvu souboru, který jste vybrali. Pokročíme předpokladem, že jste váš soubor nazvali soubor. Pokud jste tak neudělali, můžete přepsat historii, aby to vypadalo, že jste tak udělali:

$ git filter-branch --tree-filter 'mv NAZEV_SOUBORU soubor'
$ find .git/objects -type f

Nyní byste měli vidět soubor .git/objects/21/0ba5665159efc75739ccb3a6332532669eda96, protože toto je SHA1 hash jeho obsahu:

"tree" SP "34" NUL "100644 soubor" NUL 0x16f5c2d3aa9656fc424352e4cfaa2523c809778b

Ověřte si, že soubor opravdu obsahuje data výše napsáním:

$ echo 210ba5665159efc75739ccb3a6332532669eda96 | git cat-file --batch

Se zpipe je také jednoduché ověřit hash:

$ zpipe -d < .git/objects/21/0ba5665159efc75739ccb3a6332532669eda96 | sha1sum

Ověření hashe skrz cat-file je trochu složitější, protože jeho obsah je mnohem víc než jen surový dekomprimovaný objekt.

Tento soubor je „tree“ objekt: seznam n-tic sestávajících z typu souboru, jeho jména a hashe. V našem případě je typ souboru 100644, což znamená, že soubor je normální soubor a hash je blob objekt, který v sobě ukrývá obsah souboru. Ostatní možné typy souborů jsou spustitelné soubory, symlinky nebo adresáře. V posledním případě hash odkazuje na další tree objekt.

Pokud spustíte filter-branch, budete mít staré objekty, které již více nepotřebujete. I když budou zničeny automaticky hned, jak nadejde jejich chvíle, teď je vymažeme, aby byl náš příklad jednodušší.

$ rm -r .git/refs/original
$ git reflog expire --expire==now --all
$ git prune

V opravdových projektech byste se měli těmto příkazům vyhnout, protože tím vlastně mažete zálohy. Pokud chcete repozitář čistý, je obvykle nejlepší udělat jeho nový klon. Také si dávejte pozor na manipulaci s adresářem .git: co když ve stejný okamžik běží nějaký jiný příkaz nebo z ničeho nic vypadne proud? Obecně by se reference měly mazat pomocí git update-ref -d, přestože obvykle je bezpečné je odstranit ručně (refs/original).

Commity

Objasnili jsme 2 ze 3 objektů. Třetí je „commit“ objekt. Jeho obsah závisí na zprávě stejně jako na datu a času, kdy byl vytvořen. Aby odpovídal tomu, co bude následovat, budeme ho muset trochu upravit:

$ git commit --amend -m Shakespeare  # změníme zprávu
$ git filter-branch --env-filter 'export
GIT_AUTHOR_DATE=="Fri 13 Feb 2009 15:31:30 -0800"
GIT_AUTHOR_NAME=="Alice"
GIT_AUTHOR_EMAIL=="alice@example.com"
GIT_COMMITTER_DATE=="Fri, 13 Feb 2009 15:31:30 -0800"
GIT_COMMITTER_NAME=="Bob"
GIT_COMMITTER_EMAIL=="bob@example.com"'  # správný čas a autoři
$ find .git/objects -type f

Měli byste vidět .git/objects/6f/ca06c5ba5737e0eb147f9cc9761f99d0c15915, což je SHA1 hash jeho obsahu:

"commit 158" NUL
"tree 210ba5665159efc75739ccb3a6332532669eda96" LF
"author Alice <alice@example.com> 1234567890 -0800" LF
"committer Bob <bob@example.com> 1234567890 -0800" LF
LF
"Shakespeare" LF

Stejně jako předtím můžete spustit zpipe nebo git cat-file, abyste se podívali sami.

Toto je první commit, takže nemá žádné rodiče, ale pozdější commity budou vždy obsahovat alespoň jeden další řádek určující rodičovský commit.

Neropoznatelné od magie

Ještě něco by se slušelo říct. Právě jsme odhalili tajemství síly Gitu. Zní to jednoduše: vypadá to, že byste mohli smíchat dohromady pár shellových skriptů, přidat trochu kódu v C, a tak byste získali systém výše za pár hodin. Popravdě toto naprosto přesně vystihuje nejranější vývoj Gitu. Nicméně, krom geniálních balicích triků, jak ušetřit místo, a indexovacích triků, jak ušetřit čas, nyní víme, jak Git hbitě mění filesystém v databázi perfektní pro verzování.

Kupříkladu, pokud je nějaký soubor v databázi poškozen chybou disku, pak jeho hash nebude již více odpovídat, což nás bude upozorňovat na problém. Hashováním hashů jiných objektů udržujeme integritu na všech úrovních. Commity jsou atomické, takže commit nemůže vyústit v částečné zapsání změn: hash commitu můžeme vypočítat a uložit do databáze jedině tehdy, když jsme už uložili všechny související bloby, stromy a rodičovské commity. Databáze objektů je odolná vůči neočekávaným přerušením, jakým je například výpadek proudu.

Porazíme i ty nepochybnější protivníky. Představte si, že se někdo kradmo pokusí změnit obsah souboru v nějaké prehistorické verzi projektu. Aby databáze objektů vypadala „zdravě“, je potřeba také změnit hashe odpovídajících blob objektů, poněvadž jsou to nyní jiné řetězce bytů. Toto znamená, že se musí změnit hashe jakýchkoli stromových objektů odkazujících na tento soubor. A ve výsledku i hash všech objektů commitů, které obsahují takový strom. Přidejte k tomu ještě všechny potomky těchto commitů, z čehož vyplývá, že hash oficiálního HEADu bude jiný než toho v tomto špatném repozitáři. Sledováním stopy nesouhlasných hashů můžeme určit změněný soubor, stejně tak i commit, který byl jako první poškozen.

Zkráceně, jak je 20 bytů reprezentujících poslední commit někde v bezpečí, je nemožné si zahrávat s Gitím repozitářem.

A co ty slavné Gití funkce? Větvení? Slučování? Tagy? Strohé detaily. Současná hlava (HEAD) je v souboru .git/HEAD, který obsahuje hash commit objektu. Hash se mění po commitu, stejně jako po ostatních příkazech. Větve jsou skoro to samé: jsou to soubory v .git/refs/heads. Tagy také: žijí v .git/refs/tags, ale jsou měněny jinou sadou příkazů.

Tento článek je překladem sedmé kapitoly – Secrets Revealed – z GitMagic od Bena Lynna. Příště, v poslední kapitole, budou popsány některé nedostatky Gitu.

×Odeslání článku na tvůj Kindle

Zadej svůj Kindle e-mail a my ti pošleme článek na tvůj Kindle.
Musíš mít povolený příjem obsahu do svého Kindle z naší e-mailové adresy kindle@programujte.com.

E-mailová adresa (např. novak@kindle.com):

TIP: Pokud chceš dostávat naše články každé ráno do svého Kindle, koukni do sekce Články do Kindle.

Hlasování bylo ukončeno    
0 hlasů
Google
(fotka) Jakub KulhanAutor momentálně studuje na osmiletém gymnáziu v Kralupech nad Vltavou. Programování se věnuje od 11 let, kdy ho poprvé uchvátila možnost "mít vlastní stránky". Nakrátko poté objevil PHP a už se to s ním "vezlo". Webové aplikace zůstaly jeho hlavní doménou, ale ve svém volném čase probádává nejrůznější zákoutí světa programování, programovacích jazyků a všeho kolem nich.
Web    

Nové články

Obrázek ke článku Hybridní inteligentní systémy 2

Hybridní inteligentní systémy 2

V technické praxi využíváme často kombinaci různých disciplín umělé inteligence a klasických výpočtů. Takovým systémům říkáme hybridní systémy. V tomto článku se zmíním o určitém typu hybridního systému, který je užitečný ve velmi složitých výrobních procesech.

Obrázek ke článku Jak vést kvalitně tým v IT oboru: Naprogramujte si ty správné manažerské kvality

Jak vést kvalitně tým v IT oboru: Naprogramujte si ty správné manažerské kvality

Vedení týmu v oboru informačních technologií se nijak zvlášť neliší od jiných oborů. Přesto však IT manažeři čelí výzvě v podobě velmi rychlého rozvoje a tím i rostoucími nároky na své lidi. Udržet pozornost, motivaci a efektivitu týmu vyžaduje opravdu pevné manažerské základy a zároveň otevřenost a flexibilitu pro stále nové výzvy.

Obrázek ke článku Síla týmů se na home office může vytrácet. Odborníci radí, jak z pracovních omezení vytěžit maximum

Síla týmů se na home office může vytrácet. Odborníci radí, jak z pracovních omezení vytěžit maximum

Za poslední rok se podoba práce zaměstnanců změnila k nepoznání. Především plošné zavedení home office, které mělo být zpočátku jen dočasným opatřením, je pro mnohé už více než rok každodenní realitou. Co ale dělat, když se při práci z domova ztrácí motivace, zaměstnanci přestávají komunikovat a dříve fungující tým se rozpadá na skupinu solitérů? Odborníci na personalistiku dali dohromady několik rad, jak udržet tým v chodu, i když pracovní podmínky nejsou ideální.

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý