Merge și conflicte
Lectură estimată: 4 minute
Estimare pentru text, la un ritm de 180 de cuvinte pe minut. Timpul pentru analizarea codului, exerciții și proiecte se adaugă separat și depinde de ritmul tău.
Ai lucrat pe un branch, ai terminat. Acum trebuie să aduci munca înapoi în main. Operațiunea se numește merge, iar frica de ea vine dintr-un singur cuvânt: conflict.
Vestea bună: un conflict nu este o eroare și nu ai stricat nimic. Este doar Git care spune, corect: „aici doi oameni au schimbat aceeași linie, nu am de unde să știu care versiune e bună — decide tu".
Merge simplu
git switch main
git pull
git merge feature/pagina-contact
Dacă în main nu s-a întâmplat nimic între timp, Git face un fast-forward: mută pur și simplu indicatorul main înainte, pentru că nu e nimic de combinat.
Înainte: A---B---C (main)
\
D---E (feature)
După: A---B---C---D---E (main, feature)
Dacă între timp au apărut commit-uri și pe main, Git creează un merge commit, un commit cu doi părinți:
A---B---C---F---M (main)
\ /
D---E (feature)
Anatomia unui conflict
Conflictul apare doar când aceeași porțiune din același fișier a fost modificată în ambele părți. Dacă tu ai lucrat în header.php și colegul în footer.php, Git combină fără să te întrebe nimic.
Când apare, Git îți spune clar:
Auto-merging resources/views/contact.blade.php
CONFLICT (content): Merge conflict in resources/views/contact.blade.php
Automatic merge failed; fix conflicts and then commit the result.
Deschizi fișierul și găsești marcajele:
<<<<<<< HEAD
<h1>Contact</h1>
<p>Scrie-ne la contact@exemplu.ro</p>
=======
<h1>Ia legătura cu noi</h1>
<p>Telefon: 0700 000 000</p>
>>>>>>> feature/pagina-contact
- între
<<<<<<< HEADși=======e versiunea din branch-ul în care faci merge (de regulămain); - între
=======și>>>>>>>e versiunea care vine.
Cum rezolvi
Rezolvarea înseamnă să editezi fișierul până arată cum trebuie și să ștergi complet marcajele. Rezultatul poate fi una dintre versiuni, sau o combinație:
<h1>Ia legătura cu noi</h1>
<p>Scrie-ne la contact@exemplu.ro</p>
<p>Telefon: 0700 000 000</p>
Apoi marchezi fișierul ca rezolvat și finalizezi:
git add resources/views/contact.blade.php
git status # vezi dacă mai sunt fișiere în conflict
git commit # mesajul de merge e precompletat
Dacă te-ai încurcat și vrei să o iei de la capăt:
git merge --abort
Comanda te întoarce exact în starea de dinaintea merge-ului. E plasa ta de siguranță; folosește-o fără ezitare.
Greșeala numărul unu
Cea mai frecventă greșeală la conflicte este să uiți marcajele în fișier. Codul ajunge în producție cu <<<<<<< HEAD în el și pagina se rupe.
Verificare rapidă înainte de commit:
git diff --check
grep -rn "<<<<<<<" .
Unelte care te ajută
Nu trebuie să rezolvi conflictele în text brut. VS Code afișează butoane „Accept Current / Accept Incoming / Accept Both" direct în fișier. Există și:
git mergetool # deschide unealta configurată
git checkout --ours fisier.txt # păstrează versiunea din branch-ul curent
git checkout --theirs fisier.txt # păstrează versiunea care vine
Atenție la --ours / --theirs: aruncă complet cealaltă variantă. Sunt utile pentru fișiere generate (de exemplu un build), nu pentru cod scris de oameni.
Cum eviți conflictele mari
Conflictele nu se rezolvă cu comenzi mai deștepte, ci cu obiceiuri mai bune:
- Branch-uri scurte. Un branch care trăiește trei săptămâni garantează durere. Unul de două zile, aproape niciodată.
- Sincronizează des. Adu
mainîn branch-ul tău periodic, nu doar la final. - Împarte munca pe fișiere diferite, când e posibil.
- Nu reformata fișiere întregi în commit-uri care conțin și logică. Un „prettier pe tot proiectul" transformă orice merge într-un coșmar.
# în branch-ul tău, periodic:
git fetch origin
git merge origin/main
Conflicte în fișiere care nu sunt cod
Există două categorii de fișiere care produc conflicte urâte și pe care merită să le tratezi separat.
Fișierele de dependențe (package-lock.json, composer.lock) nu se rezolvă editând manual. Iei versiunea de pe main și regenerezi:
git checkout --theirs package-lock.json
npm install
git add package-lock.json
Migrările de bază de date nu produc conflict de text, dar produc conflict de realitate: doi colegi creează migrări cu aceeași tabelă sau modifică aceeași coloană. Git le va combina fără să se plângă, iar problema apare abia la rulare. Verifică întotdeauna ce migrări noi vin odată cu merge-ul:
git diff main --stat -- database/migrations
Ce faci când merge-ul aduce ceva stricat
Se întâmplă: ai făcut merge, ai împins, iar pe main ceva nu mai merge. Dacă merge-ul e deja public, nu rescrii istoricul, ci îl anulezi ca pe orice commit — cu o mențiune importantă, pentru că un merge commit are doi părinți și Git trebuie să știe la care dintre ei să se întoarcă:
git revert -m 1 <hash-ul-merge-commit-ului>
-m 1 înseamnă „păstrează linia principală", adică branch-ul în care ai integrat (de obicei main). Reține că, după un astfel de revert, dacă vrei să reintegrezi mai târziu același branch, va trebui să anulezi întâi revert-ul — altfel Git consideră că modificările au fost deja aduse.
Exercițiu (provoacă un conflict intenționat)
- Pe
main, modifică prima linie din README și commite. - Creează
feature/titlupornind de la commit-ul anterior, modifică aceeași linie diferit și commite. - Fă merge în
mainși rezolvă conflictul păstrând o combinație a celor două variante. - Repetă, dar de data asta folosește
git merge --abortca să te întorci.
Aplicație practică
Sarcina
Produce un conflict controlat în același rând din README.
Rezolvare orientativă și verificare
Citește ambele variante, rezolvă sensul, elimină marker-ele și rulează verificarea proiectului.
Greșeală de evitat
Acceptarea automată a unei părți poate pierde modificări necesare.
Documentație și surse
- Pro Git — Git
Verifică-ți înțelegerea
4 întrebări · îți trebuie 70% ca să promovezi și ca lecția să fie marcată parcursă.
Autentifică-te ca să rezolvi testul și să-ți salvezi progresul.