Git - fix your history
Published on: 2020-08-31
1. Změna posledního commitu
S příkazem commit
můžeme použít tzv. flags
, které upravují chování tohoto příkazu. Jedním z takových flags
je --amend
. Pomocí tohoto flags měníme poslední commit.
Pomocí přikzu $ git commit --amend
můžeme:
1. kombinovat změny, které máme v tuto chvíli ve staged
fázi s posledním commitem
2. změnit poslední commit message
, v které jsme udělali chybu nebo překlep. Ovšem tato změna změní uložení commitu a v historii ji budeme vidět s hvězdičkou (*). Tedy vytvoří se nový commit se stejnými informacemi, ale jinou zprávou a navíc bude obsahovat hvězdičku.
1. Přidat soubory ve staged fázi do posledního commitu
Představme si následující sled událostí:
Editujeme soubory hello.py
a main.py
. Po ukončení změn přidáme do gitu pouze main.py
a provedeme commit. V příkazové řádce by úkony vapadly nějak takto:
$ git add main.py
$ git commit
V tuto chvíli si autor uvědomí, že zapomněl přidat do gitu také soubor hello.py
, který chtěl mít ve společném commitu také se souborem main.py
, který už je ale v tuto chvíli commitnutý. Tento problém se při vývoji objevuje poměrně čast a git si s touto situací umí hravě poradit.
Postup opravy může vypadat takto:
$ git add hello.py
$ git commit --amend --no-edit
Použitý flag --no-edit
nám zajistí, že se zapomenutý soubor přidá do posledního commitu, ale commit message
se nezmění. Tedy flag --no-edit
= chceme přidat nové změny do posledního commitu bez úpravy commit message
.
2. Změna zprávy v posledním commitu
Pro změnu poslední commit message
použijeme tento příkaz:
$ git commit --amend
Tímto příkazem se nám objeví námi defaultně nastavený editor textu pro git a v něm poslední zpráva tu můžeme libovolně upravit a následně změny potvrdit, jak jsme zvyklý u běžných commitů
.
Jednořádková změna commit message
se provádí pomocí príkazu:
$ git commit --amend -m "your new or updated commit message"
Když přídáme do příkazu options -m
můžeme změnit ři přepsat commit message
přímo v příkazové řádce aniž bychom museli otevírat textový editora celý proces se takto výrazně zrychlí.
Upozornění: Příkaz amend nepoužívejte pokud jste změny už poslali do public prostoru třeba na GitHub. Jelikož --amend
udělá nový commit, tak bude problém jej pushnout do stejné větve na remote. Jak jsme si řekli --amend
udělá nový commit na větvi a ten starý z ní zmizí, při pushnutí této změny dojde ke konfliktu.
2. Změna jednoho, libovolně starého commitu
Změna se provádí pomocí příkazu git rebase
. Tento příkaz je poněkud složitější a podíváme se tedy na něj v kapitole Git rebase trochu blíže.
Pro změnu konkrétního starého commitu můžeme použít tento příkaz:
$ git rebase <id_old_commit>
id - bude hash commitu
Tento příkaz započne proces rebase
. Proces se zastaví a dá nám na výběr co můžeme udělat.
Většinou pomocí příkazu --amend
uděláme změny a následně řekneme procesu rebase
, že může pokračovat. Proces by mohl vypadat nějak takhle:
$ git commit --amend
$ git rebase --continue
3. Změna několika, libovolně starých commitů
Pro změnu několika commitů najednou se používá tzv. interaktivní rebase. Tento typ rebase
se zapíná pomocí příkazu:
$ git rebase -i
nebo
$ git rebase --interactive
Během rebase
několika commitů najednou máme možnost si vybrat z několika možností jak takové commity spojit dohromady.
- Reword nebo zkráceně ‘r’ - zastaví proces
rebase
a nechá Vás přepsat konkrétnícommit message
- Squash nebo kráceně ‘s’ - během procesu
rebase
, všechny commity označené pomocís
se sloučí s posledním commitem. Procesrebase
se pozastaví a budeme vyzvání k přepsání posledního commitu. - Fixup nebo zkráceně ‘f’ - se chová podobně jako
squash
. Narozdíl odsquashe
, takfixup
nepozastaví procesrebase
k otevření textového editoru.commit meassage
zůstane stejná jako je poslední v poslednímcommitu
pouze se tomuto poslednímu commitu přilepí commity, které jsme označili písmenemf
.commit messages
obsažené v commitech, které jsme označili pomocíf
jsou zahozeny.
drop
Kromě spojování commitů, je možné v interaktivním rebase také commity smazat pomocí slovíčka drop
nebo d
. Smazat commit je také možné pokud před daný commit nedáte žádné specialní slovo.
pickup
Slovo pickup
nebo p
znamená, že tento commit chceme zachovat vzít.
V interaktivním rebase můžeme také přehazovat pořadí jednotlivých commitů, jak v historii gitu půjdou za sebou.
4. Git rebase
Pro lepší pochopení celého kontextu se nevyhneme detailnímu popsání příkazu git rebase
.
Na začátek git rebase
a git merge
jsou v základu stejné příkazi. Oba dva slučují jednu větev do druhé. Ale každý to dělá jinak. Na konci článku je část, která se zabývá přímo srovnáním těchto dvou příkazů.
Příkaz git rebase
je možné používat ve dvou módech:
- standardní či manuální mód
- interaktivní mód (pomocí přepínače
-i
nebo--interactive
)
Nejčastejší použití rebase můžeme vidět, když máme projekt, který je na větvi master
. Tento projekt potřebuje vyvinout novou featuru. Pro tyto účely si založíme novou větev feature_branch
. Na nové feature budeme pracovat nějaký čas. A v tomto čase, kdy mi budeme pracovat na feature, kterou jsme dostali za úkol, bude zbytek týmu pracovat na dalších features projektu. Tím se samozřejmě podoba větve master
změní od podoby, z které jsme vytvořili novou větev feature_branch
. Tento proces můžeme vidět na diagramu níže:
a - b - c - g - h (master)
\
d - e (feature_branch)
Novou větev feature_branch
jsme vytvořili když větev master
měla poslední commit c
. Nyní když bych chtěl mou featuru mergnout tak větev master
se posunula o další dva commity g
a h
. Abychom mohli naši větev pěkně mergnout musíme na ni udělat nejříve udělat rebase
. Tedy chceme založit naše další změny na změnách ostatních - “I want to base my changes on what everybody has already done.”
Užitečné odkazy - další studium
Text článku byl čerpán hlavně z těchto zdrojů: