Merge — este operația de îmbinare a ramurilor în Git, care combină modificările din două linii de dezvoltare diferite într-o singură ramură țintă. Spre deosebire de rebase, merge păstrează istoricul complet al ramificării, creând un commit de merge special cu doi părinți. Conform documentației oficiale Git (2026), merge este cea mai sigură modalitate de a îmbina ramurile, deoarece nu suprascrie istoricul și permite urmărirea când și care ramuri au fost îmbinate. Este alegerea standard pentru îmbinarea în ramurile publice, cum ar fi main, develop și release.
Principalele puncte
Merge — este comanda git merge care combină modificările din ramura specificată în ramura curentă. Git găsește strămoșul comun (commitul de bază comun), calculează diff-ul fiecărei ramuri față de strămoș și creează un commit de merge care conține setul combinat de modificări. Rezultatul — ramura țintă este completată cu toate modificările din ramura îmbinată.
Sintaxa: aflându-te în ramura țintă (de exemplu, main), execută git merge feature. Git creează automat un commit de merge, dacă nu există conflicte. În mesajul implicit al commitului de merge se indică: „Merge branch ’feature’ into main“. Mesajul poate fi modificat prin flag-ul -m sau editat în editorul deschis.
Merge este o operație nedistructivă. Spre deosebire de rebase, merge nu atinge commiturile existente: ele rămân cu aceleași hashuri, autori și date. Acest lucru face din merge singura modalitate sigură de îmbinare pentru ramurile la care lucrează simultan mai mulți dezvoltatori. Dacă ceva merge greșit, merge poate fi anulat cu comanda git merge --abort.
# Comută la ramura țintă
git checkout main
# Îmbină ramura de feature
git merge feature
# Rezultat — commit de merge cu doi părinți
git log --oneline --graph
# Îmbină cu mesaj personalizat
git merge feature -m "feat: integrate authentication module"
Git suportă trei moduri de îmbinare, care se aleg în funcție de rezultatul dorit. Regular merge (implicit) creează un commit de merge. Squash merge combină toate commiturile ramurii de feature într-unul singur. Fast-forward — mută indicatorul ramurii fără a crea un commit, dacă este posibil. Alegerea modului depinde de workflow-ul echipei și regulile de istoric.
Regular merge (--no-ff) — creează un commit de merge chiar dacă îmbinarea poate fi efectuată ca fast-forward. Recomandat pentru ramura main: commitul de merge marchează explicit momentul integrării feature-ului și permite revenirea ușoară a tuturor modificărilor ramurii de feature printr-un singur revert al commitului de merge. GitHub folosește acest mod implicit la îmbinarea PR prin butonul Merge.
Squash merge (--squash) — colectează toate commiturile ramurii de feature într-un singur commit în ramura țintă. Util atunci când istoricul provizoriu al ramurii de feature nu trebuie să ajungă în main. Dezavantaj: se pierde legătura cu commiturile originale — nu se poate vedea cum feature-ul a fost dezvoltat pas cu pas. GitHub folosește acest mod la alegerea „Squash and merge“ în PR.
Fast-forward (--ff) — dacă ramura țintă nu are commituri noi după ramificarea feature-ului, Git pur și simplu mută indicatorul înainte, fără a crea un commit de merge. Istoricul rămâne liniar. Flag-ul --no-ff forțează crearea unui commit de merge, --ff-only se va încheia cu eroare dacă fast-forward nu este posibil.
# Forțează commit de merge (recomandat pentru main)
git merge --no-ff feature
# Squash merge — toate commiturile într-unul
git merge --squash feature
git commit -m "feat: add authentication"
# Fast-forward numai dacă este posibil
git merge --ff-only feature
# Anulează îmbinarea cu conflict
git merge --abort
Strategiile de îmbinare determină algoritmul pe care Git îl folosește pentru a combina modificările. Fiecare strategie este potrivită pentru diferite scenarii. Git alege automat strategia potrivită, dar dezvoltatorul o poate indica explicit prin flag-ul --strategy. Înțelegerea strategiilor ajută la prezicerea comportamentului Git la îmbinări complexe.
Recursive — strategia implicită pentru îmbinarea a două ramuri. Git găsește strămoșul comun, calculează modificările în fiecare ramură și le combină. Dacă strămoșul comun este găsit, recursive gestionează corect redenumirea fișierelor și adăugarea de fișiere noi. La conflicte, recursive poate folosi opțiuni suplimentare: ours (selectează automat versiunea noastră) și theirs (selectează versiunea lor).
Octopus — pentru îmbinarea simultană a mai mult de două ramuri: git merge feature1 feature2 feature3. Octopus nu suportă rezolvarea conflictelor — toate conflictele trebuie rezolvate înainte de apelarea comenzii. Folosit rar, în principal pentru combinarea mai multor ramuri independente care garantat nu intră în conflict (de exemplu, module diferite).
| Strategie | Număr de ramuri | Rezolvarea conflictelor |
|---|---|---|
| Recursive | 2 | Automată + opțiuni ours/theirs |
| Octopus | 3+ | Nu — toate conflictele trebuie rezolvate în prealabil |
| Ours | Oricât | Alege întotdeauna versiunea noastră, modificările străine sunt ignorate |
| Subtree | 2 | Pentru îmbinarea subarborilor (subtree merge) |
Ours — o strategie specială care ignoră complet modificările din ramura îmbinată și păstrează conținutul curent al ramurii țintă. Commitul de merge se creează, dar conținutul rămâne neschimbat. Utilă atunci când trebuie să fixezi în istoric faptul îmbinării, dar practic să respingi toate modificările din ramura străină.
Conflictul de merge apare atunci când aceleași rânduri ale unui fișier au fost modificate diferit în ambele ramuri. Git nu poate determina automat care versiune este corectă și suspendă merge-ul. Conflictul poate apărea și la redenumirea unui fișier într-o ramură și modificarea lui în cealaltă, sau la ștergerea și modificarea simultană a aceluiași fișier.
Procesul de rezolvare: Git marchează fișierele cu conflict cu markeri. În fișier apar secțiuni cu <<<<<<< HEAD (versiunea noastră), ======= (separator) și >>>>>>> feature (versiunea lor). Dezvoltatorul editează manual secțiunea conflictuală, selectând rândurile necesare din ambele versiuni, elimină markerii, salvează fișierul și îl adaugă în index prin git add.
Pentru rezolvarea vizuală a conflictelor, Git suportă mergetool — un instrument extern de comparare. Instrumente mergetool populare: Meld, KDiff3, Beyond Compare, VS Code (editor de conflicte încorporat). Mergetool afișează trei panouri: versiunea noastră, versiunea lor și rezultatul. Dezvoltatorul selectează vizual blocurile de cod pentru includerea în fișierul final.
# Începe îmbinarea și detectează conflictul
git merge feature
# CONFLICT (conținut): Conflict de îmbinare în src/main.swift
# Verifică fișierele cu conflict
git status
# Deschide instrumentul vizual de îmbinare
git mergetool
# După rezolvare — adaugă și commit
git add src/main.swift
git commit
# Anulează îmbinarea
git merge --abort
Merge este preferat în loc de rebase în câteva situații cheie. Prima: la lucrul cu ramuri publice accesibile altor dezvoltatori. Merge nu suprascrie istoricul, iar colegii se pot sincroniza în siguranță. Rebase într-o ramură publică va crea un istoric divergent și conflicte pentru toți cei care au primit deja commiturile vechi.
A doua situație: la finalizarea ramurii de feature. Majoritatea echipelor preferă merge (cu flag-ul --no-ff) în main pentru a fixa momentul integrării feature-ului. Aceasta simplifică navigarea prin istoric și permite revenirea ușoară a întregului feature printr-un singur git revert al commitului de merge. GitHub Flow oferă implicit trei opțiuni de merge: merge simplu, squash merge și rebase merge.
A treia situație: la lucrul cu un pull request care a trecut prin review. GitHub și GitLab oferă butonul de merge cu diferite opțiuni. Merge (Create a merge commit) — istoric complet cu commit de merge. Squash and merge — istoric curat fără detalii de dezvoltare. Rebase and merge — istoric liniar fără commit de merge, dar cu suprascrierea commiturilor. Alegerea depinde de regulile echipei.
Prima regulă: fii întotdeauna pe versiunea actualizată a ramurii țintă înainte de merge. Execută git checkout main && git pull înainte de a îmbina feature-ul. Aceasta minimizează conflictele și garantează că commitul de merge va conține toate modificările actualizate. Dacă ramura țintă a avansat semnificativ, execută mai întâi git merge main în interiorul ramurii de feature pentru a rezolva conflictele în contextul ei.
A doua regulă: testează codul după merge. Merge poate modifica comportamentul, chiar dacă nu au fost conflicte. Pipeline-ul CI/CD trebuie să ruleze testele pe commitul de merge înainte de trimiterea în producție. Unele echipe folosesc merge gates — verificări obligatorii care blochează merge până la trecerea lor.
A treia regulă: documentează commiturile de merge. Mesajul standard „Merge branch ’feature’ into main“ este puțin util. Se recomandă adăugarea descrierii a ceea ce a fost îmbinat: „Merge authentication module: login, registration, password recovery“. Aceasta simplifică analiza istoricului și căutarea regresiunilor. În proiecte mari, commiturile de merge sunt generate automat din numele PR.
Întrebări frecvente
A îmbina (merge) — a executa git merge pentru a combina modificări dintr-o ramură în alta. Rezultatul este un commit de merge care fixează faptul îmbinării și conține modificări din ambele ramuri. Este modul principal de integrare a ramurilor de feature în main, develop sau release în Git Flow.
Squash merge combină toate commiturile ramurii de feature într-un singur commit în ramura țintă, pierzând istoricul intermediar al dezvoltării. Merge-ul obișnuit creează un commit de merge, păstrând toate commiturile ramurii de feature. Squash merge oferă un istoric curat, dar nu permite urmărirea dezvoltării pas cu pas a feature-ului.
Deschide fișierul cu conflict, găsește secțiunile cu markerii <<<<<<< HEAD și >>>>>>>. Editează conținutul, păstrând rândurile necesare din ambele versiuni, elimină markerii. Salvează fișierul, execută git add și git commit. Poți folosi git mergetool pentru rezolvare vizuală.
Merge este folosit întotdeauna pentru ramurile publice (main, develop, release), deoarece nu suprascrie istoricul. Rebase se aplică în ramurile de feature personale înainte de publicarea lor. După ce ramura a devenit parte a depozitului comun și colegii s-au referit la ea, este permis doar merge.
Înainte de finalizarea merge-ului (în timpul conflictului) — git merge --abort anulează îmbinarea complet. După finalizare — git revert <merge-commit-hash> -m 1 creează un commit de revenire. Flag-ul -m 1 indică ce ramură părinte să se păstreze (ținta). Git revert este mai sigur decât git reset pentru ramurile publicate.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și