====== GIT ====== {{::git-transport.png}} * workspace * adresář se soubory projektu * index (staging area) * binární soubor (''.git/index'') obsahující seznam všech souborů včetně jejich sha1sum a časových razítek * local repository * skrytý adresář ''.git'' celého repozitáře obsahující mimo jiné podadresář objects * objects obsahuje všechny verze, všech souborů, všech větví v podobě komprimovaných souborů * remote repository * vzdálený repozitář (bez workspace) * může být zpřístupněn přes SSH, HTTPS nebo dokonce jen jako jiný lokální adresář ===== Založení repo ===== * založení repositáře * pro založení repositáře na git serveru (pouze meta soubory) se používá přepínač ''--bare'' git init [slozka] * připojení ke vzdálenému * vzdálených může být více, ''origin'' je default název vzdáleného repo git remote add origin https://example.com/user/test.git * stažení vzdáleného git clone https://example.com/user/test.git [lokalni_slozka] * nastavení idenfiikace git config [--global] user.name "First Last name" git config [--global] user.email "first.last@example.com" ===== Nastavení ===== * ukládání credential (cache = dočasně, store = trvale) git config [--global] credential.helper "cache" ===== Commit ===== * staging area * obsahuje dávku ke commitu * modifikované/nové soubory se nejprve musí vložit do staging area, pak commit * zobrazení stavu souborů git status [cesta] * přidání do staging git add [cesta] * vlastní commit git commit [-m "MSG"] * nahrání na vzdálený repositář * pokud jich je více (nebo pokud se nahrává poprvé) zadává se navíc jeho název git push [name] * stažení ze vzdáleného repositáře git pull [name] * konfigurace default editoru pro commit zprávy git config --system core.editor ==== Změny ==== * message u posledního commit lze změnit příkazem git commit --amend * pokud byl commit už odeslán na vzdálený repozitář, je třeba použít přepínač force ''-force-with-lease'' * pokud už někdo navázal na tento commit, akce se neprovede git push --force-with-lease [repository] [branch] ===== Vracení změn ===== ==== Reset ==== * vracení změn přidaných do staging area * zrušení všech necommitovaných lokálních změn * zrušení lokálních commitů git reset [cesta] git reset --hard git reset [revize] * režim * ''--soft'' - resetuje pouze HEAD * zruší následující commity a soubory ponechá ve staging area * ''--hard'' - resetuje HEAD, index a working tree * zruší následující commity a všechny soubory vrátí do původní verze * default revize je ''HEAD'' * lez použít čislo commitu nebo i relativní odkaz přes HEAD~2 apod * pokud je zadána starší revize, zruší všechny následující commity * nemělo by se dělat na pushnuté (nahrané na vzdálený repozitář) commity, naruší se posloupnost a vzniknou konflikty ==== Checkout ==== * revertování lokálních změn souborů * přepnutí na jinou větev (vytvoření) * získání souboru z jiné větve git checkout [revize] [cesta] git checkout [vetev] git checkout [vetev] [cesta] * default revize je HEAD * lze zadat sha1sum commitu * nebo relativně jako například HEAD~2 (2 commity dozadu) * při přepnutí na jinou větev se lokální necommitované změny souborů přenáší do nové větve * pokud by nastal konflikt, nepřepne se ==== Revert ==== * vrácení změn provedené zadaným commitem a provedení nového commitu git revert [commit] ===== Odkládání změn ===== * stash * lze použít pro řešení konfliktů při mergování * lze použít na dočasné uložení rozdělané práce * může jich být víc, lze je pojmenovávat * Uschování všech změn v lokálním repozitáři do stash a vrácení repozitáře do čistého stavu git stash [save "stash_name"] * Výpis všech uschovaných stashů git stash list * Výpis detailů stash * pokud není uveden název stash, bere se ta poslední git stash show [stash_name] * Aplikace změn ze stash do aktuální větve git stash apply [stash_name] * Aplikace změn ze stash a odstranění stash git stash pop [stash_name] * Odstraní stash git stash drop [stash_name] * Odstraní úplně všechny stash git stash clear ===== Vyzvedávání změn ===== * Příkaz ''git pull'' provádí ''git fetch'' a ''git merge'' ==== Fetch ==== * Příkaz fetch vyzvedne reference (větve, tagy, commity..) a ponechá je nesloučené s ukazatelem FETCH HEAD * z hlavního vzdáleného repozitáře * lze vyzvednout i jen konkrétní větev z konkrétního repozitáře git fetch [ [master]] * Parametr prune smaže všechny lokální reference, které na vzdáleném repozitáři neexistují git fetch --prune ==== Merge ==== * Sloučení vzdálené větve origin/master do aktuální lokální git merge origin/master * Vypsání všech commitů mezi lokální a vzdálenou master větví * lze použít také ''git diff'' git log --oneline master..origin/master ===== Větve ===== * jsou podstatou gitu * slouží jako kopie projektu (workspace) * hlavní větev se většinou označuje jako master * další větve vznikají libovolně, využívají se například pro * merge requests (po akceptování merge do hlavní větve se zdrojová zahodí) * nezávislý vývoj nových feature * dělí se na * lokální - před prvním push se musí nastavit/založit odpovídající vzdálená větev * vzdálené - nelze přímo upravovat, ze vzdálené se vytvoří nejprve lokální větev ==== Informace ==== * Vypíše seznam všech větví * parametr ''--all'' zobrazí kromě lokálních také vzdálené větve git branch [--all|-a] * Vypíše seznam větví včetně názvu vzdálené, kterou sleduje git branch -vv ==== Úpravy ==== * Vytvoří novou větev s názvem new_feature, neprovede ale přepnutí (checkout) git branch new_feature * Vytvoří větev a přepne se do ní (provede checkout) git checkout -b new_feature * Přepnutí do existující větve git checkout master * Vymaže lokální větev (pokud je mergnutá do jiné větve) git branch -d new_feature * Odstraní lokální reference na vzdálené větve, které byly na vzdálené straně odstraněny git fetch --prune * Přejmenuje aktuální větev git branch -m awesome_feature ===== Tagy ===== * slouží k označení komitu * měl by být unikátní, nelze mít dva commity se stejným tagem ==== Informace ==== * Vypíše seznam všech tagů git tag * Vypíše pouze tagy se jménem, které splňují daný pattern git tag --list "v1*" * Vypíše tagy na daném commitu, lze použít i jiné objekty gitu git tag --points-at b7ef32 * Prohlížení pomocí jména tagu, zobrazí informace o tagu i commitu git show v1.0 ==== Úpravy ==== * Přidá tag k aktuálnímu commitu * POZOR -- vynecháním přepínače ''-a'' se vytvoří lightweight tag git tag -a v2.0-beta -m "Releasing v2 beta" * Přidání zpětně ke staršímu commitu git tag -a v2.0-beta -m "Releasing v2 beta" dd7216 * Následující operace nelze provést po pushnutí tagů do remote * Přesun tagu na jiný commit pomocí --force git tag -a v1.0 --force * Odstranění tagu git tag -d v1.0 ===== Prohlížení commitů ===== * zobrazení commitů git log git log -n2 # maximálně dva commity git log --oneline # jeden řádek na commit * zobrazení commitů ve všech větvích git log --all ===== Prohlížení rozdílů ===== * zobrazení rozdílů v souborech * bez parametrů vypíše rozdíly mezi HEAD a aktuálními změnami pro všechny soubory * lze vypsat konkrétní cestu git diff [path] * Lze specifikovat commit vůči kterému se porovnává git diff [ [path]] * Parametr ''--cached'' porovnává HEAD/commit vůči souborům přidaným do staging area. * Opět lze specifikovat soubory git diff ---cached [ [path]] * Porovnává soubor/y mezi dvěma commity git diff * zobrazení commitů mezi lokálním a centrálním repositářem git log --oneline master..origin/master git diff master..origin/master * zobrazení všech změn externím nástrojem (meld) mezi aktuální branch a zadanou git difftool --dir-diff origin/moje-branch ===== Externals ===== * hodí se pro připojení jiného git projektu jako podprojekt * možnosti jsou * subtree - udělá jakoby checkout obsahu jiného projektu do složky v projektu * submodule - vytvoří se jen vazba adresáře na jiný git repozitář ==== Submodule ==== * Klonování projektu se submoduly git clone git submodule init // inicializuje adresář subprojektu git submodule update // nastaví obsah adresáře subprojektu na referenci * Aktualizace souborů submodulů * pokud chceme do superprojektu dostat novější verzi submodulu * v superprojektu nastaví referenci na poslední komit ve vzdáleném repozitáři * adresář submodulu v superprojektu změní svůj stav na modifikovaný * změní obsah adresáře submodulu, aby odpovídal referenci * a) v adresáři submodulu zavolat (doporučeno) git pull * b) v adresáři superprojektu zavolat (vytvoří detached head) git submodule update --remote * Detached head * Pokud se provádí update na referenci jinou než je commit v HEAD vzdáleného repozitáře, vznikne detached head. * Pokud neplánujeme měnit soubory subprojektu, tak by to nemělo ničemu vadit. * Detached head lze vrátit zpět na HEAD postupem: * zjistit branch, kterou má repo sledovat * kouknout, zda sledujeme nejakou konkretni v .gitmodules * pokud ne, tak třeba přes git branch --remote zjistit kam smeruje HEAD, zda to chceme * v adresáři submodulu pak git checkout git pull * Odstranění submodulu * pro verzi 1.7.8+ stačí: git submodule deinit git rm rm -rf .git/modules/ // zruší zbytek lokalních referencí, jinak může dělat v budoucnu problémy * Přidání submodulu git submodule add [-b ] [URL] [DIR] * Přepnutí branch u submodulu * prý stačí git config -f .gitmodules submodule..branch * a nebo možná * editovat branch v .gitmodule souboru (pokud tam není, tak připsat) * zavolat git submodule deinit * zavolat git submodule init * zavolat git submodule update --remote * a nebo možná git submodule update --remote cd [SUBMODULE] git checkout [NEWBRANCH] ====== Workflow ====== ===== GitLab ===== * Ruby projekt pro projekty v Git * Fork * celý projekt patří jednomu uživateli * pokud chce někdo provést změnu, vytvoří si fork celého projektu * následně vytvoří merge request do původního projektu ze svého * Větve * projekt má více členů * hlavní větve jsou protected proti přímé editaci * pokud chce někdo provést změnu, vytvoří si novou větev z cílové * následně vytvoří merge request do původní větve ===== Řešení konfliktů při merge ===== VER_FROM= VER_TO= git fetch origin git checkout ${VER_FROM} git pull git branch -D merge-${VER_FROM}-to-${VER_TO} git checkout -b merge-${VER_FROM}-to-${VER_TO} origin/${VER_TO} git merge --no-ff ${VER_FROM} git mergetool git commit -m "Resolve conflicts" git push origin merge-${VER_FROM}-to-${VER_TO} * dobrý mergetool (lze nastavit) je meld * levé okno je FROM * pravé okno je TO * prostřední je výsledek merge ====== Git HTTPS server ====== * jsou dvě možnosti * přes webdav * přes [[https://www.kernel.org/pub/software/scm/git/docs/git-http-backend.html|git-http-backend]] (doporučuje se) ===== Webdav ===== * [[http://blog.bobbyallen.me/2012/07/23/installing-a-git-server-using-apache-webdav-on-ubuntu-server-12-04/|installing-a-git-server-using-apache-webdav-on-ubuntu-server]] * [[bft_apache#webdav|Apache + WebDav]] * je zde problém s AUTH na metodu PROPFIND: git neposílá auth, ale webdav ji očekává (nebo tak něco) * zobrazuje se hláška error: Cannot access URL https://XXXXXX, return code 22 fatal: git-http-push failed * na serveru v logu je u PROPFIND error 401 (unauthorized) * zkoušel jsem [[https://jsosic.wordpress.com/tag/http/|fix]], ale nepomohlo * musel jsem rozchodit přes přidání username přímo do url (buď při clone nebo ručně následovně) vim .git/config [remote "origin"] url = https://USER@XXXXX/YYYY.git * pokud na serveru máme selfsigned certifikát, je třeba při clone zadat git clone https://XXX/YYYY.git -c http.sslVerify=false * alternativně to lze zadat přes git config nebo přímou editací .git/config souboru * sslverify jen pro určitý server se vypne takto: [http "https://XXXXXX"] sslverify = false ===== Odkazy ===== * workflow s gitem * https://www.atlassian.com/git/tutorials/comparing-workflows * jeden z mnoha návodů na git * http://www.kutac.cz/blog/pocitace-a-internety/jak-na-git-dil-0-co-proc-jak/ * aplikace pull request z github (pokud ho ještě autor nemergoval) * https://help.github.com/articles/checking-out-pull-requests-locally