]> rtime.felk.cvut.cz Git - edu/osp-wiki.git/commitdiff
Zaklad 4. cviceni (git)
authorMichal Sojka <sojkam1@fel.cvut.cz>
Tue, 9 Mar 2010 18:54:28 +0000 (19:54 +0100)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Tue, 9 Mar 2010 18:54:59 +0000 (19:54 +0100)
Jeste to je potreba dodelat.

cviceni.mdwn
cviceni/4.mdwn [new file with mode: 0644]

index 440f9e67602d578502e909ac2c463ab52ee27007..2eedd93fa562968f86247e193cff9bcdef704215 100644 (file)
@@ -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 (file)
index 0000000..a34ed05
--- /dev/null
@@ -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 <příkaz>
+    git <příkaz> --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 <file>..." to update what will be committed)
+        #   (use "git checkout -- <file>..." 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 `<remote>/`.
+
+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 <file>..." 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://<mujlogin>@repo.or.cz/srv/git/midnight-commander/osp/<mujfork>.git homework
+   nebo        
+
+        git remote add repo-or-cz ssh://<mujlogin>@repo.or.cz/srv/git/midnight-commander/osp/<mujfork>.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`.