Uživatelské nástroje

Nástroje pro tento web


software:git

Git

Různé příkazy

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)

Nastavení uživatele

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

Nastavení výchozího vzdáleného repozitáře

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

Sledování vzdáleného repa

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.

Sledování vzdálené větve

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

Nastavení alias pro příkazy gitu

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)

Nastavení barvy

git config color.diff auto
git config color.status auto

Nastavení pageru

git config --global core.pager cat
git config --global core.pager less

Lokální klonování

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

Vnořování SCM systémů

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.

Přidání změn do historie

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.

Rebase

Pro předělání posledních deseti commitů git rebase -i HEAD~10 → získáme text v $EDITORu.

  • Odtranění commitu - smazání řádky
  • Prohození commitů - prohození řádek
  • Změna pick na edit - editace commitu
  • Změna pick na squash - sloučení commitu s předchozím

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

Vymazání souboru z kompletního stromu

Když na začátku projektu omylem commitneme config s heslem třeba..

git filter-branch --tree-filter 'rm config' HEAD

Vyhledání zaneseného bugu

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

  • Záporné - konec vyhledávání
  • 125 - skip
  • 0 - good
  • 1 až 127 - bad

Bundle

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

Lokální ignorování souborů

.git/info/exclude

Instaweb

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 (?).

Git server přes OpenSSH

Pro nahození Git serveru přes OpenSSH stačí pár jednoduchých kroků:

  1. Na serveru přidáme uživatele git: 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ů)
  2. Jestliže jsme dali uživateli 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).
  3. Přihlásíme se z roota na uživatele git pomocí su git -s /bin/bash
  4. Vytvoříme mkdir /home/git/projekt.git && cd /home/git/projekt.git && git –bare init
  5. Nahodíme OpenSSH server a pak jako jeden z vývojářů použijeme klasickou sekvenci
    1. mkdir projekt
    2. cd projekt
    3. git init
    4. touch README
    5. git add README
    6. git commit -m 'first commit'
    7. git remote add origin git@REMOTE_SERVER:projekt.git
    8. git push origin master

Nevýhody:

  • Všichni vývojáři v .ssh/authorized_keys mají přístup ke všem projektům v /home/git.
  • Pro vytváření nových projektů je potřeba používat roota
  • Není možný anonymní checkout (ale není problém nahodit git instaweb)
  • Uživatel 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)
  • Je nutný běh OpenSSH serveru - další bezpečnostní riziko (je ale možné mít spuštěný OpenSSH jen pro Git a používat jiný OpenSSH server pro běžné používání)

Výhody

  • Velmi jednoduché na nastavení
  • Snadné zálohování na straně serveru

git-svn

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

http://andy.delcambre.com/2008/03/04/git-svn-workflow.html

Distribuce

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í

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(-)

Odkazy

/htdocs/trashwiki.cz/data/pages/software/git.txt · Poslední úprava: 2013/03/01 08:41 (upraveno mimo DokuWiki)