Merge — este o operațiune în Git care combină modificările dintr-o ramură în alta, creând un commit de îmbinare (merge commit). Git suportă mai multe strategii: fast-forward (istorie liniară), three-way merge (cu crearea unui merge commit) și squash merge (comprimarea tuturor commiturilor într-unul singur). Conform datelor git-scm.com, 2025, merge rămâne cel mai utilizat mecanism de integrare a codului în dezvoltarea în echipă cu Git.
Principalele
Merge (îmbinare) — este o operațiune fundamentală în Git care combină modificările dintr-o ramură (source) în alta (target). În urma îmbinării, ramura țintă primește toate commiturile din ramura sursă care nu erau încă prezente în ea. În funcție de situație, Git poate executa merge în trei moduri diferite.
Valoarea principală a merge-ului este păstrarea istoriei: merge commit înregistrează faptul combinării ramurilor, păstrează informația despre când și care ramuri au fost îmbinate. Acest lucru facilitează auditul modificărilor, căutarea regresiilor și înțelegerea cronologiei dezvoltării. În proiecte mari, merge commit este modul standard de integrare a codului.
Conform datelor GitLab Flow, merge commiturile sunt utilizate în 73% din echipele care lucrează cu Git. Abordările alternative (rebase, squash) sunt preferate de echipele orientate spre istoria liniară. Alegerea strategiei depinde de mărimea echipei, frecvența lansărilor și convențiile adoptate în proiect.
Merge este necesar când dezvoltatorul a terminat lucrul la o funcționalitate și dorește să o integreze în develop sau main. Scenariu tipic: dezvoltatorul a creat o ramură de funcționalitate din develop, a lucrat câteva zile, iar în acest timp în develop au apărut commituri noi de la alți participanți. Înainte de îmbinare trebuie combinate modificările — și pentru aceasta se folosește merge.
Fără merge nu se poate lucra în echipă la același cod în Git. De fiecare dată când doi dezvoltatori introduc simultan modificări în aceeași bază de cod, ramurile lor diverg. Merge — este singura modalitate de a reuni aceste modificări fără pierdere de date.
Git suportă trei tipuri de merge, fiecare destinat propriului scenariu. Alegerea tipului de îmbinare influențează istoria commiturilor, confortul revenirii și lizibilitatea logului.
Fast-forward apare când ramura țintă nu a avut commituri noi de la crearea ramurii sursă. În acest caz, Git pur și simplu mută indicatorul ramurii țintă înainte, la ultimul commit al ramurii sursă. Istoria rămâne liniară, fără merge commit.
# Fast-forward merge: develop nu s-a modificat de la crearea feature
git checkout develop
git merge feature/new-login
# Rezultat: indicatorul develop s-a mutat la sfârșitul lui feature
# Nu s-a creat niciun merge commit
Fast-forward este convenabil pentru ramurile de scurtă durată, unde dezvoltatorul a lucrat singur. Dar această abordare are un dezavantaj: se pierde informația că ramura a existat — toate commiturile par a fi făcute direct în develop.
Three-way merge se execută când ambele ramuri au commituri noi după punctul de divergență. Git creează un merge commit separat cu doi părinți, care înregistrează faptul combinării ramurilor. Această abordare este recomandată pentru ramurile de funcționalitate în dezvoltarea în echipă.
# Three-way merge forțat cu flagul --no-ff
git checkout develop
git merge --no-ff feature/new-login
# Merge commit creat cu mesajul implicit
# Se poate seta propriul mesaj prin -m
git merge --no-ff feature/new-login -m "Merge feature/new-login into develop"
Flagul --no-ff garantează crearea unui merge commit, chiar dacă fast-forward este posibil. Aceasta este cea mai bună practică pentru păstrarea informației despre ramificare în proiect.
Squash merge comprimă toate commiturile ramurii sursă într-unul singur și îl aplică ramurii țintă. Istoria funcționalității se pierde — în ramură ajunge un singur commit cu toate modificările. Este convenabil când commiturile detaliate din ramura de funcționalitate nu aduc valoare istoriei generale.
# Squash merge: toate commiturile feature au fost comprimate într-unul singur
git checkout develop
git merge --squash feature/experimental
git commit -m "feat: experimental login flow (squashed)"
Squash este potrivit pentru ciorne, ramuri experimentale și situații când este importantă păstrarea curățeniei istoriei. Minus — se pierde legătura cu commiturile originale, ceea ce complică revenirea modificărilor individuale.
Ours și Theirs — două strategii speciale de merge în Git. Ours ignoră complet modificările din ramura sursă, păstrând doar ce este în ramura țintă. Theirs, dimpotrivă, acceptă versiunea ramurii sursă la orice conflict. Aceste strategii sunt utile la îmbinarea unor volume mari de cod, când se știe dinainte care versiune trebuie să câștige.
Mecanismul merge în Git se bazează pe compararea a trei puncte: strămoșul comun (merge base), starea ramurii sursă și starea ramurii țintă. Git găsește merge base — ultimul commit comun pentru ambele ramuri — și calculează ce modificări au avut loc în fiecare ramură după divergență.
Git folosește algoritmul trilateral de îmbinare, care ia în considerare nu doar cele două versiuni comparate ale fișierului, ci și strămoșul lor comun. Datorită acestui fapt, Git poate rezolva automat situațiile în care modificările dintr-o ramură nu afectează părțile modificate ale celeilalte — chiar dacă ambele fișiere au fost modificate.
Să considerăm scenariul: doi dezvoltatori lucrează la fișiere diferite în aceeași ramură de funcționalitate. Primul a modificat LoginActivity.kt, al doilea — ProfileFragment.kt. Când își îmbină modificările, Git vede că modificările au afectat fișiere diferite și execută merge automat, fără intervenția umană.
Dacă ambii dezvoltatori au modificat LoginActivity.kt, dar în metode diferite — Git se va descurca și el automat, combinând modificările rând cu rând. Conflictul apare doar dacă ambii au modificat aceleași rânduri sau dacă unul a șters codul pe care celălalt l-a modificat.
Conflictul de merge apare când Git nu poate combina automat modificările, deoarece ambele ramuri au modificat aceleași rânduri în mod diferit. În acest caz, Git marchează porțiunile conflictuale în fișiere și așteaptă rezolvarea manuală de către dezvoltator.
Porțiunile conflictuale sunt marcate cu markeri speciali: <<<<<<< HEAD arată codul din ramura țintă, ======= — separatorul, >>>>>>> source-branch — codul din ramura sursă. Dezvoltatorul trebuie să aleagă manual ce variantă să păstreze sau să le combine.
# 1. Porniți merge și vedeți conflictul
git merge feature/new-login
# Rezultat: CONFLICT (content): Merge conflict in LoginActivity.kt
# 2. Vizualizați lista fișierelor cu conflicte
git status
# both modified: src/ui/login/LoginActivity.kt
# 3. Rezolvați conflictul: editați fișierul, eliminați markerii
# 4. Adăugați fișierul rezolvat și finalizați merge
git add src/ui/login/LoginActivity.kt
git merge --continue
# sau: git commit (fără --continue)
Pentru rezolvarea conflictelor există instrumente: git mergetool deschide un merger vizual (Meld, Beyond Compare, VS Code). Mulți dezvoltatori preferă să rezolve conflictele în IDE — IntelliJ IDEA și Android Studio oferă un instrument încorporat cu comparație pe trei panouri, care simplifică semnificativ acest proces.
Sfaturi pentru rezolvarea conflictelor: înțelegeți întotdeauna ce face fiecare parte a conflictului, nu ștergeți codul altcuiva fără a înțelege logica lui, iar dacă conflictul este prea complex — implicați autorul ambelor ramuri la rezolvarea comună.
Alegerea între Merge și Rebase — una dintre cele mai frecvente decizii arhitecturale în Git. Ambele abordări combină modificările, dar o fac diferit: merge păstrează istoria ramificării, rebase rescrie istoria, făcând-o liniară.
Multe echipe folosesc abordarea hibridă: rebase pentru a aduce ramura de funcționalitate la starea actuală a develop (git rebase develop), apoi merge cu flagul --no-ff pentru fixarea îmbinării. Aceasta oferă o istorie curată în interiorul funcționalității și puncte de îmbinare informative la nivelul develop.
Întrebări frecvente
Fără --no-ff Git execută fast-forward merge, dacă este posibil — pur și simplu mută indicatorul ramurii. Cu --no-ff Git creează întotdeauna un merge commit, păstrând informația despre ramificare. Recomandat pentru ramurile de funcționalitate în dezvoltarea în echipă.
Folosiți git mergetool sau instrumentul încorporat al IDE-ului. Dacă conflictul implică zeci de fișiere — probabil ramurile s-au îndepărtat prea mult. În acest caz, merită să discutați cu echipa planul de îmbinare, poate să îl împărțiți în mai multe etape.
Da: git merge --abort anulează merge-ul dacă nu este încă finalizat (conflict). Dacă merge-ul este deja finalizat — folosiți git reset --hard HEAD~1 sau git revert -m 1 <merge-commit> pentru o revenire sigură.
Recomandat pentru lucrul în echipă. Merge commit înregistrează faptul îmbinării, conține referințe la ambele ramuri și simplifică înțelegerea istoriei. Pentru ramurile personale sau experimentale, squash merge sau fast-forward sunt acceptabile.
Git nu poate îmbina automat fișierele binare — selectează una dintre versiuni integral. Pentru fișierele binare (imagini, .aab, .apk) se recomandă minimizarea modificărilor paralele și utilizarea Git LFS pentru fișiere mari.
Concluzii
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