Jak na git - díl 2.

(publikováno 25.10.2016) Git, Windows, Linux

Ve druhém díle tutoriálu o GITu podrobněji ukážu operace ve staging area, konkrétně přidávání a odebírání souborů. Také listování a procházení historie a rušení posledních commitů.

Jak na git - díl 2.

Tento článek patří do seriálu Jak na git. Ostatní články seriálu:


Staging area podruhé

Již bylo řečeno, že pomocí git add se přidávají do staging area soubory, které poté budou součástí commitu. Co když ale je potřeba soubor ze staging area odebrat? Příkaz git status, nějakou jednoduchou nápovědu vypíše přímo, viz následující obrázek.

Příkaz git status

git status # Vypíše seznam podobný jako na obrázku

git status --short # Výstupem je jednořádkový výpis
git status --ignored # Do výpisu zahrne i ignorované soubory

Přidávání, odebírání a rušení změn

Přidávání je popsáno v minulém článku, jen doplnění, že před verzí Gitu 2.x příkaz git add nepřidal do staging area soubory, které se mazaly. Nyní už se to řešit naštěstí nemusí.

Na příkaz git checkout i git reset je potřeba si dávat velký pozor, protože dělají velké množství úloh a některé dosti destruktivní. Protože větve budou někdy příště, v posledním příkazu místo vetev stačí napsat master, protože tak se nyní hlavní větev jmenuje.

# Viz minulý díl, přidává jak "untracked" tak "not staged" soubory
git add soubor

# Odstraní soubory pouze ze staged area, místo jména souboru
# lze napsat i . pro všechny, podobně jako u git add
git reset HEAD soubor

# Zruší úpravy souborů pouze v non-staged area, soubory přidané
# do staging area a "untracked" ponechá
# POZOR na tečku, zruší v non-staged vše, viz git add apod
git checkout .
git checkout soubor

# Zruší úpravy souborů jak v non-staged, tak v staging area
# Pouze ale soubory již trackované gitem. Nové soubory ponechá
git checkout vetev soubor

git log - výpis předchozích commitů

Příkaz git log, jak název napovídá, zobrazí historii commitů. Každý commit je identifikován unikátním kódem, který je vygenerován SHA1 algoritmem. Tímto kódem se dá odkazovat na jednotlivé commity. Naštěstí se nemusí psát celý 40-místný kód, ale většinou stačí prvních 6-8 znaků.

# Vypíše informace o commitech, včetně data, zprávy i autora 
git log

# Následující přepínače se dají kombinovat
# Poslendí 2 commity, jednořádkový výpis
git log -n 2 --oneline
# Zobrazí reference na HEAD a větve u jednotlivých commitů
git log --decorate
# Zobrazí všechny větve a zobrazí ve stromě
git log --all --graph

# Různé omezení na výpis,
# robrazí jen commity splňující 1 a více kritérií
git log path/to/file.txt
git log --author="pattern"
git log --grep="pattern zprávy commitu" --regexp-ignore-case
git log --since="YYYY-mm-dd" # nebo --after="YYYY-mm-dd"
git log --until="YYYY-mm-dd" # nebo --before="YYYY-mm-dd"

# Výpis v rozsahu, lze kombinovat s větvemi, tagy, commity, HEAD...
# Všechny následující vypíšou příkazy commity 1364cf a b54afd
git log 55aa66..b54afd
git log 55aa66..HEAD
git log 55aa66..master

git log

git checkout a HEAD reference

Pomocí git log se dají zjistit informace o starých commitech. Pomocí git checkout se tyto commity dají prohlížet. Důležité je prvně vysvětlit co je HEAD reference. HEAD je ukazatel na určitý commit většinou však větev, a všechny soubory jsou ve stavu tohoto commitu. Na větev ukazuje proto, že při novém commitu se posouvá automaticky, nemusí se přesouvat. Při vytvoření nového commitu je jeho rodič ten, kam ukazoval HEAD.

Pokud tedy pomocí git checkout se HEAD přesune do staršího commitu, soubory se změní, aby odpovídaly commitu kde je HEAD. Stav, kdy HEAD ukazuje na commit místo na větev se nazývá detached head.

# HEAD se přesune se o 2 commity dozadu vůči aktuálnímu commitu
git checkout HEAD~2

# HEAD se přesune se na commit, s kódem 55aa66
git checkout 55aa66

# Pro návrat zpět do původního stavu, tj ukazuje na větev
# Dokud nejsou vysvětleny větve, vetev stačí nahradit za master
git checkout vetev

git checkout Detached HEAD stav po git checkout

checkout jednotlivých souborů

Nemusí se vždy měnit všechny soubory z commitu na starší verzi. Git dokáže vrátit pouze jednotlivé soubory. Při tomto řešení HEAD zůstane na původním místě. Nyní se může klidně vytvořit ze souboru nový commit. Git totiž verzi souboru z minulého commitu umístí přímo do staging area.

# HEAD zůstane, ale původní verze souboru se vloží do stagign area
git checkout 55aa66 index.html

# Stejná situace jako výše, git checkout vrátí soubor do verze
# jako je v master větvi
git checkout master index.html

git reset

Příkaz git reset odebírá soubory ze staging area. Pokud je ale specifikován commit do kterého má být vše resetováno, zruší posledních n commitů. Tato operace není vhodná, pokud již commity jsou pushnuté, protože poté nebude sedět posloupnost a vzniknou konflikty apod. Podle módu (--mixed, --soft, --hard), může git reset přepsat i aktuální úpravy, na to velký pozor, ať se omylem nepřepíší veškeré změny.

# Commity zruší a soubory vloží do "unstaged" stavu
# --mixed je defaultní, místo čísla commitu lze použít HEAD~2 apod
git reset 55aa66
git reset --mixed 55aa66

# Zruší commit a soubory ponechá ve staging area
git reset --soft 55aa66

# Zruší commit a všechny soubory vrátí do původní verze
git reset --hard 55a66

git reset Stav po git reset, commity další jsou smazány

Garbage collecting

Při provedení git reset nejsou staré commity ihned smazány, ale pouze označené ke smazání.  Lze je tedy obnovit, ale pouze do doby, než git vyčistí vše a smaže je i fyzicky. K těmto na první pohled ztraceným commitům se dá dostat pomocí příkazu git reflog. Více v pátém díle.

Podobný scénář nastane při vytvoření commitů v detached HEAD stavu. Nové commity budou v nové větvi, ta ale nemá ale žádnou referenci. Při spuštění garbare collectingu se také smažou. Viz obrázek a ukázka příkazů:

# Zrušení posledních commitů, git je ve stavu viz obrázek výše
git reset --hard 55aa66
# Pokud je známo číslo commitu, lze se do něj vrátit
git reset b54afd

# Vytvoření commitu v detached HEAD stavu
git checkout 55aa66
# Nyní jsou vytvořeny/upraveny/smazány nějaké soubory
# git commit -a přidá všechny soubory, ušetří příkaz git add .
git commit -a -m "This commit will be removed by garbage collector"
git checkout master

Následující obrázek není úplně přesný. Pokud přesuneme HEAD zpět na commit b54afd tak git log nám commit dd7216 již neukáže. Pokud by ale na něj ukazovala HEAD, a použijeme přepínač --all tak uvidíme graf podobný tomu na obrázku.

git commit z detached HEAD Commit dd7216 vytvořen z detached HEAD stavu,
při dalším spuštění garbage collectingu bude smazán.


Podělte se v komentářích o zkušenosti s Gitem, nebo přidejte tipy k příkazům do dalších článků o gitu.

K tomuto článku již není možné přidávat další komentáře