Средний 9 мин чтения
Merge vs Rebase
Merge и Rebase — два способа интеграции изменений из одной ветки в другую. У каждого свои преимущества и случаи применения.
gitmergerebasehistory
Merge
git merge создаёт merge commit, объединяющий две истории:
До:
main: A ─── B ─── C
\
feature: D ─── E
После git merge feature (из main):
main: A ─── B ─── C ─── M
\ /
feature: D ─── E
git checkout main
git merge feature/auth
Плюсы:
- Сохраняет точную историю — видно, когда и что было слито
- Безопасен — не переписывает историю
- Простое разрешение конфликтов (один раз)
Минусы:
- История засоряется merge commit-ами при активном ветвлении
Rebase
git rebase переписывает историю, перенося коммиты ветки на вершину другой:
До:
main: A ─── B ─── C
\
feature: D ─── E
После git rebase main (из feature):
main: A ─── B ─── C
\
feature: D' ─── E'
(D и E переписаны как D' и E')
git checkout feature/auth
git rebase main
Плюсы:
- Линейная, чистая история
- Проще читать
git log - Нет лишних merge commit-ов
Минусы:
- Переписывает историю — опасно для опубликованных веток
- Конфликты нужно решать для каждого коммита отдельно
Золотое правило Rebase
Никогда не делайте rebase публичных веток (которые уже запушены и используются другими)
# ✅ Безопасно — rebase своей локальной ветки на main
git checkout feature/my-feature
git rebase main
# ❌ Опасно — rebase ветки, которую использует команда
git checkout main
git rebase feature/shared-branch # Никогда!
Interactive Rebase — переписывание истории
git rebase -i HEAD~3 # Редактировать последние 3 коммита
git rebase -i main # Редактировать все коммиты начиная с main
Открывается редактор:
pick abc1234 feat: add login form
pick def5678 fix: typo in form
pick ghi9012 refactor: extract validation
# Команды:
# pick - оставить коммит как есть
# reword - изменить сообщение коммита
# edit - остановиться для внесения изменений
# squash - объединить с предыдущим коммитом (сохранить оба сообщения)
# fixup - объединить с предыдущим (выбросить сообщение)
# drop - удалить коммит
Сжатие (squash) нескольких коммитов
pick abc1234 feat: add login feature
squash def5678 wip: save progress
squash ghi9012 fix: forgot edge case
Результат — один чистый коммит вместо трёх WIP-коммитов.
Реальный рабочий процесс
Сценарий 1: Feature branch workflow
# 1. Создать ветку от актуального main
git checkout main && git pull
git checkout -b feature/user-profile
# 2. Разработка...
git commit -m "feat: add profile page"
git commit -m "wip: save"
git commit -m "feat: add avatar upload"
# 3. Перед PR — привести историю в порядок
git rebase -i main # Squash WIP-коммиты
# 4. Обновить на актуальный main
git rebase main
# 5. Push и PR
git push -u origin feature/user-profile
Сценарий 2: Конфликт при rebase
git rebase main
# Возникает конфликт...
# Редактируем файл, разрешаем конфликт
git add resolved-file.ts
git rebase --continue # Продолжить
# Если что-то пошло не так:
git rebase --abort # Вернуться к состоянию до rebase
Merge vs Rebase: когда что использовать
| Ситуация | Рекомендация |
|---|---|
| Интеграция feature ветки в main | merge --no-ff |
| Обновление feature от main | rebase |
| Публичная ветка (уже запушена) | merge |
| Локальная ветка (только у вас) | rebase |
| Нужна чистая линейная история | rebase |
| Нужно видеть точки слияния | merge |