Modern QA2026Rebase vs Merge
Join

Course17 Git & Version Control

Foundations · Chapter 17

Rebase vs Merge

Updated Jul 2026

Два способа интеграции изменений

И merge, и rebase интегрируют изменения из одной ветки в другую, но создают разную историю коммитов. Понимание различий помогает вам поддерживать чистую историю, избегать конфликтов и эффективно работать с командой.

Merge

Merge создаёт новый «коммит слияния», объединяющий истории двух веток. Полная история ветки сохраняется в графе.

git checkout main
git merge feature/login-tests
# Creates a merge commit; feature branch history visible in graph

Как выглядит история после merge:

main:    A --- B --- C --- M (merge commit)
                    /     /
feature: D --- E --/

Видны и коммиты основной ветки (A, B, C), и коммиты фича-ветки (D, E). Коммит слияния (M) отмечает точку интеграции.

Преимущества merge

  • Сохраняет историю: вы можете точно увидеть, когда фича-ветка была создана и слита
  • Безопасен для общих веток: никогда не переписывает существующие коммиты
  • Легко откатить: откатите коммит слияния, чтобы отменить всю фичу

Недостатки merge

  • Загромождённая история: множество коммитов слияния может сделать лог трудночитаемым
  • Шумные диффы: коммиты слияния могут усложнить просмотр git log --oneline

Rebase

Rebase воспроизводит ваши коммиты поверх целевой ветки, создавая линейную историю, как если бы вы написали код после последних изменений в целевой ветке.

git checkout feature/login-tests
git rebase main
# Your commits are rewritten on top of main's HEAD

Как выглядит история после rebase:

Before rebase:
main:    A --- B --- C
                \
feature:         D --- E

After rebase:
main:    A --- B --- C
                      \
feature:               D' --- E'  (new commits with same changes)

Коммиты D и E заменяются на D' и E' — те же изменения, но новые хэши. История линейна.

Преимущества rebase

  • Чистая, линейная история: нет коммитов слияния, загромождающих лог
  • Легче ревьюировать: диффы PR показывают только изменения фичи, без шума слияния
  • Проще bisect: git bisect работает надёжнее на линейной истории

Недостатки rebase

  • Переписывает историю: коммиты получают новые хэши, что опасно для общих веток
  • Может запутать: при неправильном rebase можно потерять работу
  • Разрешение конфликтов для каждого коммита: может потребоваться разрешать один и тот же конфликт несколько раз, если несколько коммитов затрагивают один файл

Когда использовать каждый вариант

Ситуация Используйте Причина
Обновление фича-ветки с последними изменениями main Rebase Сохраняет ваш PR чистым и удобным для ревью
Слияние PR в main Merge (или squash merge) Коммит слияния отмечает точку интеграции
Интеграция долгоживущей ветки Merge Сохраняет полную историю работы
Общая ветка с несколькими контрибьюторами Merge Никогда не делайте rebase коммитов, на которых другие могли основать свою работу
Очистка коммитов перед открытием PR Interactive rebase Объединение WIP-коммитов в логичные, удобные для ревью единицы

Золотое правило: никогда не делайте rebase коммитов, которые были запушены в общую ветку и на которых другие могли основать свою работу. Переписывание общей истории вызывает конфликты у всех, кто эти коммиты уже получил.

Разрешение конфликтов при rebase

При rebase Git воспроизводит каждый коммит по одному. Если коммит конфликтует с целевой веткой, Git приостанавливается и просит вас разрешить конфликт.

git rebase main
# CONFLICT (content): Merge conflict in tests/login.spec.ts
# Fix stopped at abc123f... Add login retry test

# Step 1: Open the conflicting file and resolve the conflict markers
# <<<<<<< HEAD
# current main version
# =======
# your version from the feature branch
# >>>>>>> Add login retry test

# Step 2: After resolving, stage the file
git add tests/login.spec.ts

# Step 3: Continue the rebase
git rebase --continue

# If you want to abort and go back to the state before rebase:
git rebase --abort

Советы по разрешению конфликтов:

  • Внимательно читайте обе версии. Не принимайте слепо одну сторону.
  • Если конфликт в тестовом коде, проверьте, не добавили ли обе стороны тесты для одной и той же функции. Возможно, нужно сохранить оба варианта.
  • Используйте git rebase --abort, если не уверены. Всегда можно попробовать снова.
  • После разрешения запустите тесты локально, чтобы убедиться в корректности решения.

Interactive rebase: очистка перед PR

Interactive rebase позволяет переписывать, объединять, переупорядочивать или удалять коммиты перед их публикацией.

# Rebase the last 4 commits interactively
git rebase -i HEAD~4

Открывается редактор с вашими коммитами:

pick abc1234 WIP: start login tests
pick def5678 fix typo
pick ghi9012 WIP: more login tests
pick jkl3456 finish login tests

Измените действия:

pick abc1234 WIP: start login tests
fixup def5678 fix typo                    # Merge into previous, discard message
squash ghi9012 WIP: more login tests      # Merge into previous, combine messages
pick jkl3456 finish login tests

Распространённые действия:

  • pick: оставить коммит как есть
  • squash: объединить с предыдущим коммитом, отредактировать объединённое сообщение
  • fixup: объединить с предыдущим коммитом, отбросить сообщение этого коммита
  • reword: изменить сообщение коммита
  • drop: удалить коммит полностью

Когда QA-инженерам стоит использовать interactive rebase:

  • Объединить несколько «WIP» или «fix typo» коммитов в один логичный коммит
  • Переформулировать расплывчатые сообщения типа «fix tests» во что-то описательное
  • Удалить коммиты-эксперименты (например, «add console.log»)
  • Переупорядочить коммиты, чтобы связанные изменения были сгруппированы

Squash merge

Многие команды используют squash merge при завершении PR. Squash merge объединяет все коммиты PR в один коммит в main.

# GitHub PR merge options:
# 1. Create a merge commit (preserves all commits)
# 2. Squash and merge (combines into one commit)
# 3. Rebase and merge (linear history, preserves individual commits)

Предпочтение QA: squash merge обычно лучше всего для фича-веток. Он сохраняет историю main чистой (один коммит на фичу), а детальная история коммитов сохраняется в самом PR.

Практический рабочий процесс для QA-инженеров

Вот ежедневный рабочий процесс, который поддерживает ваши ветки в чистоте:

# 1. Start a new feature branch
git checkout main
git pull origin main
git checkout -b feature/add-checkout-tests

# 2. Work on your tests, making multiple commits
git add tests/checkout.spec.ts
git commit -m "WIP: add checkout happy path test"
# ... more work ...
git commit -m "add checkout error handling tests"
git commit -m "fix selector for payment button"

# 3. Before opening a PR, update with latest main
git fetch origin
git rebase origin/main

# 4. Clean up commits with interactive rebase
git rebase -i HEAD~3
# Squash "fix selector" into the relevant commit

# 5. Force-push to your feature branch (safe because it's your branch)
git push --force-with-lease origin feature/add-checkout-tests

# 6. Open PR. After approval, squash merge into main.

Флаг --force-with-lease безопаснее, чем --force. Он отказывается пушить, если кто-то другой запушил в ветку после вашего последнего fetch, предотвращая случайное затирание чужой работы.

Практическое упражнение

  1. Создайте фича-ветку, сделайте 5 коммитов (включая несколько «WIP» и «fix typo»)
  2. Сделайте rebase ветки на последнюю версию main
  3. Используйте interactive rebase для объединения WIP-коммитов в чистые, логичные коммиты
  4. Намеренно создайте конфликт и потренируйтесь в его разрешении во время rebase
  5. Запушьте с --force-with-lease и проверьте чистую историю
  6. Откройте PR и используйте squash merge для его завершения