Lekce 9 - Git - Kolize mezi větvemi
V předchozím kvízu, Kvíz - Zkoumání historie, správa a slučování větví v Gitu, jsme si ověřili nabyté zkušenosti z předchozích lekcí.
V dnešním Git tutoriálu se budeme zabývat kolizemi při slučování větví. Vysvětlíme si, kdy kolize vznikají. Na praktickém příkladu se naučíme, jak kolizi nejlépe vyřešit.
Všechny příkazy budeme provádět v našem naklonovaném
repozitáři laravel
z lekce Git - Základy -
Dokončení. Otevřeme terminál MinTTY
a pomocí příkazu
cd laravel
se do repozitáře přesuneme.
Kolize mezi větvemi
Kolize vznikají při slučování dvou větví. Kolize nastane, když se dvě větve současně pokoušejí upravit stejnou část kódu nebo soubor a Git nedokáže rozhodnout, kterou verzi použít.
Kolize mohou vzniknout z následujících důvodů:
- úpravy stejného řádku kódu,
- smazání nebo přejmenování souborů,
- změny v různých částech stejného souboru.
Dojde-li ke kolizi, Git označí soubory, ve kterých se konflikt vyskytl.
Soubory jsou označené jako nevyřešené změny neboli
unmerged paths
. V takovém případě je na vývojáři, aby
konflikt vyřešil a určil, které změny mají být
zachovány. Řešení kolizí je důležitou součástí správy verzí
v Gitu a je nezbytné pro koordinaci vývoje projektu v týmu.
Pokud bychom narazili na kolizi při slučování, spuštěním příkazu
git status
bychom si zobrazili výpis souborů, které kolizi
způsobily. Pokud by například obě naše větve upravily stejnou část
souboru README.md
, zobrazila by se tato varovná zpráva:
On branch 10.x Unmerged paths: (use "git add/rm ..." as appropriate to mark resolution) both modified: README.md
Typy kolizí
Konflikty mohou nastat ve dvou případech: na začátku procesu sloučení nebo během něj.
Selhání sloučení při spuštění
Tento typ kolize nastává v případě, kdy by byly probíhající změny v
pracovním adresáři nebo v pracovní oblasti projektu přepsány commity,
které se právě slučují. Tento problém vzniká kvůli existujícím
lokálním změnám. K odstranění této situace a převzetí kontroly nad
místním stavem slouží příkazy git checkout
,
git commit
a git reset
.
Při selhání sloučení při spuštění se zobrazí následující zpráva:
error: Entry '<fileName>' not uptodate. Cannot merge. (Changes in working directory)
Selhání během slučování
Kolize typu selhání během slučování říká, že došlo ke konfliktu mezi aktuální cílovou větví a slučovanou větví. Při tomto typu kolize se zobrazí následující zpráva:
error: Entry '<fileName>' would be overwritten by merge. Cannot merge. (Changes in staging area)
Identifikace konfliktů při slučování větví
Na následujícím příkladu si ukážeme, jak taková kolize může vzniknout. Naučíme se místo kolize identifikovat a opravit.
Začneme tím, že se přepneme do větve feature
:
MINGW64:/c/mujgit/laravel ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (10.x) $ git checkout feature ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (feature) $
Větev feature
jsme zakládali v lekci Git - Slučování
větví. Pokud ji nemáte, založte si ji příkazem
git checkout -b feature
.
Nyní provedeme editaci souboru README.md
a vytvoříme
commit:
MINGW64:/c/mujgit/laravel ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (feature) $ echo "Editace souboru na větvi feature" >> README.md ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (feature) $ git add README.md ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (feature) $ git commit -m "Úprava souboru README.md" [feature 59424c6f] Úprava souboru README.md 1 file changed, 1 insertion(+) ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (feature) $
Následně se přepneme na větev 10.x
, provedeme editaci
souboru README.md
a vytvoříme commit:
MINGW64:/c/mujgit/laravel ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (feature) $ git checkout 10.x ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (10.x) $ echo "Editace souboru na větvi 10.x" >> README.md ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (10.x) $ git add README.md ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (10.x) $ git commit -m "Úprava souboru README.md" [10.x 875436f6] Úprava souboru README.md 1 file changed, 1 insertion(+) ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (10.x) $
V posledním kroku sloučíme větev feature
s větví
10.x
:
MINGW64:/c/mujgit/laravel ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (10.x) $ git merge feature Auto-merging README.md CONFLICT (content): Merge conflict in README.md Automatic merge failed; fix conflicts and then commit the result. ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (10.x|MERGING) $
Hlášení o kolizi
Po spuštění příkazu git merge
nastane kolize a vypíše se
nám následující zpráva:
Auto-merging README.md CONFLICT (content): Merge conflict in README.md Automatic merge failed; fix conflicts and then commit the result.
Zpráva nám oznamuje, že došlo ke kolizi v souboru README.md
a automatické sloučení selhalo. Nyní se podíváme na nesloučené větve.
Spusťme příkaz git status
, abychom získali následující
výpis o stavu repozitáře:
MINGW64:/c/mujgit/laravel ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (10.x|MERGING) $ git status On branch 10.x Your branch is ahead of 'origin/10.x' by 5 commits. (use "git push" to publish your local commits) You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add <file>..." to mark resolution) both modified: README.md no changes added to commit (use "git add" and/or "git commit -a") ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (10.x|MERGING) $
Výpis nám říká:
On branch 10.x
– Nacházíme se na větvi10.x
.Your branch is ahead of 'origin/10.x' by 5 commits.
– Lokální větev má o 5 commitů více než vzdálená větevorigin/10.x
.You have unmerged paths.
– Existují soubory, které nelze automaticky sloučit. Konflikty v těchto souborech je třeba vyřešit ručně.Unmerged paths:
– Existují soubory se změnami, které je třeba ručně sloučit.both modified: README.md
– SouborREADME.md
byl upraven oběma větvemi a způsobil kolizi.
Vidíme, že kolizi způsobil soubor README.md
. Jelikož
cílová a slučovaná větev obsahují změny, Git neví, kterou verzi souboru
použít, a proto vyvolal kolizi.
Nalezení místa kolize
Místo, kde došlo ke kolizi, si popíšeme. Otevřeme soubor
README.md
příkazem cat
:
MINGW64:/c/mujgit/laravel ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (10.x|MERGING) $ cat README.md ...
Místo, kde došlo ke kolizi při sloučení, je označeno těmito vizuálními znaky:
<<<<<<< HEAD Editace souboru na větvi 10.x ======= Editace souboru na větvi feature >>>>>>> feature
Značky =======
označují střed kolize. Obsah mezi těmito
značkami a řádkem HEAD
představuje obsah existující v
aktuální cílové větvi, na který odkazuje ukazatel HEAD
.
Řešení kolize
Pokud se setkáme s kolizí, je důležité ji správně vyřešit. Nejběžnějším postupem je upravit soubor, ve kterém ke kolizi došlo, a určit, které změny mají být zachovány.
V našem případě se bude jednat o soubor README.md
. Otevřeme
si jej v editoru a nalezneme následující konfliktní značky:
MINGW64:/c/mujgit/laravel ... Přidaný text 1 Přidaný text 2 <<<<<<< HEAD Editace souboru na větvi 10.x ======= Editace souboru na větvi feature >>>>>>> feature
Pro vyřešení kolize je nutné odstranit konfliktní značky a upravit
obsah tak, aby odpovídal požadovanému výsledku sloučení. Soubor
README.md
upravíme tak, aby byly přítomny úpravy z obou
větví. Konec souboru README.md
bude vypadat následovně:
... Přidaný text 1 Přidaný text 2 Editace souboru na větvi 10.x Editace souboru na větvi feature
Upravený soubor uložíme a provedeme commit pro uložení provedených změn:
MINGW64:/c/mujgit/laravel ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (10.x|MERGING) $ git add . ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (10.x|MERGING) $ git commit -m "Oprava kolize při sloučení větví" [10.x 139dc808] Oprava kolize při sloučení větví ItNetwork@DESKTOP-ADEVTG4 MINGW64 /c/mujgit/laravel (10.x) $
Po vytvoření commitu je kolize úspěšně vyřešena a změny jsou zaznamenány v repozitáři. Sloučení větví se automaticky dokončí po vytvoření commitu.
V příští lekci, Git - Vzdálený repozitář - GitHub a protokoly HTTPS a SSH, si založíme profil na GitHubu. Ukážeme si, jak nastavit Git pro připojení přes protokoly HTTPS a SSH.