Реклама
Селектел, перетяжка, 22.06
Селектел, перетяжка, 22.06
Селектел, перетяжка, 22.06

Git rebase vs merge: когда что использовать и в чём разница

git merge и git rebase решают одну задачу — интеграцию изменений из веток, — но по-разному. Разбираем оба подхода, объясняем interactive rebase и формулируем золотое правило, которое сохранит нервы вашей команды.

Обложка: Git rebase vs merge: когда что использовать и в чём разница

Если вы работаете с Git в команде, рано или поздно встаёт вопрос: как объединить ветки — через git merge или через git rebase? Оба инструмента решают одну задачу — интегрируют изменения из одной ветки в другую, — но делают это совершенно по-разному. Неправильный выбор может превратить историю репозитория в хаос или создать проблемы для всей команды.

В этой статье разберём, как работает каждая команда, когда что применять и почему нарушение золотого правила rebase ведёт к конфликтам у коллег. Статья подойдёт разработчикам, которые уже знакомы с базовыми командами Git и хотят разобраться с ветвлением и историей коммитов.

Ключевые выводы

merge создаёт merge-коммит и сохраняет полную историю веток — когда и откуда пришли изменения.

rebase переносит коммиты на новую базу и создаёт линейную историю без лишних merge-коммитов.

— Золотое правило: никогда не ребейсить публичные ветки, которые уже запушены и используются другими.

— feature-ветки перед слиянием — rebase; main/develop при получении чужих изменений — merge или pull --rebase.

— interactive rebase (git rebase -i) позволяет склеить, переименовать и отредактировать коммиты до публикации.

Также полезно изучить полезные команды Git — там собраны практические приёмы на каждый день.

Как работает git merge

git merge объединяет две ветки, создавая новый коммит — merge-коммит. Этот коммит имеет двух родителей: последний коммит текущей ветки и последний коммит ветки, которую вы вливаете. История полностью сохраняется: видно, когда ветка была создана, что в ней менялось, когда слита обратно.

			# Схема до merge
main:    A---B---C
                  \
feature:           D---E

# После: git checkout main && git merge feature
main:    A---B---C---M   <- merge-коммит (два родителя: C и E)
                  \ /
feature:           D---E
		

Merge безопасен для публичных веток: он только добавляет новый коммит, не меняя существующие. Коллеги, которые уже склонировали репозиторий, без проблем сделают git pull и получат обновлённую историю.

Минус — при активной разработке история быстро засоряется merge-коммитами. Если в команде 10 человек и у каждого по несколько веток, граф становится нечитаемым.

Как работает git rebase

git rebase переносит коммиты текущей ветки на новую базу — то есть «перекладывает» их поверх другой ветки. При этом Git создаёт новые коммиты с теми же изменениями, но другими хешами. Результат — линейная история без лишних merge-коммитов.

			# Схема до rebase
main:    A---B---C
                  \
feature:           D---E

# После: git checkout feature && git rebase main
main:    A---B---C---D'---E'   <- feature теперь поверх main (линейно)
                              (новые хеши! D'≠D, E'≠E)
		

Обратите внимание: D и E превращаются в D' и E' — это другие коммиты. Именно поэтому rebase опасен для ветки, которую уже видели другие разработчики: у них в локальных репозиториях останутся старые D и E, а в origin появятся новые D' и E'. При следующем git pull возникнет путаница и конфликты.

Interactive rebase: squash, fixup, reword

Флаг -i (interactive) открывает редактор со списком коммитов, которые можно переупорядочить и изменить перед публикацией. Это мощный инструмент для «уборки» истории feature-ветки до создания pull request.

			git rebase -i HEAD~4   # редактировать последние 4 коммита
		

Откроется список вида:

			pick a1b2c3d Добавить авторизацию
pick e4f5g6h Исправить опечатку
pick i7j8k9l WIP: доделать форму
pick m0n1o2p Финальный вариант формы
		

Команды, доступные в interactive rebase:

  • squash (или s) — склеить коммит с предыдущим, объединить сообщения
  • fixup (или f) — склеить с предыдущим, выбросить сообщение этого коммита
  • reword (или r) — изменить только сообщение коммита
  • edit (или e) — остановиться на коммите и внести изменения в файлы
  • drop (или d) — удалить коммит

Типичный сценарий: перед созданием PR склеить несколько черновых коммитов («WIP», «ещё правки», «исправить тест») в один чистый коммит с понятным сообщением. Команда увидит осмысленную историю, а не рабочий дневник.

Когда что использовать

Нет универсального ответа — выбор зависит от контекста и договорённостей в команде. Вот практические ориентиры.

feature-ветка → используйте rebase

Если вы работаете над личной feature-веткой, которую ещё не публиковали (или публиковали, но работаете в одиночку), — обновляйтесь через rebase:

			git checkout feature/my-task
git fetch origin
git rebase origin/main
		

Так ваши коммиты окажутся поверх актуального main, и PR будет применяться чисто, без merge-коммита. История останется линейной.

Слияние в main → используйте merge

Когда feature-ветка проверена и одобрена, её сливают в основную ветку через merge. В большинстве команд это делается через pull request, и CI автоматически создаёт merge-коммит. Это нормально: merge-коммит в main фиксирует факт слияния и сохраняет связь с веткой.

Общая ветка → никогда rebase

Если над веткой работают несколько разработчиков, git rebase категорически нельзя использовать. Rebase переписывает хеши — и у коллег возникнет рассинхронизация. При следующем git pull Git увидит два «параллельных» набора коммитов с одинаковыми изменениями, и придётся вручную разбираться с конфликтами.

Золотое правило rebase

Никогда не делайте rebase ветки, которая уже запушена в удалённый репозиторий и используется другими разработчиками.

Это правило звучит просто, но регулярно нарушается. Сценарий: вы запушили feature-ветку, открыли PR, получили ревью — и решили «подчистить» историю через git rebase -i. После этого придётся делать git push --force. Если коллега уже склонировал вашу ветку — у него сломается история.

Исключение: git push --force-with-lease — более безопасная версия force push, которая откажет, если кто-то успел запушить в ту же ветку. Но лучше договориться в команде заранее: нужна ли вам линейная история или достаточно merge-коммитов.

Сравнение: merge vs rebase

  • История: merge — нелинейная с merge-коммитами; rebase — линейная, как будто ветки не было
  • Безопасность для команды: merge — всегда безопасен; rebase — только на локальных или личных ветках
  • Трассировка: merge — видно, когда и откуда пришли изменения; rebase — история «переписана», оригинальные хеши утеряны
  • Конфликты: merge — разрешаются один раз; rebase — могут появляться на каждом переносимом коммите
  • Читаемость: merge — граф коммитов быстро загромождается; rebase — чистая линейная история
  • Откат: merge — git revert по merge-коммиту; rebase — откатить сложнее, так как хеши изменились
Часто задаваемые вопросы
1
Можно ли сделать rebase после того, как открыл pull request?

Технически да, но это требует git push --force-with-lease и договорённости с командой. Если коллеги уже оставили ревью или добавили коммиты в вашу ветку — rebase создаст проблемы. Безопаснее делать rebase до открытия PR, а после — только merge.

2
Что такое squash merge и чем он отличается от rebase?

Squash merge (git merge --squash) склеивает все коммиты ветки в один и добавляет его в основную ветку без merge-коммита. История выглядит чисто, как после rebase, но ветка при этом не привязывается к основной через родительский коммит. GitHub и GitLab предлагают squash merge как опцию при закрытии PR.

3
Как восстановиться, если rebase пошёл не так?

Воспользуйтесь git reflog — он хранит все состояния HEAD, включая до начала rebase. Найдите нужный коммит в reflog и выполните git reset --hard HEAD@{N}, где N — номер записи. Также во время rebase можно в любой момент выполнить git rebase --abort, чтобы вернуться к исходному состоянию.

Заключение

Выбор между merge и rebase — это не вопрос «что лучше», а вопрос «что нужно здесь». Merge сохраняет полную картину истории и безопасен для общих веток. Rebase даёт чистую линейную историю и идеален для подготовки feature-веток перед слиянием. Главное правило: не переписывайте то, что уже видели другие. Договоритесь о конвенции с командой — и придерживайтесь её.