Змержити або вмержити — це дія зі злиття двох гілок у Git, що об’єднує зміни з однієї гілки в іншу. У сучасній розробці мерж — стандартний спосіб інтеграції feature-гілки в основну гілку проекту. За даними GitHub Octoverse 2024, щоденно виконується понад 15 мільйонів мержів. Merge — ключовий механізм колаборативної роботи, що дозволяє об’єднувати працю кількох розробників у єдиний продукт.
Головне
Merge у Git — це операція об’єднання двох або більше історій розробки в одну. Коли розробник змерджує гілку, Git автоматично знаходить спільного предка (base commit) і створює новий коміт злиття, що включає зміни з обох гілок. Three-way merge — стандартний алгоритм, що порівнює три стани: спільний предок, перша гілка та друга гілка.
Процес мержу починається з команди git merge. Git визначає точку розходження гілок і послідовно застосовує зміни з вихідної гілки поверх цільової. Якщо зміни не конфліктують, Git виконує fast-forward або створює merge commit залежно від налаштувань. Fast-forward — сценарій, при якому цільова гілка просто переміщується на коміти вихідної.
# Переключитися на цільову гілку і змержити
git checkout main
git merge feature/payment-module
# Змержити з явним no-fast-forward
git merge --no-ff feature/payment-module
# Скасувати мерж, якщо конфлікти надто складні
git merge --abort
Прапорець --no-ff (no fast-forward) примусово створює merge commit навіть при можливості fast-forward. Це зберігає інформацію про те, що зміни були зроблені в окремій гілці. Багато команд віддають перевагу саме такому підходу для збереження розгалуження історії в явному вигляді.
У Git існують три основні стратегії злиття гілок, кожна з яких підходить для певного сценарію. Вибір стратегії залежить від культури команди та вимог до чистоти історії проекту.
| Стратегія | Результат | Коли застосовувати |
|---|---|---|
| Standard merge | merge commit + вся історія | команди, що цінують повну історію |
| Squash merge | один коміт, історія стиснута | feature-гілки з безліччю дрібних комітів |
| Rebase merge | лінійна історія, без merge commit | особисті feature-гілки, до створення PR |
Standard merge створює merge commit із двома батьками. Повна історія зберігається, але граф розгалуження ускладнюється. Squash merge об’єднує всі коміти feature-гілки в один і застосовує його поверх цільової гілки — історія стає лінійною та чистою, але втрачається інформація про проміжні етапи.
Rebase, хоч і не є повноцінним мержем, досягає того ж результату — зміни однієї гілки переносяться поверх іншої. Різниця в тому, що історія переписується: коміти feature-гілки створюються заново поверх останнього коміту цільової гілки. Це дає ідеально лінійну історію, але вимагає force push при відправці.
Конфлікт при мержі виникає, коли в двох гілках змінено одні й ті ж рядки файлу. Git не може автоматично визначити, який варіант зберегти, і вимагає втручання розробника. Конфлікти відображаються у файлах у вигляді спеціальних маркерів: <<<<<<<, =======, >>>>>>>.
Процес вирішення конфлікту включає кілька кроків. Спочатку розробник відкриває конфліктуючий файл і вручну вибирає потрібні зміни. Важливо не просто вибрати одну з версій, а зрозуміти логіку обох змін і прийняти коректне рішення. Після редагування файлу маркери конфлікту видаляються, і зміни додаються до staging area через git add.
# Переглянути список конфліктуючих файлів
git status
# Запустити mergetool (наприклад, VS Code, IntelliJ)
git mergetool
# Після вирішення всіх конфліктів
git add .
git merge --continue
# Або скасувати мерж повністю
git merge --abort
Використання візуальних merge tools значно прискорює вирішення конфліктів. VS Code, IntelliJ IDEA та GitKraken надають інтерфейси з трьома панелями: поточна гілка, вхідна гілка та результат. Інструмент git mergetool автоматично відкриває налаштований редактор для кожного конфліктуючого файлу.
Найкращий спосіб уникнути складних конфліктів — регулярна синхронізація feature-гілки з основною. Якщо розробник змерджує main у свою гілку раз на день, конфлікти будуть невеликими та легко вирішуваними. Накопичення змін протягом тижня гарантує складні конфлікти з високим ризиком помилок.
Rebase та merge — два способи об’єднання змін, і вибір між ними часто викликає суперечки в командах. Rebase переносить коміти з однієї гілки поверх іншої, переписуючи історію. Merge створює новий коміт злиття, зберігаючи історію розгалуження. Кожен підхід має свої переваги та обмеження.
Rebase доречний, коли розробник працює у своїй локальній feature-гілці та хоче отримати чисту лінійну історію перед створенням Pull Request. Після rebase всі коміти вибудовуються послідовно, без зайвих merge commit. Однак rebase вимагає force push і незастосовний до гілок, у яких працюють кілька людей одночасно.
Золоте правило Git: не використовуй rebase на комітах, які вже були відправлені в спільний репозиторій. Це гарантує, що історія в спільній гілці залишається незмінною, та інші розробники не зіткнуться з дубльованими або втраченими комітами. Для інтеграції feature-гілки в основну використовуй merge через Pull Request.
Правильний процес мержу — основа стабільної розробки. У сучасній командній роботі мерж виконується не через консоль, а через Pull Request на GitHub або Merge Request у GitLab. PR проходить код-рев’ю, автоматичні перевірки CI та лише після цього мержиться в основну гілку.
Перша практика — мержити тільки після проходження всіх перевірок. CI-пайплайн має зібрати проект, запустити тести та перевірити якість коду. Якщо хоча б одна перевірка не пройшла, мерж блокується. Сучасні платформи (GitHub, GitLab) мають вбудований захист: branch protection rules автоматично блокують мерж при падінні CI.
Друга практика — ніколи не мержити зламаний код. Перед мержем розробник має переконатися, що його зміни не ламають білд і не регресують існуючу функціональність. Для цього існують автоматичні тести та code review.
Третя практика — чистити feature-гілки після мержу. Гілка, яка вже змерджена, має бути видалена. Це запобігає плутанині та захаращенню репозиторію. GitHub автоматично пропонує видалити гілку після мержу PR, а налаштування репозиторію можна налаштувати на автоматичне видалення.
Поширені запитання
Мерж (merge) — злиття двох гілок Git в одну. Зміни з однієї гілки переносяться в іншу через тристороннє злиття (three-way merge). Результат фіксується в новому коміті злиття, у якого два батьківські коміти. Merge commit зберігає інформацію про те, які гілки були об’єднані.
Merge створює новий коміт злиття, зберігаючи історію розгалуження. Rebase переписує історію, переносячи коміти поверх іншої гілки без створення merge commit. Rebase дає лінійну історію, але вимагає force push. Merge безпечніший для спільних гілок, rebase кращий для особистих.
Відкрийте конфліктуючий файл, знайдіть маркери <<<<<<<, ======= та >>>>>>>, виберіть потрібні зміни та видаліть маркери. Додайте файл через git add та завершіть мерж через git merge --continue. Використовуйте git mergetool для візуального вирішення у VS Code або IntelliJ IDEA.
Pull Request (або Merge Request) обов’язковий при мержі feature-гілки в основну гілку проекту. PR проходить код-рев’ю колег та автоматичні перевірки CI. Це стандарт сучасної розробки. Прямий пуш у main-гілку заборонений у більшості проектів.
Squash merge об’єднує всі коміти feature-гілки в один перед мержем. Це дає чисту історію основної гілки без проміжних комітів-чернеток. Використовуйте squash merge, коли feature-гілка містить багато службових комітів (wip, fixes) і не потрібно зберігати всі проміжні кроки в історії.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також