Technické
Netechnické
- Jídlo a pití
| Příkaz | Význam |
|---|---|
| git init | inicilizuje v $PWD nový repositář (nebo aktualizuje stávající) |
| git add . | přidá rekurzivně všechny soubory a adresáře pod svojí správu, pokud tam již nejsou |
| git status | vypíše aktuální stav |
| git commit -a | zapíše stav projektu z index do větve (uložení provedených změn) |
| git commit -a -m "commit msg" | stejně jako předchozí ale rovnou s předáním commit msg |
| git add -u . | Do indexu zapíše změny pouze už známých souborů (změněné a odstraněné, ale ne nové) |
| git branch | vypíše seznam dostupných větví |
| git branch -d xaxa | smaže větev xaxa |
| git branch xaxa | vytvoří kopii aktuální větve se jménem xaxa |
| git checkout xaxa | přepne na větev xaxa |
| git checkout master | přepne na hlavní větev (nebo se vrátí na HEAD pokud cestujeme v čase) |
| git merge xaxa | spojí obsah větve s xaxa s aktuální větví |
| git tag 1.0rc1 | označí aktuální verzi aktuální větve štítkem |
| git log | zobrazí historii větve |
| git diff --color | zobrazí diff necommitnutých změn |
| git diff --color --cached | zobrazí diff necommitnutých přidaných změn |
| git diff --color HEAD^ HEAD | zobrazí diff posledního commitu |
| git diff "@{yesterday}" | co se změnilo v projektu od včerejška |
| git diff SHA1_HASH "master~4" | rozdíl mezi konkrétním commitem a -4 commit v historii |
| git diff --stat | Počty změněných řádků a další informace |
| git diff > patch SHA1_HASH | vytvoří patch |
| git patch < patch | aplikuje patch |
| git apply | aplikuje patch, lze použít výstup git diff |
| git whatchanged --since="2 weeks ago" | přehled změn za poslední dva týdny |
| git commit --amend | Změna popisu posledního commitu (nepoužívejte když nevíte co děláte) |
| git add file && git commit --amend -a | připojení zapomenutého souboru k poslednímu commitu |
| git reset --hard | Zahodí (trvale a nevratně) vše co nebylo commitnuto (tj aktuální, zřejmě nepovedené, úpravy) |
| git reset --hard SHA1_HASH | stejně jako předchozí, ale zahodí všechno až do commitu vyznačeného pomocí SHA1_HASH (git log) |
| git checkout SHA1_HASH | vrátí se v historii ke commitu s daným SHA1 (budoucnost zůstává zachována, ale při commitu se vytvoří nová větev vývoje) |
| git checkout SHA1_HASH file.x file.y | přenesení konkrétních souborů z historie do přítomnosti (pozor na přepsání) |
| git checkout :/"commit msg" | cestování v čase s "commit msg" adresací (použitelné i v dalších příkazech, ale více nebezpečné) |
| git checkout master~5 | skok v čase o pět commitů vzad |
| git revert SHA1_HASH | provede navrácení ke starému commitu, ale tento návrat je zaznamenán jako pokračování vývoje (lepší než reset) |
| git clone URL | naklonuje vzdálený repositář |
| git pull | aktualizace repositáře staženého pomocí git clone |
| git cherry-pick SHA1_HASH | sloučí vybraný commit z libovolné větve do aktuální |
| git stash | schová lokální necommitnuté změny do skrýše a vrátí stav k poslednímu commitu (vždy když chceme neztratit změny, které nechceme commitnout, použijeme stash) |
| git stash apply | vyndá ze skrýše změny a aplikuje je na HEAD |
| git blame SOUBOR | zobrazí kterou řádku kdo naposledy editoval |
| git add -p && git commit | rozseká aktuální změny na menší commity |
| gitk | zobrazí grafickou reprezentaci repositáře |
| git gc | minimalizace repa |
| git reset HEAD <file> | odebere soubor z indexu (jeho lokalni zmeny zustanou) |
| git show <hash>:<soubor> | zobrazi obsah souboru vzhledem ke konkretni revizi (misto <soubor> musi byt cela cesta k souboru od korene repositare) |
Konfigurace platná pro lokální repositář
$ git config user.name "Jméno Příjmení" $ git config user.email "e-mailova@adresa"
Globálně platná konfigurace
$ git config --global user.name "Jméno Příjmení" $ git config --global user.email "e-mailova@adresa"
Globální konfigurace se ukládá v souboru $HOME/.gitconfig a obsah souboru může vypadat například takto:
[user] name = Martin Kopta email = CENSORED [push] default = matching [merge] tool = vimdiff
Pokud chceme provádět push na stejné místo častěji (mirrorování lokálního repositáře na server třeba), můžeme nastavit remote pro pull.
Příklad (pro sourceforge.net)
git remote add origin ssh://USERNAME@PROJECTNAME.git.sourceforge.net/gitroot/PROJECTNAME/REPONAME git config branch.master.remote origin git config branch.master.merge refs/heads/master
Pak následuje (poprvé a naposled po tomto nastavení) příkaz
git push origin master
čímž odešleme master větev na server. Pro další synchronizaci stačí už jen příkazy
git push git pull
Pro vytvoření nové větve na vzdáleném repositáři
git push origin heads/dbg
Pro smazání vzdálené větve (nazvané dbg)
git push origin :heads/dbg
Velmi častá situace pro běžné uživatele nevývojáře. Chceme sledovat nějaký projekt a mít vždy nejposlednější verzi jaká existuje (nejnovější commit v public repu). Nejprve si inicializujeme adresář, ve kterém budeme ukládat projekt pomocí git clone URL a poté sledujeme změny pomocí git pull.
Při git clone URL získáme repositář, obsahující větev master. Vzdálený repositář ale může mít více větví. Ty při listování pomocí git branch neuvidíme, protože příkaz listuje jenom lokální větve (v našem repositáři). Pro zobrazení větví v lokálním repositáři A větví vzdáleného repositáře použijeme git branch -a. Pokud chceme sledovat nějakou další větev než master, použijeme git branch <nova_lokalni_vetev> <remote_vetev>. Například
-bash-4.1$ cd one.git/ -bash-4.1$ git branch -a * master remotes/origin/HEAD -> origin/master remotes/origin/feature-192 remotes/origin/master remotes/origin/one-1.2 remotes/origin/one-1.4 remotes/origin/one-2.0 -bash-4.1$ git branch one-2.0 remotes/origin/one-2.0 Branch one-2.0 set up to track remote branch one-2.0 from origin. -bash-4.1$ git checkout one-2.0 Switched to branch 'one-2.0'
http://stackoverflow.com/questions/67699/how-do-i-clone-all-remote-branches-with-git
Pokud nás nebaví psát git status, můžeme používat ručně vytvořený alias:
git config --global alias.st status
(takto lze samozřejmě aliasovat každý příkaz)
git config color.diff auto git config color.status auto
git config --global core.pager cat git config --global core.pager less
Pokud potřebujeme využít paralelní práce na projektu a nemůžeme využít branch (například master se kompiluje, testuje nebo tak něco), můžeme udělat dočasný klon.
git clone . ~/dev/tmp/projectx-clone
Pak můžeme vesele hackovat úplně jinde na disku (git vytvoří co nejvíce hardlinků půjde takže klonování je hodně rychlé). Pokud chceme změny klonu zanést zpátky do hlavního repa, použijeme pull.
git pull ~/dev/tmp/projectx-clone HEAD
Pokud pracujeme s verzovacím systémem, který nám až tak nevyhovuje, ale pracovat s ním musíme, můžeme provádět "Guerilla verzování". V aktuálním checkoutu založíme git repo - git init && git add . a (raději) vyklonujeme ven git clone . ../project-git. Pak můžeme vesele hackovat pomocí gitu a po dokončení se vrátit do původního repa, dát git pull ../project-git HEAD a commitnout pomocí vnějšího SCM.
Pokud potřebujeme provést nějakou úpravu staršího commitu (třeba bugfix pro
poslední commit než jsme začali pracovat na dosud nehotové feature), můžeme
vytvořit větev od starého commitu. Pomocí git checkout -b bugfix_666
SHA1_HASH se přepneme na starý commit a od něj inicializujeme novou větev
pojmenovanou bugfix_666. Provedeme změny, dáme git commit a třeba git
push. Pak se můžeme vrátit do naší současné verze a pokračovat na tom, co jsme
dělali předtím → git checkout master. Pro sloučení aktuální verze s
bugfixem pak použijeme git merge bugfix_666.
Pro předělání posledních deseti commitů git rebase -i HEAD~10 → získáme text v $EDITORu.
Pro editaci commitu označeného "edit" git commit –amend
Dokončení: git rebase –continue
→ Časté provádění commitů je dobré, protože pak můžeme použít rebase
Když na začátku projektu omylem commitneme config s heslem třeba..
git filter-branch --tree-filter 'rm config' HEAD
Pokud chceme najít commit, ve kterém byla zanesena featura/bug, můžeme použít bisect. Pomocí git bisect start označíme počátek vyhledávání. git bisect bad SHA1_HASH označíme commit, kde je featura/bug přítomen, git bisec good SHA1_HASH označíme commit kdy featura/bug není. Git nastaví stav projektu na commit uprostřed mězi těmito commity. My otestujeme zda je feature/bug přítomno, řekneme git bisect bad, pokud není tak řekneme git bisect good. Takto se dostaneme binárním půlením ke commitu, který jsme hledali. Hledání ukončíme git bisect reset. Pokud lze přítomnost feature/bug testovat automaticky, lze nastavit git bisect run CMD a vše proběhne automaticky.
Návratové kódy CMD
Pokud potřebujeme provést pull přes médium, které není Gitem podporováno (USB disk, diskety, CD, DVD, ..), můžeme vytvořit balíček (bundle) a přenášet pouze ten.
git bundle create nejaky_soubor HEAD
Bundle pak můžeme pullnout jako by to byl obyčejný file-repositář
git pull nejaky_soubor
Pokud přenášíme nějaké větší repo (třeba KDE nebo tak něco), může se nám hodit přenášení jenom malé části.
git bundle create nejaky_soubor HEAD ^SHA1_KTERE_MAJI_OBA
Případně pomocí tagů
git tag -f posledni_balicek HEAD git bundle create novy_balicek HEAD ^posledni_balicek
.git/info/exclude
Visualizace git repa lze provést pomocí webového rozhraní, které se aktivuje jednoduše příkazem
git instaweb
Výchozí se používá lighttpd, ale lze použít libovolný jiný webserver. Také lze použít git instaweb –httpd webrick což nahodí jakýsi ruby webserver (?).
Pro nahození Git serveru přes OpenSSH stačí pár jednoduchých kroků:
adduser git, kterému dáme jako shell /usr/bin/git-shell a heslo, které ani nebudeme nikdy potřebovat (takže může být libovolně šílené a neuhodnutelné – pwgen a třeba 100 znaků)git domovský adresář /home/git, nastavíme správně práva, vyčistíme jeho $HOME od případného distribučního bordelu a přidáme do .ssh/authorized_keys vývojáře daného projektu (opět nezapomenout na práva).su git -s /bin/bashmkdir /home/git/projekt.git && cd /home/git/projekt.git && git –bare initmkdir projektcd projektgit inittouch READMEgit add READMEgit commit -m 'first commit'git remote add origin git@REMOTE_SERVER:projekt.gitgit push origin masterNevýhody:
.ssh/authorized_keys mají přístup ke všem projektům v /home/git.git má nastavené heslo a může být potenciálním bezpečnostním rizikem (lze řešit pomocí zákazu přihlašování pomocí hesel a více OpenSSH serverů na serveru nebo prostým smazáním hesla)Výhody
Inicializace git-svn repa:
git svn init -s http://example.com/svn/my_proj git svn fetch git repack -d
Klasický vývojový cyklus:
git checkout -b new_feature git commit -a -m "commit message" git checkout master git merge new_feature git svn rebase git svn dcommit
Pro stažení změn z SVN repa:
git svn rebase
Pro commit do vzdáleného repa:
git svn dcommit
V případě potřeby tvorby release (z jakéhokoliv důvodu) lze použít obdobu příkazu 'bzr export'
git archive --format=tar --prefix=project/ HEAD > ../project.tar
Nebo s komprimací
git archive --format=tar --prefix=project/ HEAD | gzip > ../project.tar
nebo jako zip
git archive --format=zip --prefix=project/ HEAD > ../project.zip
nebo export jenom části projektu
git archive --format=tar --prefix=project-docs/ HEAD:docs/ > ../project-docs.tar
Exportování lze využít pro tvorbu snapshotů
#!/usr/bin/env bash if [ -z "$1" ] || [ -z "$2" ] then echo "Usage: $(basename $0) <projectname> <exportdir>" exit 1 fi project="$1" exportdir="$2" ################ date=$(date +%y%m%d%H%M%S) name="${project}-${date}" git archive --format=tar --prefix="${name}/" HEAD | \ gzip > "${exportdir}/${name}.tar.gz"
Příklad použití branch/commit/merge
$ mkdir gittest $ cd gittest/ $ cat > main.c int main ( void ) { return ( 0 ) ; } $ git init Initialized empty Git repository in /tmp/gittest/.git/ $ git add . $ git status # On branch master # # Initial commit # # Changes to be committed: # (use "git rm --cached <file>..." to unstage) # # new file: main.c # $ git commit -m "první commit na master větvi" [master (root-commit) 1c00ab6] první commit na m... 1 files changed, 4 insertions(+), 0 deletions(-) create mode 100644 main.c $ git branch hlaska $ git branch hlaska * master $ git checkout hlaska Switched to branch "hlaska" $ git branch * hlaska master $ vim main.c $ git commit -m "pridani vypisu hlasky" main.c [hlaska 20fc3a3] pridani vypisu hlasky 1 files changed, 2 insertions(+), 0 deletions(-) $ git checkout master Switched to branch "master" $ git merge hlaska Updating 1c00ab6..20fc3a3 Fast forward main.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)