4.5 Merge conflict – feloldás pánikmentesen
Áttekintő
Első merge conflict láttán szinte mindenki lefagy. A terminál pirossal kiírja: CONFLICT, a fájl teliszórva furcsa <<<<<<< jelekkel, a kollégák várják a PR-t – és te nem tudod, mit csinálj.
Ez teljesen normális. A merge conflict nem egy hiba, amit te követtél el. Nem is katasztrófa. Egyszerűen arról van szó, hogy ketten módosítottatok ugyanazon a helyen, és a Gitnek fogalma sincs, melyik verziót tartsuk meg.
Ez az alfejezet megmutatja:
- miért keletkezik merge conflict
- hogyan olvasd a conflict markereket
- lépésről lépésre hogyan old fel pánik nélkül
- mikor kell bevonni a szerzőt
- hogyan maradj kevesebb conflicttal hosszú távon
Részletes leírás
Miért keletkezik merge conflict?
A Git nagyon okos. Legtöbbször simán össze tudja fésülni két ember munkáját – ha különböző fájlokat módosítottatok, vagy ugyanazon fájl különböző részeit.
Conflict akkor keletkezik, ha:
- Ketten módosítottatok ugyanazon a soron (vagy közvetlen közelében)
- Valaki törölte a fájlt, valaki más meg módosította
- Branch merge-elésekor a Git nem tudja eldönteni, melyik változat a helyes
A Git ilyenkor nem dönt helyetted. Megjelöli az ütköző részeket, és azt mondja: „Ezt ti oldjátok fel."
A conflict markerek olvasása
Amikor conflict van, a Git így jelöli meg az érintett részeket:
<<<<<<< HEAD
return user.isAdmin() ? "admin" : "user";
=======
return user.role;
>>>>>>> feature/user-roles
Amit tudnod kell:
<<<<<<< HEAD– a te branch-ed verziója innen kezdődik=======– elválasztó a két verzió között>>>>>>> feature/user-roles– a bemergelni kívánt branch verziója idáig tart
A kettő között nincs „helyes" és „helytelen". Mindkét változtatás valaki munkája volt. A te feladatod eldönteni, mi kerüljön végül a kódba.
A feloldás lépései
1. Nyugodj meg – ez nem vészhelyzet.
Senki nem törölt el semmit. A Git megőrizte mindkét verziót. Visszaléphetsz bármikor (git merge --abort).
2. Azonosítsd az összes conflict-ot.
git status
A kimeneten minden conflict-os fájl megjelenik. Ne próbálj egyből beleugrani – először nézd meg, hány fájlban van probléma.
3. Nyisd meg az érintett fájlokat.
A legtöbb modern editor (VS Code, IntelliJ, stb.) vizuálisan jelöli a conflict-okat – mutatja mindkét verziót és kínál egyszerű feloldási gombokat (Accept Current / Accept Incoming / Accept Both).
Ha nincs ilyen eszközöd, szövegszerkesztővel is megnyithatod a fájlt és manuálisan oldod fel.
4. Minden conflict-nál döntsd el, mi maradjon.
Három eset lehetséges:
- Az egyik verzió a helyes → Töröld a másikat és a markereket
- Mindkettő kell → Kombináld őket (ez a leggyakoribb eset)
- Egyik sem jó → Írd meg újra azt a részt
Fontos: a feloldás után ne maradjon marker a fájlban. Sem <<<<<<<, sem =======, sem >>>>>>>. Ha bennmarad, az szintaxishibát okoz – és nehéz észrevenni.
5. Jelöld megoldottnak.
Miután feloldottad az összes conflict-ot egy fájlban:
git add feloldott-fajl.py
6. Folytasd a merge-t.
Ha minden conflict-ot feloldottál:
git commit
A Git automatikusan generál egy merge commit üzenetet. Elfogadhatod, vagy módosíthatod.
Mikor vond be a szerzőt?
Feloldani tudod magad: ha az ütköző kód egyértelmű és érti vagy, mit csinál mindkét sor.
Kérdezz, ha:
- Nem érted, miért módosította a másik fejlesztő azt a részt
- A két verzió logikailag ütközik (nem csak szintaktikailag)
- Biztosra akarsz menni, hogy nem törsz el valamit
Nem szégyen megkérdezni: „Hé, feloldottam a conflict-ot, de az a rész nem volt számomra egyértelmű – ránéznél mielőtt mergelem?"
Hogyan teszteld, hogy a feloldás helyes?
A feloldás után mindig futtasd le a teszteket, mielőtt pusholsz. Ha nincs automatizált teszt, legalább manuálisan ellenőrizd az érintett funkcionalitást.
A leggyakoribb hibaforrás: a conflict feloldása szintaktikailag helyes, de logikailag rossz. A Git nem tud erről – csak te tudod ellenőrizni.
Proaktív stratégiák: kevesebb conflict a jövőben
Szinkronizálj rendszeresen. Minél régebben nő el a branch-ed a fő ágaktól, annál több conflict lesz. Napi vagy kétnaponkénti git pull --rebase origin main sokat segít.
git pull --rebase origin main
Kis PR-ok, gyors review. Ha a PR-od egy hét után kerül mergeli, közben mások is módosíthattak ugyanazon a területen. Kis, fókuszált PR-ok → kevesebb conflict.
Kommunikáció a csapatban. Ha tudod, hogy kollégád is ugyanazon a modulon dolgozik, egyeztessetek előre. Nem kell mindig technikai megoldás – néha elég egy rövid Slack üzenet.
Életszerű példák
1. példa – klasszikus conflict két fejlesztő között
Szituáció: A main branch-en Anna módosított egy validációs függvényt. Te a feature branch-eden ugyanazt a függvényt módosítottad, más logikával. Mergeled a main-t, és:
<<<<<<< HEAD
def validate_email(email):
return "@" in email and "." in email
=======
def validate_email(email):
import re
return bool(re.match(r"[^@]+@[^@]+\.[^@]+", email))
>>>>>>> main
Mi a teendő?
- Nézd meg, mikor és miért módosította Anna
- A regex-es megközelítés robusztusabb → valószínűleg azt érdemes megtartani
- Ha a te változtatásod is tartalmazott valami egyedit, integráld bele
- Kérdezz rá, ha bizonytalan vagy: „A regex-es verzió erősebb, maradjon az, vagy volt okod az egyszerűbbre?"
Feloldás:
def validate_email(email):
import re
return bool(re.match(r"[^@]+@[^@]+\.[^@]+", email))
Töröld a markereket, git add, majd folytasd.
2. példa – saját konfliktusodat okozol rebase közben
Szituáció: Rebase-eled a branch-edet, és több helyen is conflict keletkezik, mert régóta nem szinkronizáltál.
Tanulság: Rebase-nél minden commit-hoz külön-külön kell feloldani a conflict-okat. Ez idegesítő lehet, ha sok commit volt.
Mit csinálj?
- Konfliktust oldd fel
git addaz érintett fájlokragit rebase --continue- Ismételd, amíg kész
Ha nagyon bonyolult lett, visszaléphetsz: git rebase --abort – és próbálod máshogy (pl. git merge main-t, ami egyben rendezi).
3. példa – conflict, amit nem értesz
Szituáció: Megnyitod a conflict-os fájlt, de fogalmad sincs, mit csinál az a kódrészlet. Mindkét verzió ismeretlen területen van.
Amit NE tegyél: Ne válaszd ki „ösztönösen" az egyiket és reméld, hogy jó lesz.
Amit tegyél:
- Nézd meg a
git logalapján, ki írta az ütköző sorokat - Írd meg nekik: „Merge conflict van az X fájlban, nem vagyok biztos a feloldásban, ránéznél?"
- Ha sürgős és nem elérhető, válaszd a konzervatívabb megközelítést (a meglévő, tesztelt verziót) és dokumentáld, hogy újra kell nézni
Ez nem gyengeség – ez professzionális hozzáállás.
4. példa – conflict miután „csak egy sort módosítottál"
Szituáció: Egy apró bugfixet csináltál – egy sort módosítottál. Mégis conflict van, mert a main-en ugyanaz a sor megváltozott.
Ez a leggyakoribb eset. Ilyenkor egyszerű:
- Értsd meg, miért módosult a main-en az a sor
- Integráld a bugfixedet az új kontextusba
- Teszteld, hogy mindkét változtatás érvényes-e
Tesztfeladatok
1. feladat – Conflict marker felismerése
Az alábbi kódrészletben merge conflict van. Azonosítsd:
- Melyik rész a te branch-ed verziója?
- Melyik a bemergelni kívánt branch verziója?
- Mi a branch neve, amiből mergelsz?
<<<<<<< HEAD
const MAX_RETRY = 3;
=======
const MAX_RETRY = 5;
>>>>>>> fix/increase-retry-limit
Helyes válasz:
- Te branch-ed:
const MAX_RETRY = 3; - Bemergelni kívánt:
const MAX_RETRY = 5; - Forrás branch neve:
fix/increase-retry-limit
2. feladat – Lépések sorrendbe állítása
Sorold helyes sorrendbe az alábbi lépéseket merge conflict feloldásakor:
A) git commit
B) A conflict markerek eltávolítása és a helyes tartalom megőrzése
C) git status futtatása a conflict-os fájlok azonosítására
D) git add <fájlnév>
E) Az érintett fájl megnyitása szerkesztőben
F) Tesztek futtatása
Helyes sorrend: C → E → B → F → D → A
3. feladat – Igaz vagy hamis?
Döntsd el, melyik állítás igaz és melyik hamis:
a) A merge conflict mindig azt jelenti, hogy valaki hibázott.
b) A git merge --abort visszavonja a merge folyamatot és visszaállítja az eredeti állapotot.
c) Conflict feloldása után nem kell tesztelni, ha a szintaxis helyes.
d) A ======= jel felett mindig a te módosításod látható (HEAD).
e) Ha nem érted a conflict-os kódot, az egyiket kell választani ösztönösen.
Válaszok:
- a) Hamis – conflict természetes velejárója az együttműködésnek
- b) Igaz
- c) Hamis – szintaktikailag helyes kód logikailag még hibás lehet
- d) Igaz
- e) Hamis – ilyenkor kérj segítséget a szerzőtől
4. feladat – Szimulált conflict feloldása
Az alábbi conflict-os kódrészletet kell feloldanod. A kontextus: egy API endpoint rate limiting értékét módosítottátok ketten. A te branch-eden 100-ra állítottad (forgalmi terhelés teszteléshez), a main-en a csapat 50-re változtatta (production limit). A feature branch-et mergeled main-be, és production-ba megy.
<<<<<<< HEAD
RATE_LIMIT_PER_MINUTE = 100
=======
RATE_LIMIT_PER_MINUTE = 50
>>>>>>> main
Kérdés: Melyik értéket tartanád meg és miért?
Várt válasz: A 50-et, mert ez a production limit, amit a csapat szándékosan állított be. A 100 tesztelési célra volt, production-ba nem kerülhet. Ha a tesztelési értéket meg akarod tartani, tedd environment változóba, ne hardcode-old.
5. feladat – Proaktív stratégia
Melyik az a szokás, ami a leghatékonyabban csökkenti a merge conflict-ok számát?
A) Mindig squash-olni a commit-okat push előtt
B) Rendszeresen szinkronizálni a feature branch-et a main-nel
C) Soha nem dolgozni ugyanazon a fájlon mint a kolléga
D) Conflict esetén mindig a saját verziót megtartani
Helyes válasz: B – A rendszeres szinkronizálás (git pull --rebase origin main) csökkenti az eltérések felhalmozódását, így kisebb és kezelhetőbb conflict-ok keletkeznek.
6. feladat – Mit tegyél, ha…?
Minden szituációhoz válaszd ki a helyes reakciót:
Szituáció 1: Conflict-ot oldasz fel, és a kód szintaktikailag hibás, mert bennmaradt egy <<<<<<< marker.
→ A) Commitolod és reméled, hogy senki nem veszi észre
→ B) Keresed a bennmaradt markert, törlöd és újra ellenőrzöd a fájlt
Szituáció 2: Conflict van, de nem érted, mit csinál az érintett kódrészlet.
→ A) Kiválasztod az egyiket véletlenszerűen
→ B) Megnézed a git log-ot, ki írta, és megkérdezed
Szituáció 3: Rebase közben 8 commitnál is conflict keletkezik.
→ A) git rebase --abort, majd git merge helyett
→ B) Egyesével feloldod mind a 8-at
Válaszok: 1→B, 2→B, 3→mindkettő elfogadható (a --abort és merge váltás praktikus opció, de az egyesével feloldás is működik)
7. feladat – Fogalmak párosítása
Párosítsd össze a Git parancsokat a hatásukkal:
| Parancs | Hatás |
|---|---|
git merge --abort | A) Folytatja a rebase-t conflict feloldása után |
git add <fájl> | B) Visszavonja a merge folyamatot, visszaáll az eredeti állapot |
git rebase --continue | C) Megmutatja a conflict-os fájlokat |
git status | D) Megjelöli a fájlt feloldottként |
Válaszok: merge --abort → B, git add → D, rebase --continue → A, git status → C
8. feladat – Elemzés
Az alábbi conflict feloldásban mi a hiba?
Eredeti conflict:
<<<<<<< HEAD
function getUser(id) {
return db.query("SELECT * FROM users WHERE id = " + id);
}
=======
function getUser(id) {
return db.query("SELECT * FROM users WHERE id = ?", [id]);
}
>>>>>>> security/sql-injection-fix
Megoldás, amit egy junior adott:
function getUser(id) {
return db.query("SELECT * FROM users WHERE id = " + id);
}
Mi a probléma?
Várt válasz: A junior a saját (HEAD) verzióját tartotta meg, ami SQL injection sérülékenységet tartalmaz. A security/sql-injection-fix branch-en lévő paraméteres lekérdezés (?, [id]) a biztonságos megoldás. Conflict feloldásakor a tartalom jelentőségét is érteni kell, nem csak szintaktikailag kell dönteni.
9. feladat – Gondolkodj hangosan
Leírtál egy új funkciót egy feature branch-en, közben a main-en is volt változás ugyanazon a fájlban. Mergeled a main-t, és conflict keletkezik egy 40 soros függvényen belül.
Írd le lépésről lépésre, mit csinálsz a conflicttól a sikeres mergig. (Nincs egyetlen helyes válasz – a gondolkodásmód számít.)
Mintaválasz:
git status– megnézem, hány fájlban van conflict- Megnyitom a fájlt editorban – VS Code megmutatja vizuálisan mindkét verziót
- Megnézem a git log-ban, mit változtatott a main-en az a rész és miért
- Ha értem a változtatás okát, kombináltom a két verziót (ha szükséges) vagy megtartom a helyeset
- Ha nem értem, megkérdezem a szerzőt mielőtt döntök
- Törlöm az összes marker maradványt
git adda feloldott fájlra- Lefuttatom a teszteket
- Ha minden OK,
git commit - Pusholom a branch-et
10. feladat – Összefoglalás
Melyik állítás írja le legjobban a merge conflict-ot?
A) Hiba, amit el kell kerülni jobb kódírással
B) A Git jelzése, hogy két változtatás ugyanazon a helyen ütközik, és emberi döntést igényel
C) Biztonsági figyelmeztetés, hogy valaki módosítani próbálta a kódodat
D) Automatikusan feloldható probléma, amit a Git általában meg tud csinálni helyetted
Helyes válasz: B – A merge conflict nem hiba, hanem jelzés: két párhuzamos változtatás ütközött, és a döntést a Git nem tudja meghozni helyetted. Ez normális része az együttműködésnek.