Řekněme, že v systému Git máme následující situaci:
Vytvořený repozitář:
mkdir GitTest2
cd GitTest2
git init
Provedou se některé změny v hlavním souboru a odevzdají se.
echo "On Master" > soubor
git commit -a -m "Initial commit"
Feature1 se větví z masteru a je hotová nějaká práce:
git branch feature1
git checkout feature1
echo "Feature1" > featureFile
git commit -a -m "Commit for feature1"
Mezitím je v master-kódu objevena chyba a je vytvořena hotfix-branch.
git checkout master
git branch hotfix1
git checkout hotfix1
Chyba je opravena ve větvi hotfix a začleněna zpět do větve master (třeba po žádosti o revizi kódu):
> bugfixFile > echo "Bugfix" > bugfixFile
git commit -a -m "Bugfix Commit"
git checkout master
git merge --no-ff hotfix1
Vývoj funkce1 pokračuje:
a pokračuje se ve vývoji: git checkout feature1
Řekněme, že potřebuji opravu ve své větvi feature, třeba proto, že se tam chyba také vyskytuje. Jak toho mohu dosáhnout, aniž bych duplikoval revize do své feature větve?
Chci zabránit tomu, aby se do mé feature větve dostaly dvě nové revize, které nemají žádný vztah k implementaci feature. To mi připadá důležité zejména v případě, že používám pull requesty: Všechny tyto revize budou také zahrnuty do pull requestu a budou muset být zkontrolovány, ačkoli to již bylo provedeno (protože hotfix je již v masteru).
Nemohu provést git merge master --ff-only
: "fatal: Not possible to fast-forward, aborting.", ale nejsem si jistý, zda mi to pomohlo.
Jak sloučíme hlavní větev do větve feature? Snadno:
git checkout feature1
git merge master
Nemá smysl zde vynucovat rychlé sloučení, protože to nelze provést. Odevzdali jste jak do větve feature, tak do větve master. Rychlé přeřazení dopředu je nyní nemožné.
Podívejte se na GitFlow. Jedná se o model větvení pro git, který lze dodržovat, a vy jste to nevědomky již udělal. Je to také rozšíření systému Git, které přidává některé příkazy pro nové kroky pracovního postupu, které automaticky provádějí věci, které byste jinak museli dělat ručně.
Co jste tedy ve svém pracovním postupu udělali správně? Máte dvě větve, se kterými pracujete, vaše větev feature1 je v podstatě větev "develop" v modelu GitFlow.
Vytvořili jste větev hotfix z větve master a sloučili ji zpět. A nyní jste se zasekli.
Model GitFlow vás žádá, abyste hotfix sloučili také do vývojové větve, což je ve vašem případě "feature1".
Takže skutečná odpověď by byla:
git checkout feature1
git merge --no-ff hotfix1
To přidá všechny změny, které byly provedeny v rámci opravy, do větve funkcí, ale pouze tyto změny. Mohou být v konfliktu s ostatními vývojovými změnami ve větvi, ale nebudou v konfliktu s hlavní větví, pokud nakonec sloučíte feature větev zpět do hlavní.
Při přeřazování buďte velmi opatrní. Přeskupujte pouze v případě, že změny, které jste provedli, zůstaly lokální ve vašem úložišti, např. jste nepřevedli žádné větve do jiného úložiště. Rebasing je skvělý nástroj, který vám pomůže uspořádat lokální revize do užitečného pořadí před tím, než je vytlačíte do světa, ale následný rebasing způsobí začátečníkům v systému git, jako jste vy, zmatek.
Měli byste být schopni převést svou větev na master:
git checkout feature1
git rebase master
Zvládněte všechny vzniklé konflikty. Když se dostanete k revizím s opravami chyb (již v masteru), Git vám řekne, že tam žádné změny nebyly a že už možná byly použity. Pak pokračujete v rebaze (přičemž přeskočíte revize, které jsou již v master) pomocí příkazu
git rebase --skip
Pokud provedete git log
na větvi feature, uvidíte'že revize opravy chyby se objeví pouze jednou, a to v části master.
Podrobnější informace naleznete v dokumentaci knihy Git o git rebase
(https://git-scm.com/docs/git-rebase), která se zabývá právě tímto případem použití.
================ Upravit pro další kontext ====================
Tato odpověď byla poskytnuta speciálně pro otázku položenou @theomega, s přihlédnutím k jeho konkrétní situaci. Všimněte si této části:
Chci zabránit [...] revizím na mé větvi funkce, které nemají žádný vztah k implementaci funkce.
Přesně to, co přinese tento výsledek, je přeřazení jeho soukromé větve na master. Naopak sloučení master do jeho větve by přesně způsobilo to, co konkrétně nechce, aby se stalo: přidání revize, která nesouvisí s implementací funkce, na níž pracuje prostřednictvím své větve.
Na adresu uživatelů, kteří si přečtou nadpis otázky, přeskočí skutečný obsah a kontext otázky a pak si jen slepě přečtou horní odpověď v domnění, že se bude vždy vztahovat na jejich (jiný) případ použití, si dovolím upřesnit:
git merge master
jako v odpovědi @Sven'a).A konečně, pokud'nejste spokojeni s tím, že tato odpověď není pro vaši situaci nejvhodnější, i když pro @theomega byla, přidání komentáře níže vám nijak zvlášť nepomůže: Já neovlivňuji, která odpověď bude vybrána, to dělá pouze @theomega.
Možná budete moci provést "cherry-pick" a stáhnout do větve funkcí přesně ty revize, které potřebujete.
Proveďte git checkout hotfix1
, abyste se dostali do větve hotfix1. Poté proveďte git log
, abyste získali hash SHA-1 (velká posloupnost náhodných písmen a čísel, která jednoznačně identifikuje revizi) dané revize. Zkopírujte ji (nebo prvních asi 10 znaků).
Pak se pomocí git checkout feature1
vraťte zpět do větve feature.
Pak git cherry-pick <hash SHA-1, který jste právě zkopírovali>
.
Tím se tato revize, a pouze tato revize, přenese do vaší větve feature. Tato změna bude ve větvi - právě jste ji "cherry-picked" vložili. Pak pokračujte v práci, upravujte, commitujte, pushujte atd. podle svého uvážení.
Když nakonec provedete další sloučení z jedné větve do své feature větve (nebo naopak), Git rozpozná, že jste již do této konkrétní revize sloučili, bude vědět, že ji nemusí provádět znovu, a prostě ji "přeskočí".