Průvodce začátečníka interaktivním rebasováním

Původně publikoval Stride 16. ledna 2018 52,731 čtení

Na začátku tohoto roku jsem poprvé dělal interaktivní rebase a byl jsem ohromen tím, co se s tím dá dělat. Také jsem zjistil, že je to zpočátku trochu složité. Doufám, že tento návod pomůže odstranit některé nejasnosti kolem ní.

A protože je tak mocná a můžete v podstatě přepsat historii, malé varování, než začneme: Existuje mnoho názorových směrů na systém Git a na to, zda je přeřazování dobrý nápad, nebo ne. V tomto příspěvku se do těchto diskusí nebudeme pouštět a jeho cílem je čistě projít základy používání interaktivního rebasingu.

TL;DR

  • Interaktivní rebasing lze použít pro změnu revizí mnoha způsoby, jako je editace, mazání a mačkání.
  • Chcete-li systému Git sdělit, kde má interaktivní přebasování začít, použijte kód SHA-1 nebo index revize, která bezprostředně předchází revizi, kterou chcete změnit.
  • Při interaktivním přebasování, kdy se systém Git pozastaví u revize, kterou jste označili k úpravě, se pracovní postup neliší od běžného procesu odevzdávání – soubory rozfázujete a pak je odevzdáte. Jediný rozdíl je v tom, že místo příkazu git commit použijete příkaz git commit --amend.
  • Interaktivní přeřazení vytvoří nové SHA-1, proto je nejlepší používat interaktivní přeřazení u revizí, které jste neodeslali do vzdálené větve.

Problém

V tomto příkladu budeme řešit situaci, kdy jsme pracovali ve feature větvi a máme několik revizí, které bychom chtěli změnit nebo odstranit. Takto vypadá náš protokol git:

Z výše uvedeného protokolu git vyplývají dvě revize, které chceme změnit:
4a4d705 – V této revizi jsme omylem spáchali konflikt sloučení
6c01350 – V této revizi jsme odstranili konflikt sloučení

Chceme se vrátit v čase k revizi 4a4d705, odstranit konflikt sloučení v revizi a poté odstranit revizi 6c01350, protože konflikt sloučení je vyřešen a tuto revizi již nepotřebujeme. To bude zlepšení naší historie revizí ze dvou důvodů:

  1. Nebudeme mít rozbité revize (konflikty sloučení)
  2. Budeme mít pouze smysluplné revize, žádné revize související výhradně s opravou přehlédnutého konfliktu sloučení

Řešení

Tato situace je vhodným kandidátem pro interaktivní přeřazení. Scott Chacon ve své knize Pro Git popisuje interaktivní rebasing následovně: „Někdy nelze opravenou věc … změnit na ne zcela dokonalou revizi, kterou opravuje, protože tato revize je pohřbena hluboko v sérii oprav. Právě k tomu slouží interaktivní rebase: použijte ji po spoustě , přeskupením a úpravou revizí a zmačkáním více revizí do jedné.“

Jaké revize chceme upravit?“

Chceme-li spustit interaktivní rebase, musíme systému Git sdělit, které revize chceme upravit. To provedeme odkazem na revizi bezprostředně předcházející nejstarší revizi, kterou chceme upravit. Nebo, jednoduše řečeno, odkazujeme na „poslední revizi, kterou chceme zachovat tak, jak je“, jak uvádí Scott Chacon.

Podívejme se na náš příklad, abychom mu lépe porozuměli. Existují dva způsoby, jak se na tuto revizi odkázat:
Podle SHA-1 – Poslední revize, kterou chceme ponechat jako stávající, má SHA-1 528f82e, takže ji můžeme předat našemu interaktivnímu příkazu rebase.
Podle indexu – Poslední revize, kterou chceme zachovat jako stávající, má indexovou pozici 3 (Git používá indexování podle nuly), takže můžeme našemu interaktivnímu příkazu rebase předat HEAD~3.

Poznámka – Pokud máte jen několik revizí, u kterých chcete interaktivní rebase provést, je použití indexu pro většinu lidí pravděpodobně jednodušší. Pokud však máte mnoho revizí, je pravděpodobně jednodušší použít příkaz SHA-1, abyste nemuseli počítat až do konce protokolu git.

Spustit interaktivní rebasing

Na základě našeho příkladu spustíme buď:

$ git rebase -i 528f82e

nebo

$ git rebase -i HEAD~3

což otevře toto okno ve Vimu:

Všimněte si, že revize jsou v opačném pořadí než v protokolu git. V protokolu git je nejnovější revize nahoře. V tomto zobrazení je nejnovější revize dole. Všimněte si také, že v komentářích níže je uveden užitečný seznam platných příkazů, které můžeme použít u každé revize.

Pokud neznáte Vim, stačí kliknout na každé slovo pick, které chcete upravit, a pak stisknout klávesu <i> (pro režim vkládání). Po dokončení psaní stiskněte klávesu <esc> pro ukončení režimu vkládání.

V našem příkladu jsme změnili příkaz na edit pro revizi, kterou chceme upravit, a příkaz na drop pro revizi, kterou chceme odstranit. Poté spustíme :wq pro uložení a ukončíme okno Vim.

Změnit revizi

Zpět v terminálu vidíme tuto zprávu:

To dává smysl, že jsme se zastavili na 4a4d705. Jedná se o nejstarší revizi v řadě revizí, které chceme upravit. Začneme touto revizí a budeme postupovat přes jednotlivé revize až k té nejnovější.

Připomínáme, že 4a4d705 byla revize s konfliktem sloučení, kterou jsme omylem odevzdali. Když otevřeme editor, uvidíme tam konflikt sloučení:

Opravíme tedy konflikt sloučení v souboru, ale co budeme dělat teď? Když máte pochybnosti, git status:

Cool! Tohle je skutečně užitečné. Vidíme, že právě upravujeme 4a4d705, a vidíme další dvě revize, které mají být provedeny po této revizi.

Zbytek zprávy nám vysvětluje známý pracovní postup. Systém Git nám říká, že pokud chceme změnit revizi, spustíme git commit --amend. To bude v podstatě fungovat jako náš typický git commit, který používáme v běžném pracovním postupu. V dolní části této zprávy vidíme, že náš soubor byl upraven a odráží změny, které jsme právě provedli, abychom odstranili konflikt sloučení. Než soubor odevzdáme, musíme jej rozfázovat. Tím se nijak nelišíme od běžného pracovního postupu.

Všechno, co uděláme, je, že git add tempChanger.js upravený soubor zařadíme do fáze a pak git commit --amend zařadíme do revize! Nyní se opět otevře okno Vim se zprávou o odevzdání:

Zprávu o odevzdání můžeme buď upravit, nebo ponechat tak, jak je. Rozhodneme se ponechat zprávu o revizi stejnou a zadáme :wq pro uložení a ukončení okna.

Nyní jsme upravili naši starou revizi. A co teď? Spustíme git status:

Pokračovat v interaktivní obnově

Nemáme už v revizi co měnit, takže pokračujme!“

Spustíme git rebase --continue a uvidíme následující zprávu:

Aha, máme hotovo? Ale co ty další dvě revize? No, další revize, na kterou se mělo reagovat, byla 6c01350. Tuto revizi jsme označili ke smazání (drop), když jsme spustili interaktivní rebase. Systém Git ji automaticky smazal a přešel na další revizi 41aa9d2. Ta nebyla při počáteční interaktivní rebase nikdy změněna. Jeho výchozí příkaz byl pick, což znamená, že revize bude použita. Git tuto revizi použil, a protože to byla poslední revize, interaktivní rebase byla dokončena.

Poznamenejme, že kdybychom měli více revizí k úpravě, jednoduše bychom se přesunuli na další revizi a zahájili proces její změny stejně, jako jsme to udělali výše. Cyklus pokračuje, dokud nezbývají žádné revize.

Tlačítko eject

Je třeba poznamenat, že pokud v některém okamžiku naší interaktivní rebase něco pokazíme a nebudeme vědět, jak to opravit, můžeme ji vždy přerušit. V kterémkoli okamžiku můžeme v terminálu spustit příkaz git rebase --abort a interaktivní rebase bude přerušena bez uložení změn. Pak bychom museli interaktivní rebase spustit znovu.

Po interaktivní rebase

Náš protokol git nyní vypadá takto:

Všimněte si, že se oproti době před spuštěním interaktivní rebase změnilo několik věcí:

  • Už nemáme revizi 6c01350 se zprávou o revizi „Remove merge conflict“. To je revize, kterou jsme odstranili v naší interaktivní rebase.
  • Naše revize, kterou jsme upravili, 4a4d705, má jiný kód SHA-1, 2b7443d.
  • Naše poslední revize z původního protokolu git, 41aa9d2, má také nový kód SHA-1, 2b95e92. Tato revize nebyla změněna, ale byla jednoduše použita na revizi před ní 2b7443d.

Vedlejší účinky interaktivního přeřazování

Pro dvě nejnovější revize v našem protokolu git, protože mají nové hodnoty SHA-1, je systém Git považuje za zcela nové revize. To platí i pro naši poslední revizi 2b95e92, kde se zpráva o revizi ani soubory vůbec nezměnily. To přináší důležitý bod týkající se interaktivního přepracování:

To nic neovlivní, pokud revize, které jste upravili, nebyly odeslány do vzdálené větve. Pokud byste však ve skutečnosti dokončili interaktivní rebase na revizích, které již byly odeslány do vzdálené větve, a pak znovu odeslali svou větev, uvidíte:

Technicky byste to mohli obejít použitím git push --force, ale to je velmi nebezpečné. Pokud jsou ve vzdálené větvi revize od jiných lidí, ale vaše místní větev tyto revize ještě nemá, fakticky jejich revize smažete.

Jiným řešením je použití git push --force-with-lease, které změní pouze vaše revize, ale ne revize patřící jiným, i když to může být také problematické. Pokud například jiný vývojář již má tyto revize, které dostaly nové SHA-1, ve své lokální větvi, při stažení vzdálené větve bude mít konflikty sloučení s každou z těchto revizí.

Kdy použít --force-with-lease je nad rámec tohoto příspěvku, ale bylo by nejlepší se před tím poradit s ostatními členy vašeho týmu. Více informací o git push --force-with-lease si můžete přečíst zde.

Klíčovým poznatkem z této části je, že je mnohem jednodušší a bezpečnější používat interaktivní rebasing u revizí, které ještě nebyly odeslány do vzdálené větve.

Napsal Blake DeBoer. Původně zveřejněno na Dev.to

Senior, Lead, nebo Principal developer in NYC? Společnost Stride přijímá nové zaměstnance! Chcete zvýšit úroveň svého technického týmu? Podívejte se, jak to děláme my! www.stridenyc.com

Tags

Join Hacker Noon

Vytvořte si bezplatný účet a odemkněte si vlastní čtenářský zážitek.

Leave a Reply