Hlavní navigace

GIT: naše první vydání

Karel Žák

Tak a je to konečně tady. Přišel ten Velký Den, kdy je načase udělat první oficiální release (vydání). Co to znamená pro váš repositář v GITu? Jednoduše řečeno „zapíchneme“ do repositáře dostatečně velkou značku, se kterou už nikdy nikdo nepohne. Ta bude navždy označovat místo, kde je verze 0.0.1.

Onu značku uděláme tak, že vytvoříme nový tag a podepíšeme ho pomocí GPG:

$ git tag -s -m "this is the best release" v0.0.1

tag v0.0.1 si můžeme snadno ověřit:

$ git tag -v v0.0.1
object 4ba6758ad5043242933a0c005b416d70fb5e9a1e
type commit
tag v0.0.1
tagger Karel Zak <kzak@....> 1205885297 +0100

this is the best release
gpg: Signature made Wed 19 Mar 2008 01:08:17 AM CET using DSA key ID DC06D885
gpg: Good signature from "Karel Zak <kzak@....>"

SHA-1 každého commitu je počítána z jeho obsahu, a tím je i odkaz na tree (snapshot repositáře v daném čase) a rodiče (předchozí stav). A jak již víme, vše až na úroveň dat je adresováno pomocí SHA-1 počítaného z obsahu. Tedy platí, že každá zpětná změna v repositáři změní i SHA-1 všech následujících commitů. Proto k ověření stavu celého libovolně velkého repositáře stačí porovnat jedno jediné SHA-1. Podobně stačí podepsat jedno jediné SHA-1.

Ale co když jsem udělal nějaký bug a chci tag smazat a udělat znova? Pokud nikdo nemá kopii vašeho repositáře a vše je jen vaše soukromá věc, není problém. Pokud ale již byla věc zveřejněna, tak máte velký problém. GIT nikdy sám nemaže tagy. Pokud si někdo vaše změny aplikuje na svůj repositář (např. git pull), GIT nezmění již existující tag.

Důvod je prostý – bezpečnost. GIT neimplementuje orwellovské „Ministry of Truth“, takže historii za něčími zády nikdy nemění. Každá podobná změna je viditelná.

Nevědět o existenci větví v GITu je nepřípustné ignoranství. Větvení (branchování) není v GITu bonus navíc, naopak, je to základní vlastnost.

K vytvoření větve vedou dvě cesty:

$ git checkout -b <branchname>

a nebo:

$ git branch <branchname>

oba příkazy můžete doplnit o tzv. startpoint – tedy místo, od kterého větev začíná. Většinou to však není nutné a GIT sám použije HEAD (poslední commit aktuálního větve).

Základní rozdíl mezi výše uvedenými příkazy je, že git-checkout přepne i pracovní adresář do vybrané větve, zatímco git-branch ne (a tedy stále pracujete s původní větví). To je důvodem, proč většina uživatelů dává přednost příkazu git-checkout.

Pokud ztrácíte jistou, která větev je aktuální, tak:

$ git branch

vypíše standardní větve a v seznamu označí právě používanou.

Pokud pracujete na repositáři, který je klonem jiného (cizího) repositáře a pravidelně si stahujete změny (např. git-pull) z originálního zdroje, je vhodné nepracovat v „master“. Branch master je standardní „tracking“ větev a aplikují se zde změny z originálního repositáře (pochopitelně záleží na vašem nastavení a používaných příkazech). Souběh vašich změn a změn z originálního repositáři může vést ke konfliktům.

Je tedy lepší pro svou práci používat nějakou lokální větev. Často se těmto větvím říká „topic“ větve.

Dobrá, máme projekt na kterém pracuje více lidí. My máme kopii (klon) repositáře s jeho „master“ větví. Implementujeme nějakou novou vlastnost, a aby nás nic nerušilo, používáme svůj vlastní větev. Tedy:

$ git clone git://project
$ cd project
$ git checkout -b topic
$ git branch
* topic
master

$ $EDITOR file.c
$ git commit -a -s -m "cool new feature"
.
.
.

mezi tím okolní svět nespí, ale aktivně provádí změny v původním repositáři. Nás pochopitelně tyto změny zajímají. Tedy pravidelně voláme:

$ git pull

což vede k tomu, že se mění obsah větve „master“ a naše lokální topic větev zastarává. To není nutně problém, ale jednou přijde doba, kdy chcete své změny poslat ostatním (případně jste maintainer a chcete změny aplikovat do „master“ větve), a pak je vhodné vaši větev „refreshnout“ tak, aby vaše změny bylo možné aplikovat na aktuální stav v hlavním repositáři. Řešením je rebase:

$ git rebase <upstream>

kde <upstream> je branch, který chcete použít jako zdroj, v našem případě „master“:

$ git rebase master

v tomto případě vezme GIT jednoduše patche z „master“ které nejsou v našem „topic“ a aplikuje je před naše změny. A následně se pokusí na takto refreshnutou větev aplikovat naše patche s „topic“.

Pomůžeme si obrázkem z man stránky git-rebase, stav před:

                     A---B---C topic
                    /
               D---E---F---G master

stav po rebase:

                             A´--B´--C´ topic
                            /
               D---E---F---G master

Pochopitelně může dojít ke konfliktům, pokud se modifikuje v „master“ to samé jako v „topic“. Proto je vhodné provádět při dlouhodobější práci v „topic“ rebase častěji a řešit tak jen menší konflikty.

Takto občerstvené patche je možné následně odeslat ostatním a nebo je aplikovat do jiné větve apod. Pokud chcete překopírovat větší množství patchů do jiné větve, lze použít příkaz:

$ git checkout -f master
$ git pull . topic

aplikuje patche z „topic“ do větve „master“. Pokud jste před tím neprovedli rebase, může opět dojít ke konfliktu který musíte vyřešit (tedy editor, commit, ..apod).

Pokud chcete aplikovat jen jeden patch, a to doslova bez ohledu na to, jak hluboko a kde je zakopán, použijte příkaz:

$ git cherry-pick <SHA-1>

kde SHA-1 je checksum commitu, který bude aplikován do aktuálního repositáře.

Větve lze pochopitelně používat na mnoho dalších činností, ale již ponechám případným zájemcům na jejich studiu. Podobě jako další možnosti, které GIT vývojářům dává…

Další informace

Presentace Git
(zdrojové kódy v LaTeX)

Našli jste v článku chybu?