From ca4386c58c06e8b216aa67e64fc7c661d4b21c95 Mon Sep 17 00:00:00 2001 From: Michal Sojka Date: Tue, 9 Mar 2010 19:54:28 +0100 Subject: [PATCH] Zaklad 4. cviceni (git) Jeste to je potreba dodelat. --- cviceni.mdwn | 2 +- cviceni/4.mdwn | 338 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 339 insertions(+), 1 deletion(-) create mode 100644 cviceni/4.mdwn diff --git a/cviceni.mdwn b/cviceni.mdwn index 440f9e67..2eedd93f 100644 --- a/cviceni.mdwn +++ b/cviceni.mdwn @@ -15,7 +15,7 @@ Osnova 2. [[Tvorba "produktu" z nezávislých OSS komponent|cviceni/2]] (embedded Linux) 3. [[Specifikace individuálního zadání|cviceni/3]] samostatná práce a jeho zařazení do existujících OS projektů (konzultace se cvičícími) -4. Verzovací systém Git +4. [[Verzovací systém Git|cviceni/4]] 5. Prezentace projektu do kterého budu přispívat v samostatné práci a nástin řešení 6. Test diff --git a/cviceni/4.mdwn b/cviceni/4.mdwn new file mode 100644 index 00000000..a34ed051 --- /dev/null +++ b/cviceni/4.mdwn @@ -0,0 +1,338 @@ +[[!meta title="Verzovací systém Git"]] + +[[!toc levels=2]] + +Cíl +=== + +Naučit se pracovat verzovacím systémem [Git](http://git-scm.com/), + +* distribuovaným vývojový model +* práce s několika větvemi +... + +Úvod +==== + +V tomto cvičení budeme opět pracovat s projektem +[Midnight commander][mc] z [[1. cvičení|1]]. Pokud s gitem začínáte, +doporučuji v průběhu jednotlivých kroků kontrolovat stav repozitáře +pomocí grafických nástrojů. + +* Příkaz `gitk` zobrazuje graficky historii a dovoluje její + interaktivní procházení. Přijímá stejné volby jako `git log`, takže + v příkazech níže ho můžete použít i pro vizualizaci výstupu `git + log`. + +* Příkaz `git gui` je grafický nástroj částečně nahrazující příkazy + `git status` a `git commit`. Pomocí menu je možné provádět i další + operace jako např. vytváření větví a práce se vzdálenými repozitáři. + +* Dále existuje ještě spousta dalších [nástrojů][tools]. Já osobně používám + kromě výše zmíněných příkazů ještě `tig` a `qgit`. + +Dále se vám určitě bude hodit dokumentace: + git help + git --help + +[tools]:http://git-scm.com/tools + +Postup +====== + +1. Základní nastavení. Aby vaše commity obsahovaly správné údaje o + vás, nastavte si jméno a email: + + git config --global user.name "Your Name Comes Here" + git config --global user.email you@yourdomain.example.com + + + +1. Předpokládáme, že máte zdrojové kódy midnight commanderu někde na + disku, takže se přesuňte do adresáře s nimi. + + cd ~/mc + +Lokální větve +------------- + +2. Možná budete chtít zachovat vaší práci z prvního cvičení. Uložíme + jí do nové větve *cviceni1*. Nejprve se ale podíváme v jakém stavu + máme zdrojové kódy: + + git status + Dostaneme něco jako: + + # On branch master + # Changed but not updated: + # (use "git add ..." to update what will be committed) + # (use "git checkout -- ..." to discard changes in working directory) + # + # modified: po/az.po + # modified: po/be-tarask.po + # modified: po/be.po + # ... + # modified: src/cmddef.h + # modified: src/main.c + Vidíme, že pracujeme na větvi *master* a vzhledem k verzi uložené v + repozitáři máme několik změněných souborů. + +[mc]:http://www.midnight-commander.org/ + +1. Midnight commander má bohužel jednu vlastnost, která může ztížit + vaše začátky s gitem. Při kompilaci dojde k automatickému + přegenerování některých souborů v repozitáři a git potom hlásí, že + jsme tyto soubory změnili a "otravuje" s nimi při každém commitu. + + Naštěstí existuje možnost jak gitu říct, že nás změny v některých + souborech nezajímají: + + git update-index --assume-unchanged $(git ls-files po m4) + + Příkaz `git ls-files po m4` vypíše všechny soubory z adresářů *po* + a *m4*, které jsou spravované gitem a příkazem `git update-index + --assume-unchanged` pak gitu sdělíme, aby si do indexu poznamenal, + že tyto soubory má ignorovat. + + > *Poznámka:* Možná víte o souborech *.gitignore* (viz `man + > gitignore`), které slouží k podobnému účelu. Ostatně midnight + > commander je také využívá, jak se můžete snadno přesvědčit: + > + > cat .gitignore + > + > Soubory *.gitignore* se ale vztahují pouze na soubory, které + > ještě nejsou součástí repozitáře, což není případ výše zmíněných + > souborů. + +3. Vytvoříme větev *cviceni1* a přepneme se na ni: + + git checkout -b cviceni1 + + Nyní už by měl `git status` ukazovat že pracujeme s větví + *cviceni1* a vidíme pouze námi modifikované soubory. + +4. Nyní provedeme *commit*: + + git commit -a -m 'Zmeny z prvniho cviceni' + + Parametrem `-a` říkáme, že "commitujeme" vše (all) a `-m` udává + komentář ke commitu (message). Kdybychom `-m` vynechali, git spustí + editor a nechá nás napsat zprávu v něm. + + > *Poznámka:* Pokud vám nevyhovuje výchozí editor (většinou `vi`), + > nastavte si, že chcete používat jiný editor (např. `pico`): + > + > git config --global core.editor pico + +5. Nyní se přepneme zpět na větev *master*: + + git checkout master + V adresáři se vám teď objeví verze bez vašich úprav z 1. cvičení. + +6. Seznam větví v našem repozitáři zjistíme příkazem + + git branch + Aktuální větev je označena hvězdičkou `*`. + +Práce s více vzdálenými repozitáři +---------------------------------- + +Do teď jsme pracovali pouze s jedním vzdáleným repozitářem. Mezi velké +výhody gitu (a ostatních distribuovaných verzovacích systémů) patří +schopnost pracovat s více vzdálenými repozitáři. + +1. Které vzdálené repozitáře máme nakonfigurované zjistíme pomocí + + git remote -v + + Vidíme, že máme nakonfigurovaný repozitář s názvem *origin* a jeho + URL. + +1. Pokud chceme nějaký konkrétní vzdálený repozitář používat často, + vyplatí se ho pojmenovat krátkým jménem (v příkladu níže *osp*), + abychom nemuseli pořád psát dlouhé URL: + + git remote add osp git://repo.or.cz/midnight-commander/osp.git + +2. Nyní můžeme stáhnout obsah právě přidaného repozitáře: + + git fetch osp +3. Příkaz nám vypíše, že v repozitáři byly dvě nové větve. Všechny + větve ze vzdálených repozitářů vypíšeme příkazem + + git branch -r + Zjednodušeně řečeno, jediný rozdíl mezi lokální a vzdálenou větví + je v tom, že vzdálená větev má prefix `/`. + +4. Nyní nás zajímá co je ve větvích, které jsme právě stáhli: + + git log osp/only-directories ^master + git log master..osp/only-directories + Tyto dva příkazy jsou ekvivalentní a vypisují commity, které jsou + ve větvi *osp/only-directories* a zároveň nejsou ve větvi *master*. + + Chcete-li vidět i změny v kódu použijte jeden z následujících příkazů + git log -p osp/only-directories ^master + gitk osp/only-directories ^master + +6. Podobně můžeme postupovat i s původním repozitářem. Jméno *origin* + je výchozí a proto ho nemusíme zadávat: + + git fetch + Co přibylo ve větvi *master* od prvního cvičení zjistíme příkazem: + + git log master..origin/master + +Slučování větví (merge) +----------------------- + +Operace slučující dvě a více větví do jedné se nazývá *merge*. V Gitu +můžou při slučování nastat tři situace: + +* *Already up-to-date* je situace, kdy už je větev, kterou chceme + sloučit, dosažitelná z aktuální větve (už byla sloučena v + minulosti). Při sloučení nedojde k žádné změně. +* *Fast-forward* je opak předchozí situace, tj. aktuální větev je + dosažitelná ze slučované větve. To odpovídá situaci, kdy + aktualizujeme na novější verzi. Při sloučení je větev (tj. ukazatel + na poslední commit) posunuta na novější verzi. +* *True merge*. Pokud nenastane jedna z předchozích situací, jedná se + o skutečné sloučení. Výsledek je nějaká kombinace obou verzí. + +Pokud došlo v případě *True merge* ke změně stejného místa v kódu v +obou větvích, dojde k tzv. *konfliktu*, který musí být vyřešen ručně. + +1. Zkuste provést sloučení vaší větve *master* s *origin/master* + + git merge origin/master + Výsledkem bude *Fast forward* a uvidíme jaké soubory byly změněny: + + git merge origin/master + Updating 0ebd30c..a99dc51 + Fast forward + configure.ac | 1 + + contrib/Makefile.am | 9 +- + ... + Toto je velmi častá operace a proto lze oprace `fetch` a `merge` + nahradit jedním příkazem + git pull +2. Vždy, když člověk pracuje na nějaké netriviální změně, je užitečné, + založit si na to samostatnou větev. Dnešním úkolem bude sloučit + větev *osp/only-directories* s větví *master* a protože to není + triviální založte si na to novou větev: + + git checkout -b homework +3. Pokud provedete sloučení + + git merge osp/only-directories + Výsledek bude vypadat pravděpodobně takto: + Renaming doc/mc.1.in => doc/man/mc.1.in + Auto-merging doc/man/mc.1.in + Auto-merging src/find.c + CONFLICT (content): Merge conflict in src/find.c + Automatic merge failed; fix conflicts and then commit the result. + Vidíme, že git správně zjistil, že soubor `doc/mc.1.in` byl + v novější verzi přejmenován a provedl sloučení až po přejmenování. + Při slučování změn ve `src/find.c` už takové štěstí nemáme a + výsledkem je konflikt. + + +Řešení konfliktů +---------------- + +Konflikt lze řešit několika způsoby (viz také `git merge --help`): + +* Vzdáme to a vrátíme se k verzi před slučováním + + git reset --hard + +* Konflikt vyřešíme a oznámíme to gitu příkazy `git add` a `git + commit` (jak nám git napovídá v hláškách) + +V průběhu řešení konfliktu je užitečné používat příkaz `git status`, +abychom zjistili co je ještě potřeba vyřešit. V našem případě vypadá +výstup zhruba takhle: + + # On branch merge-assignment + # Changes to be committed: + # + # modified: doc/man/mc.1.in + # + # Unmerged paths: + # (use "git add/rm ..." as appropriate to mark resolution) + # + # both modified: src/find.c + # + +TODO... + +* git mergetool +* editor a <<<<<<<< ========= >>>>>>>> +* gitk --merge + + +Repozitář na repo.or.cz +--------------------------- + +K tomu, aby výsledky vaší práce na open source projektech byly snadno +dostupné pro ostatní je užitečné založit si vlastní repozitář, odkud +si budou moct ostatní vaše změny stáhnout. + +1. [Zaregistrujte][reg] se na [repo.or.cz][roc]. K repozitáři na + repo.or.cz se přistupuje protokolem SSH a autorizace se provádí na + základě veřejných klíčů. + + 1. Pokud žádný klíč nemáte, vytvořte si ho příkazem + + ssh-keygen + + Příkaz se vás zeptá kam klíč uložit. Výchozí volba vám zpočátku + bude stačit. Dále se zeptá na heslo (passphrase) k vašemu + privátnímu klíči. Pokud žádné heslo nezadáte, bude se moct + kdokoli, kdo se dostane k souboru s vaším klíčem (např. + administrátor školních serverů), autorizovat jako vy. + + 2. Pokud jste se rozhodli chránit klíč heslem, je otravné zadávat + heslo vždy, když klíč používáte. Naštěstí existuje program + `ssh-agent`, který uchovává odheslované klíče v paměti a + poskytuje je vždy, když je nějaký oprávněný program potřebuje. + Vy tak zadáte heslo jen jednou a to když předáváte klíč + ssh-agentovi příkazem + + ssh-add + +[reg]:http://repo.or.cz/reguser.cgi +[roc]:http://repo.or.cz/ + +2. Vytvoření repozitáře na repo.or.cz. + + Můžete založit buď [nový projekt][new] a nebo udělat tzv. + [fork existujícího projektu][forkmc]. Pro oba typy projektů můžete + zvolit zda bude repozitář pouze automaticky aktualizovanou kopí + jiného repozitáře (*mirror*) a nebo zda-li bude možné do něj přímo + ukládat nové commity (*push*). + + Pro účely tohoto cvičení si + [založte fork Midnight commanderu][forkmc] v *Push módu*, který se + bude jmenovat podle vašeho loginu. Do tohoto repozitáře pak + nahrajete úkol z dnešního cvičení. + +3. Do vašeho vzdáleného repozitáře můžete nahrát vaší větev některým z + těchto způsobů + + git push ssh://@repo.or.cz/srv/git/midnight-commander/osp/.git homework + nebo + + git remote add repo-or-cz ssh://@repo.or.cz/srv/git/midnight-commander/osp/.git + git push repo-or-cz homework + +[new]:http://repo.or.cz/regproj.cgi +[forkmc]:http://repo.or.cz/regproj.cgi?fork=midnight-commander/osp.git + +Zadání +====== + +Proveďte sloučení větve `git://repo.or.cz/midnight-commander/osp.git +only-directories` s aktuální vývojovou větví (`master`). Výsledek +uložte do [vámi vytvořeného repozitáře (forku) na repo.or.cz][forkmc] +do větve `homework`. -- 2.39.2