Merge — это операция слияния веток в Git, которая объединяет изменения из двух разных линий разработки в одну целевую ветку. В отличие от rebase, merge сохраняет полную историю ветвления, создавая специальный merge-коммит с двумя родителями. По данным официальной документации Git (2026), merge является наиболее безопасным способом объединения веток, поскольку не перезаписывает историю и позволяет отследить, когда и какие ветки сливались. Это стандартный выбор для слияния в публичных ветках, таких как main, develop и release.
Главное
Merge — это команда git merge, которая объединяет изменения из указанной ветки в текущую. Git находит общего предка (общий базовый коммит), вычисляет diff каждой ветки относительно предка и создаёт merge-коммит, содержащий объединённый набор изменений. Результат — целевая ветка пополняется всеми изменениями из сливаемой ветки.
Синтаксис: находясь в целевой ветке (например, main), выполнить git merge feature. Git автоматически создаёт merge-коммит, если нет конфликтов. В сообщении merge-коммита по умолчанию указывается: «Merge branch 'feature' into main». Сообщение можно изменить через флаг -m или отредактировать в открывшемся редакторе.
Merge — это неразрушающая операция. В отличие от rebase, merge не трогает существующие коммиты: они остаются с теми же хешами, авторами и датами. Это делает merge единственным безопасным способом слияния для веток, с которыми одновременно работают несколько разработчиков. Если что-то пошло не так, merge можно отменить командой git merge --abort.
# Switch to target branch
git checkout main
# Merge feature branch
git merge feature
# Result — merge commit with two parents
git log --oneline --graph
# Merge with custom message
git merge feature -m "feat: integrate authentication module"
Git поддерживает три режима слияния, которые выбираются в зависимости от желаемого результата. Regular merge (по умолчанию) создаёт merge-коммит. Squash merge объединяет все коммиты feature-ветки в один. Fast-forward — перемещает указатель ветки без создания коммита, если возможно. Выбор режима зависит от workflow команды и правил истории.
Regular merge (--no-ff) — создаёт merge-коммит даже если merge можно выполнить fast-forward. Рекомендуется для main-ветки: merge-коммит явно маркирует момент интеграции фичи и позволяет легко откатить все изменения feature-ветки одним revert merge-коммита. GitHub использует этот режим по умолчанию при слиянии PR через кнопку Merge.
Squash merge (--squash) — собирает все коммиты feature-ветки в один коммит в целевой ветке. Полезен, когда черновая история feature-ветки не должна попадать в main. Недостаток: теряется связь с оригинальными коммитами — нельзя увидеть, как фича разрабатывалась пошагово. GitHub использует этот режим при выборе «Squash and merge» в PR.
Fast-forward (--ff) — если целевая ветка не имеет новых коммитов после ответвления feature, Git просто перемещает указатель вперёд, без создания merge-коммита. История остаётся линейной. Флаг --no-ff принудительно создаёт merge-коммит, --ff-only завершится ошибкой, если fast-forward невозможен.
# Force merge commit (recommended for main)
git merge --no-ff feature
# Squash merge — all commits into one
git merge --squash feature
git commit -m "feat: add authentication"
# Fast-forward only if possible
git merge --ff-only feature
# Abort conflicted merge
git merge --abort
Стратегии слияния определяют алгоритм, который Git использует для объединения изменений. Каждая стратегия подходит для разных сценариев. Git автоматически выбирает подходящую стратегию, но разработчик может указать её явно через флаг --strategy. Понимание стратегий помогает предсказать поведение Git при сложных слияниях.
Recursive — стратегия по умолчанию для слияния двух веток. Git находит общего предка, вычисляет изменения в каждой ветке и объединяет их. Если найден общий предок, recursive корректно обрабатывает переименование файлов и добавление новых. При конфликтах recursive может использовать дополнительные опции: ours (автоматически выбирать нашу версию) и theirs (выбирать их).
Octopus — для одновременного слияния более двух веток: git merge feature1 feature2 feature3. Octopus не поддерживает разрешение конфликтов — все конфликты должны быть решены до вызова команды. Используется редко, в основном для объединения нескольких независимых веток, которые гарантированно не конфликтуют (например, разные модули).
| Стратегия | Количество веток | Разрешение конфликтов |
|---|---|---|
| Recursive | 2 | Автоматическое + опции ours/theirs |
| Octopus | 3+ | Нет — все конфликты должны быть решены заранее |
| Ours | Любое | Всегда выбирает нашу версию, чужие изменения игнорируются |
| Subtree | 2 | Для слияния поддеревьев (subtree merge) |
Ours — особая стратегия, которая полностью игнорирует изменения из сливаемой ветки и сохраняет текущее содержимое целевой ветки. Merge-коммит создаётся, но содержимое остаётся без изменений. Полезна, когда нужно зафиксировать в истории факт слияния, но фактически отклонить все изменения из чужой ветки.
Merge-конфликт возникает, когда одни и те же строки файла были изменены в обеих ветках по-разному. Git не может автоматически определить, какая версия правильная, и приостанавливает merge. Конфликт может также возникнуть при переименовании файла в одной ветке и его изменении в другой, или при одновременном удалении и модификации одного файла.
Процесс разрешения: Git помечает конфликтующие файлы маркерами. В файле появляются участки с <<<<<<< HEAD (наша версия), ======= (разделитель) и >>>>>>> feature (их версия). Разработчик вручную редактирует конфликтный участок, выбирая нужные строки из обеих версий, убирает маркеры, сохраняет файл и добавляет его в индекс через git add.
Для визуального разрешения конфликтов Git поддерживает mergetool — внешний инструмент сравнения. Популярные mergetool: Meld, KDiff3, Beyond Compare, VS Code (встроенный редактор конфликтов). Mergetool отображает три панели: наша версия, их версия и результат. Разработчик визуально выбирает блоки кода для включения в итоговый файл.
# Start merge and detect conflict
git merge feature
# CONFLICT (content): Merge conflict in src/main.swift
# Check conflicted files
git status
# Open visual mergetool
git mergetool
# After resolution — add and commit
git add src/main.swift
git commit
# Abort merge
git merge --abort
Merge предпочтительнее rebase в нескольких ключевых ситуациях. Первая: при работе с публичными ветками, доступными другим разработчикам. Merge не перезаписывает историю, и коллеги могут безопасно синхронизироваться. Rebase в публичной ветке создаст расходящуюся историю и конфликты у всех, кто уже получил старые коммиты.
Вторая ситуация: при завершении feature-ветки. Большинство команд предпочитает merge (с флагом --no-ff) в main, чтобы зафиксировать момент интеграции фичи. Это упрощает навигацию по истории и позволяет легко откатить целую фичу одним git revert merge-коммита. GitHub Flow по умолчанию предлагает три опции merge: простой merge, squash merge и rebase merge.
Третья ситуация: при работе с pull request, который прошёл ревью. GitHub и GitLab предлагают merge-кнопку с разными опциями. Merge (Create a merge commit) — полная история с merge-коммитом. Squash and merge — чистая история без деталей разработки. Rebase and merge — линейная история без merge-коммита, но с перезаписью коммитов. Выбор зависит от правил команды.
Первое правило: всегда быть на актуальной версии целевой ветки перед merge. Выполните git checkout main && git pull перед тем, как сливать feature. Это минимизирует конфликты и гарантирует, что merge-коммит будет содержать все актуальные изменения. Если целевая ветка сильно ушла вперёд, сначала выполните git merge main внутри feature-ветки для разрешения конфликтов в её контексте.
Второе правило: тестировать код после merge. Merge может изменить поведение, даже если не было конфликтов. CI/CD пайплайн должен прогнать тесты на merge-коммите перед отправкой в production. Некоторые команды используют merge gates — обязательные проверки, которые блокируют merge до их прохождения.
Третье правило: документировать merge-коммиты. Стандартное сообщение «Merge branch 'feature' into main» малополезно. Рекомендуется добавлять описание того, что было слито: «Merge authentication module: login, registration, password recovery». Это упрощает анализ истории и поиск регрессий. В крупных проектах merge-коммиты автоматически генерируются из названия PR.
Часто задаваемые вопросы
Мёржить — выполнить git merge для объединения изменений из одной ветки в другую. Результатом является merge-коммит, который фиксирует факт слияния и содержит изменения из обеих веток. Это основной способ интеграции feature-веток в main, develop или release в Git Flow.
Squash merge объединяет все коммиты feature-ветки в один коммит в целевой ветке, теряя промежуточную историю разработки. Обычный merge создаёт merge-коммит, сохраняя все коммиты feature-ветки. Squash merge даёт чистую историю, но не позволяет отследить пошаговую разработку фичи.
Откройте конфликтующий файл, найдите участки с маркерами <<<<<<< HEAD и >>>>>>>. Отредактируйте содержимое, оставив нужные строки из обеих версий, удалите маркеры. Сохраните файл, выполните git add и git commit. Можно использовать git mergetool для визуального разрешения.
Merge всегда используется для публичных веток (main, develop, release), так как не перезаписывает историю. Rebase применяется в личных feature-ветках до их публикации. После того как ветка стала частью общего репозитория и к ней обратились коллеги, разрешён только merge.
До завершения merge (во время конфликта) — git merge --abort отменяет слияние полностью. После завершения — git revert <merge-commit-hash> -m 1 создаёт отменяющий коммит. Флаг -m 1 указывает, какую родительскую ветку сохранить (целевую). Git revert безопаснее git reset для опубликованных веток.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также