Merge — що це таке, типи злиття та механізм роботи

Автор: IT Sectr Опубліковано: 2026-05-10 Час читання: 10 хв

Merge — це операція в Git, яка об'єднує зміни з однієї гілки в іншу, створюючи коміт злиття (merge commit). Git підтримує кілька стратегій: fast-forward (лінійна історія), three-way merge (зі створенням merge commit) і squash merge (стиснення всіх комітів в один). За даними git-scm.com, 2025, merge залишається найбільш використовуваним механізмом інтеграції коду в командній Git-розробці.

Головне

  • Merge — операція злиття гілок у Git зі створенням або без коміту злиття
  • Fast-forward merge — лінійне злиття без додаткового коміту, коли немає розходження
  • Three-way merge — створює merge commit при розходженні гілок
  • Squash merge — стискає всі коміти гілки в один перед злиттям
  • Конфлікти виникають при зміні одних і тих самих рядків в обох гілках

Що таке Merge?

Merge (злиття) — це фундаментальна операція в Git, яка об'єднує зміни з однієї гілки (source) в іншу (target). У результаті злиття цільова гілка отримує всі коміти з вихідної гілки, яких у ній ще не було. Залежно від ситуації, Git може виконати merge трьома різними способами.

Основна цінність merge — збереження історії: merge commit фіксує факт об'єднання гілок, зберігає інформацію про те, коли і які гілки зливались. Це полегшує аудит змін, пошук регресій та розуміння хронології розробки. У великих проектах merge commit є стандартним способом інтеграції коду.

За даними GitLab Flow, merge commits використовуються в 73% команд, які працюють з Git. Альтернативні підходи (rebase, squash) надають перевагу команди, орієнтовані на лінійну історію. Вибір стратегії залежить від розміру команди, частоти релізів та прийнятих у проекті угод.

Коли виникає Merge

Merge потрібен, коли розробник завершив роботу над фічею і хоче інтегрувати її в develop або main. Типовий сценарій: розробник створив feature-гілку від develop, попрацював у ній кілька днів, а за цей час у develop з'явилися нові коміти від інших учасників. Перед злиттям потрібно об'єднати зміни — і для цього використовується merge.

Без merge неможливо спільно працювати над одним кодом у Git. Кожного разу, коли два розробники одночасно вносять зміни в одну кодову базу, їхні гілки розходяться. Merge — єдиний спосіб звести ці зміни назад без втрати даних.

Типи злиття в Git

Git підтримує три типи merge, кожен з яких призначений для свого сценарію. Вибір типу злиття впливає на історію комітів, зручність відкату та читабельність лога.

Fast-forward merge

Fast-forward виникає, коли цільова гілка не мала нових комітів з моменту створення вихідної. У цьому випадку Git просто переміщує покажчик цільової гілки вперед, на останній коміт вихідної. Історія залишається лінійною, без merge commit.

bash
# Fast-forward merge: develop не змінювався з моменту створення feature
git checkout develop
git merge feature/new-login

# Результат: покажчик develop перемістився на кінець feature
# Жодного merge commit не створено

Fast-forward зручний для короткочасних гілок, де розробник працював наодинці. Але в цього підходу є недолік: втрачається інформація про те, що гілка існувала — всі коміти виглядають як зроблені безпосередньо в develop.

Three-way merge

Three-way merge виконується, коли обидві гілки мають нові коміти після точки розходження. Git створює окремий merge commit з двома батьками, який фіксує факт об'єднання гілок. Цей підхід рекомендується для feature-гілок у командній розробці.

bash
# Примусовий three-way merge з прапорцем --no-ff
git checkout develop
git merge --no-ff feature/new-login

# Створено merge commit з повідомленням за замовчуванням
# Можна задати своє повідомлення через -m
git merge --no-ff feature/new-login -m "Merge feature/new-login into develop"

Прапорець --no-ff гарантує створення merge commit, навіть якщо fast-forward можливий. Це найкраща практика для збереження інформації про розгалуження в проекті.

Squash merge

Squash merge стискає всі коміти вихідної гілки в один і застосовує його до цільової. Історія фічі втрачається — в гілку потрапляє один коміт з усіма змінами. Це зручно, коли детальні коміти у feature-гілці не несуть цінності для загальної історії.

bash
# Squash merge: всі коміти feature стиснуті в один
git checkout develop
git merge --squash feature/experimental
git commit -m "feat: experimental login flow (squashed)"

Squash підходить для чернеток, експериментальних гілок і ситуацій, коли важливо зберегти чистоту історії. Мінус — втрачається зв'язок з вихідними комітами, що ускладнює відкат окремих змін.

Стратегії Ours і Theirs

Ours і Theirs — дві спеціальні стратегії merge у Git. Ours повністю ігнорує зміни з вихідної гілки, залишаючи тільки те, що є в цільовій. Theirs, навпаки, приймає версію вихідної гілки при будь-якому конфлікті. Ці стратегії корисні при злитті великих обсягів коду, коли заздалегідь відомо, яка версія має перемогти.

Як працює Merge

Механізм merge у Git заснований на порівнянні трьох точок: спільного предка (merge base), стану вихідної гілки та стану цільової гілки. Git знаходить merge base — останній коміт, спільний для обох гілок — і обчислює, які зміни відбулися в кожній гілці після розходження.

  • Крок 1 — Git визначає merge base: останній коміт, який є в обох гілках
  • Крок 2 — Git будує два diff'и: від merge base до source і від merge base до target
  • Крок 3 — Git намагається застосувати обидва набори змін до merge base
  • Крок 4 — Якщо зміни не конфліктують — merge завершується автоматично
  • Крок 5 — Якщо конфлікт — Git зупиняється і запитує вирішення

Git використовує тристоронній алгоритм злиття, який враховує не тільки дві порівнювані версії файлу, але й їхнього спільного предка. Завдяки цьому Git може автоматично вирішити ситуації, коли зміни в одній гілці не зачіпають змінені ділянки іншої — навіть якщо обидва файли були модифіковані.

Алгоритм роботи merge на прикладі

Розглянемо сценарій: два розробники працюють над різними файлами в одній feature-гілці. Перший змінив LoginActivity.kt, другий — ProfileFragment.kt. Коли вони зливають свої зміни, Git бачить, що зміни торкнулися різних файлів, і виконує merge автоматично, без втручання людини.

Якщо ж обидва розробники змінили LoginActivity.kt, але в різних методах — Git також впорається автоматично, об'єднавши зміни рядково. Конфлікт виникає тільки якщо обидва змінили одні й ті самі рядки або якщо один видалив код, який інший змінив.

Вирішення конфліктів при Merge

Конфлікт merge виникає, коли Git не може автоматично об'єднати зміни, тому що обидві гілки модифікували одні й ті самі рядки по-різному. У цьому випадку Git позначає конфліктні ділянки у файлах і чекає ручного вирішення від розробника.

Конфліктні ділянки розмічаються спеціальними маркерами: <<<<<<< HEAD показує код із цільової гілки, ======= — роздільник, >>>>>>> source-branch — код із вихідної гілки. Розробник повинен вручну вибрати, який варіант залишити, або об'єднати їх.

bash
# 1. Запустити merge і побачити конфлікт
git merge feature/new-login
# Вивід: CONFLICT (content): Merge conflict in LoginActivity.kt

# 2. Подивитися список файлів з конфліктами
git status
# both modified: src/ui/login/LoginActivity.kt

# 3. Вирішити конфлікт: відредагувати файл, прибрати маркери
# 4. Додати вирішений файл і завершити merge
git add src/ui/login/LoginActivity.kt
git merge --continue
# або: git commit (без --continue)

Для вирішення конфліктів існують інструменти: git mergetool відкриває візуальний мерджер (Meld, Beyond Compare, VS Code). Багато розробників вважають за краще вирішувати конфлікти в IDE — IntelliJ IDEA і Android Studio надають вбудований інструмент із трипанельним порівнянням, який значно спрощує цей процес.

Поради щодо вирішення конфліктів: завжди розумійте, що робить кожна сторона конфлікту, не видаляйте чужий код без розуміння його логіки, і якщо конфлікт занадто складний — залучіть авторів обох гілок до спільного вирішення.

Merge vs Rebase: коли що вибирати

Вибір між Merge і Rebase — одне з найчастіших архітектурних рішень у Git. Обидва підходи об'єднують зміни, але роблять це по-різному: merge зберігає історію розгалуження, rebase переписує історію, роблячи її лінійною.

  • Merge — зберігає контекст: видно, коли і від якої гілки робилося злиття. Краще для публічних гілок (develop, main) і командної роботи
  • Rebase — створює чисту лінійну історію без зайвих merge commit'ів. Краще для особистих feature-гілок перед відправкою на рев'ю
  • Правило: ніколи не робіть rebase публічних гілок, які використовують інші розробники

Багато команд використовують гібридний підхід: rebase для приведення feature-гілки до актуального стану develop (git rebase develop), а потім merge з прапорцем --no-ff для фіксації злиття. Це дає чисту історію всередині фічі та інформативні точки злиття на рівні develop.

Часті запитання

У чому різниця між merge і merge --no-ff?

Без --no-ff Git виконує fast-forward merge, якщо можливо — просто переміщує покажчик гілки. З --no-ff Git завжди створює merge commit, зберігаючи інформацію про розгалуження. Рекомендується для feature-гілок у командній розробці.

Що робити, якщо merge конфлікт дуже великий?

Використовуйте git mergetool або вбудований інструмент IDE. Якщо конфлікт зачіпає десятки файлів — можливо, гілки занадто сильно розійшлися. У такому випадку варто обговорити з командою план злиття, можливо — розбити його на кілька етапів.

Чи можна скасувати merge?

Так: git merge --abort скасовує merge, якщо він ще не завершений (конфлікт). Якщо merge вже завершений — використовуйте git reset --hard HEAD~1 або git revert -m 1 <merge-commit> для безпечного відкату.

Чи потрібно створювати merge commit для кожної фічі?

Рекомендується для командної роботи. Merge commit фіксує факт злиття, містить посилання на обидві гілки та спрощує розуміння історії. Для особистих або експериментальних гілок допустимий squash merge або fast-forward.

Як merge працює з бінарними файлами?

Git не може автоматично зливати бінарні файли — він вибирає одну з версій цілком. Для бінарних файлів (зображення, .aab, .apk) рекомендується мінімізувати паралельні зміни та використовувати Git LFS для великих файлів.

Підсумки

  • Merge — базова операція Git для об'єднання змін з однієї гілки в іншу
  • Fast-forward — лінійне злиття без merge commit, коли розходження немає
  • Three-way merge — створює merge commit з двома батьками, зберігає контекст
  • Squash merge — стискає всі коміти гілки в один, втрачаючи історію фічі
  • Конфлікти виникають при зміні одних і тих самих рядків і вирішуються вручну
  • Merge відрізняється від Rebase: перший зберігає розгалуження, другий робить історію лінійною
  • Для публічних гілок рекомендується merge з --no-ff, для особистих — rebase або squash

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також