Základy GITu

Agenda

  • Struktura GITu
  • Základní příkazy
  • Detached head a dangling commity
  • Merge a Rebase

Struktura GITu

Hlavní komponenty

  • HEAD - ukazatel na aktuální commit
  • Branch - jmenný ukazatel na commit
  • Working directory - skládá se ze souborů, na kterých aktuálně pracujeme
    • Stavy Git souborů:
      • Untracked
      • Staged
      • Committed
      • Modified
  • Staging / Index - registr modifikovaných souborů
  • Local repository - kontejner, který zaznamenává změny na projektu
  • Remote repository - repozitář na serveru

Stavy Git souborů

Git komponenty

Legenda

  • Pro následující diagramy budeme používat toto značení:

Git strom

  • Git ukládá commity ve stromové struktuře. Každý commit může mít nula, jeden i více předků.

Základní příkazy

Základní příkazy

PříkazOblastPopis
git initRepoVytvoří prázdný Git repozitář
git cloneRepoNaklonuje repozitář do prázdného adresáře
git branchRepoVytváří, zobrazuje a maže větve
git logRepoZobrazí záznam commitů
git addFile-levelPřidá změny v pracovním adresáři do indexu
git commitCommit-levelVytvoří unikátní snapshot podle změn v indexu/stage
git pushCommit-levelUploadne data na remote repozitář
git fetchCommit-levelSynchronizuje změny s remote repozitářem
git pullCommit-levelAktualizuje HEAD s nejnovějšími změnami
git checkoutCommit-levelPřepíná mezi větvemi či commity
git checkoutFile-levelVrátí zpět změny či stáhne různé verze souborů z jiných commitů
git resetCommit-levelZahodí commity či necommitnutné změny
git resetFile-levelVyhodí soubor z indexu
git restoreFile-levelZahodí změny v pracovním adresáři
git revertCommit-levelVytvoří revertní commit

Git commit

  • Vytvoří unikátní snapshot dle změn v indexu

Git commit --amend

  • Přidá změny k předchozímu commitu
Pokud aktualizujete commit, jeho hash se změní!

Git push

  • Uploadne data na remote repozitář

Git fetch

  • Synchronizuje data s remote repozitářem
Git fetch neovlivní váš pracovní adresář ani HEAD!

Git pull

  • Aktualizuje HEAD s posledními změnami

Git reset a git restore (pro soubory)

  • git reset zahodí změny v indexu, git restore zahodí změny v pracovním adresáři
A co mám dělat, když zahodím změny omylem?

Git reset (pro commity)

Git checkout (pro commity)

  • Umožňuje navštívit jiné commity/větve

Git checkout - relativní

  • HEAD~ - ukazuje na prvního předka
  • HEAD^2 - ukazuje na druhého předka
  • HEAD@{N} - ukazuje na dangling commit

Detached HEAD a dangling commity

Detached HEAD

  • Nastane, když posuneme HEAD tam, kde není odkaz na žádnou větev

Dangling commity

  • git checkout posune HEAD, git reset posune také ukazatel na větev
  • Dangling commity jsou sirotci, kteří už neodkazují na hlavní strom

Dangling commity a reflog

  • git reflog zobrazí historii všech operací
  • Může být použit pro jakoukoliv undo operaci
  • Příklad: reflog pro daný strom
    1 1b83d80 (HEAD -> master) HEAD@{0}: commit: C
    2 10732cb HEAD@{1}: checkout: moving from feature to master
    3 ece569e (feature) HEAD@{2}: commit: BA
    4 10732cb HEAD@{3}: checkout: moving from master to feature
    5 10732cb HEAD@{4}: commit: B
    6 d2851af HEAD@{5}: commit (initial): A

Merge a Rebase

Čistý merge

  • Mergne jednu větev do jiné. Nastává, kdy tu nejsou paralelní commity.

Špinavý merge

  • Nastává u veřejných větví
Keen ví, že tento přístup není nejvhodnější!
Keen má raději git
rebase!
Keen je chytrý!
Buďte jako Keen!

Git rebase

  • Pomůže integrovat větve tak, aby na sebe bezkonfliktně navazovaly
  • Může vytvořit nové commity nebo odstranit ty staré

Git rebase - příklad

Git rebase zpravidla vytváří nové commity a modifikuje strom!

Git merge vs Git rebase

Git merge vs Git rebase

Výhody

  • git merge je nedestruktivní operace
  • git rebase má za výsledek mnohem čistší a lineární historii

Nevýhody

  • U aktivních veřejných větví může git merge zaneřádit historii
  • git rebase ztrácí kontext, který naopak poskytuje merge commit
Pokud používáte git merge v týmovém projektu často, vaše repo se nakonec promění v Guitar Hera

Interaktivní rebase

  • git rebase -i
  • Můžeme rozšířit a různě upravit jednotlivé commity
  • Může být použit pro vyčištění zbastlené historie před čistým mergem
  • Příklad:
    1 pick a8f0e62 Implement new selectbox
    2 squash 42ec648 Update docs
    3 fixup 5ebfbb8 Fix a few issues
    4 fixup 41508f6 Fix a few other issues
  • p (pick) - použij commit
  • r (reword) - použij commit a edituj zprávu
  • e (edit) - použij commit a sluč s tím předchozím
  • s (squash) - spoj commit a zachovej zprávu
  • f (fixup) - spoj commit a zahoď zprávu
  • x (exec) - spusť shellový příkaz

Zlaté pravidlo při Rebase

  • Nikdy neprovádějte rebase u veřejných větví. Budete potřebovat force-push a způsobíte problémy ostatním.
  • Zde: někdo force-pushnul commity D a E a ostatní se snaží pullnout změny.

Shrnutí

  • Hash commitu se nedá změnit. Pokud změníte commit, git vytvoří nový a zahodí starý
  • git fetch stahuje poslední změny, git pull zároveň posune HEAD
  • Detached head nastane pokud posuneme HEAD tam, kde není ukazatel na žádnou větev
  • git checkout posune HEAD, git reset zároveň posune ukazatel na větev
  • Pokud ztratíte některé commity, můžete je najít přes git reflog
  • git rebase vytváří nové commity a modifikuje strom
  • git merge je nedestruktivní operace, git rebase ztrácí po aplikaci kontext
  • Nikdy neprovádějte rebase u veřejných větví
  • Co jsme se naučili: init, clone, status, branch, log, add, commit, switch, whatchanged, push, fetch, pull, checkout, reset, restore, revert, merge, rebase, reflog, diff, remote
  • Kompletní cheatsheet je k dispozici zde