Jak na squash GIT commitů

Jak posledních několik commitů vrátit zpátky a sdružit do jednoho.

Většina lidí má totiž problém s velkým množstvím commitů v jednom pull requestu. Když dostal požadavek „please squash your commits“ poprvé, strávil jsem nad vyřešením tohoto úkolu více času, než nad samotným programováním funkčnosti v pull requestu.

Na začátku je třeba commitnout nebo schovat (stash) všechny dosud neuložené změny. Pak je také dobré aktualizovat si lokální verzi:

git pull

Úkol

Mám výchozí seznam posledních commitů (nejnovější nahoře)

Chci nejnovější 3 commity sdružit do jednoho a ten jeden přejmenovat.

V příkazové řádce napíši:

git rebase -i [hash]

Za [hash] je třeba dosadit hash posledního commitu, kterého se změny vůbec netýkají a má zůstat nedotčen. V mém případě to tedy bude 6e43c21.

Objeví se okno se třemi posledními commity.

U všech s výjimkou prvního přepíšu pick na „s“ jako squash.

Dám CTRL+X, Yes a Enter pro potvrzení výchozího názvu souboru.

Horší případ

Někdy se stane (a zatím jsem nevypozoroval, kdy přesně a proč), že se objeví chybová hláška, že nelze pokračovat v procesu kvůli konfliktům. Konflikty je třeba vyřešit. Po jejich vyřešení je můžu mergnout a pokračovat v procesu:

git add .
git rebase --continue

Většinou se to zastaví hned na dalším commitu, znovu tam jsou konflikty, znovu je potřeba je vyřešit a opakovat. Takhle pořád dokola až do zblbnutí, než se propracuji až na konec.

Když je těch konfliktů fakt hodně, je dobré si někam vedle uložit výsledné žádoucí podoby všech problémových souborů a při každém kroku je pak vždy jen zkopírovat. Jinak totiž člověk neustále řeší ty samé konflikty dokola. Jestli někdo zná lepší postup, budu rád o doplnění v komentářích.

Jakmile jsou všechny konflikty vyřešené, můžu pokračovat.

Lepší případ

V tom lepším případě se ihned objeví druhé okno, kde je možné upravit commit message.

Výchozí hodnotou je spojení všech squashnutých commitů. Já je odmažu (CTRL+K) a vložím novou žádoucí hodnotu.

Opět CTRL+X, Yes a ENTER.

Pokud vše proběhne v pořádku, stačí už jen pushnout změny zpátky na GitHub (nebo kde mám origin).

git push --force

Výsledek vypadá přesně tak, jak jsem na začátku chtěl:

Varování

Asi bych měl připsat varování, že změna historie je ošemetná operace, kde se může leccos pokazit. Zejména v případě, že s origin repozitářem pracuje vícero lidí, může dojít k mnoha nemilým problémům, s nimiž se já coby one-man programátor nesetkám. Před použitím tohoto postupu buďte tedy opatrní a v případě nejistoty si postup vyzkoušejte někde vedle.