Merge — что это такое, типы слияния и механизм работы

Автор: IT Sectr Опубликовано: 2026-05-10 Время чтения: 10 мин

Merge — это операция в Git, которая объединяет изменения из одной ветки в другую, создавая коммит слияния (commit merge). 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 фиксирует факт слияния, содержит ссылки на обе ветки и упрощает понимание истории. Для личных или экспериментальных веток допустим 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 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

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