Learning Platform
Глоссарий Troubleshooting
Урок 13.04 · 25 мин
Средний
mergesquashrebasemerge-commithistorygithub

Merge strategies на GitHub — три варианта

После approve PR, GitHub предлагает три способа merge. Каждый создаёт разную историю на main. Выбор влияет на читаемость git log, способность откатывать изменения, и общую atomic-ность коммитов. В этом уроке: технически что делает каждая стратегия, какая когда подходит, и почему в DE-командах обычно squash или merge-commit, а rebase-merge редко.


Setup для примера

Допустим, у тебя feature ветка с 5 коммитами:

main:     A -> B -> C
feature:  A -> B -> C -> F1 -> F2 -> F3 -> F4 -> F5

F1..F5 — твои коммиты feature. A..C — main. Хочешь замержить feature в main. Что покажет git log --graph --oneline после каждой стратегии?


Стратегия 1: Create a merge commit

Default GitHub поведение. Эквивалент git merge feature (no fast-forward):

$ git switch main
$ git merge --no-ff feature

После:

main:  A -> B -> C ───────────────────-> M
                ↘                     ↗
                  F1 -> F2 -> F3 -> F4 -> F5

Создан merge-коммит M с двумя родителями: C (main до merge) и F5 (feature). Все F1..F5 коммиты сохранены в истории.

Плюсы

  • Сохранён context работы: видно как ты пошагово делал feature.
  • Easy revert: один git revert -m 1 <merge-commit> отменяет всю фичу.
  • Точная история: timestamps и author каждого коммита оригинальные.

Минусы

  • Шумная история: git log --oneline на main забит мелкими WIP коммитами.
  • Сложнее найти когда что: «при каком коммите feature замержена» — надо искать merge-коммит.

Когда юзать

  • Долгоживущие feature ветки с значимыми коммитами (каждый — логически отдельный шаг).
  • Команда практикует тщательный commit hygiene (каждый коммит атомарный, message по conventional commits).
  • Большие фичи где история разработки важна.

Стратегия 2: Squash and merge

Все коммиты feature «сплющиваются» в один:

$ git merge --squash feature
$ git commit -m "feat: add users pipeline (squashed)"

После:

main:  A -> B -> C -> S

Где Sодин коммит, содержащий все изменения F1..F5 одним патчем. F1..F5 как отдельные коммиты исчезают с main (но остаются на feature, пока её не удалят).

GitHub UI позволяет редактировать message squash-коммита перед merge. По умолчанию — это title PR + body списком commit messages из feature.

Плюсы

  • Чистая main история: один коммит на одну фичу. git log --oneline main читается легко.
  • Atomic units: каждая строка лога = одна логическая фича.
  • Простой revert: один git revert <squash-commit>.
  • Не нужна commit hygiene на feature: можно WIP, fix typo, tests pass plz — всё сольётся в один чистый коммит.

Минусы

  • Теряется детальная история: «через какие шаги шёл author к финальной версии» — невидимо.
  • Author = тот кто squash-нул, не original author в некоторых случаях (GitHub обычно сохраняет).
  • Bisect (поиск бага) теряет точность: один большой коммит вместо мелких ступенек.

Когда юзать

  • Большинство DE команд: SaaS, продуктовая разработка, internal repos.
  • Feature разрабатывалась с messy commits («WIP», «fix linter», «add tests»).
  • Команда ценит чистый main log выше детальной истории.

Стратегия 3: Rebase and merge

Все коммиты feature переписываются поверх main, без merge-коммита:

$ git switch feature
$ git rebase main
$ git switch main
$ git merge --ff-only feature

После:

main:  A -> B -> C -> F1' -> F2' -> F3' -> F4' -> F5'

F1..F5 ребейзнуты (новые SHA, отсюда F1'..F5'). Применены прямо на main как линейная последовательность. Никакого merge-коммита.

Плюсы

  • Линейная история: git log --oneline без merge-коммитов, всё в одну линию.
  • Сохраняет атомарность каждого коммита: F1..F5 видны отдельно.
  • Bisect работает чисто: можно найти баг точно на одном коммите.

Минусы

  • Теряет context merge: не видно «эти 5 коммитов были одной feature» (нет marker’а).
  • Переписывает SHA: original commit hashes исчезают (плохо для PR-комментариев которые ссылаются на конкретные коммиты).
  • Сложнее revert: надо ревертить каждый коммит F1’..F5’ отдельно, или диапазон.
  • Каждый коммит должен пройти CI — иначе main падает на промежуточных commit-ах (если CI runs on every commit).

Когда юзать

  • Команды с строгим commit hygiene на feature (каждый коммит — атомарный, тесты проходят на каждом).
  • Open-source проекты типа Linux kernel, Postgres, где линейная история — конвенция.
  • Когда команда любит git log --oneline без merge-коммитов.

Сравнительная диаграмма

История main после каждой стратегии
Исходно: feature имеет 5 коммитов
Amain
B
Cmain HEAD до merge
F1…F5feature
Merge commit: M указывает на C и F5, F1-F5 сохранены
A
B
C
Mmerge-коммит, два родителя
+F1…F5F1-F5 видны в branch
Squash: один S коммит с всеми изменениями
A
B
C
Sодин коммит = all changes
Rebase: F1-F5 переписаны как F1'-F5', линейно
A
B
C
F1’…F5’новые SHA, линейно

Decision matrix для DE команд

СценарийСтратегия
Большинство SaaS / продуктовых командSquash
Команда с дисциплинированным commit hygieneSquash или Rebase
Open-source где история важнаMerge commit или Rebase
Linux kernel / Postgres style проектыRebase
dbt / Airflow corporate reposОбычно Squash
Spark / Hadoop communityMerge commit
Свой pet project, один разработчикSquash (проще)

В DE-командах реально: 70% squash, 25% merge-commit, 5% rebase-merge. Junior должен спросить у tech lead «какой у нас merge strategy». Это team convention.

TIP

GitHub можно настроить так, что разрешена только одна стратегия (Settings -> Pull Requests -> Allow merge types). Это enforces team convention автоматически. Если в твоей команде разрешён только squash — забудь про merge commit и rebase merge.


Squash detail: что попадает в commit message

При Squash and merge, GitHub формирует message:

PR title

* Commit 1 message
* Commit 2 message
* Commit 3 message

Например:

feat(dags): add users ETL pipeline (#234)

* WIP basic structure
* Add transform step
* Add tests
* Fix linter
* Update docs

В UI можно отредактировать message перед merge. Best practice — почистить:

feat(dags): add users ETL pipeline (#234)

Implements ETL для users из Postgres в warehouse.
Includes transform, validation, tests.

Closes #123

Number (#234) в конце автоматически добавляется GitHub — ссылка на PR. Очень полезно для tracking.


Что НЕ делать

Ad-hoc rebase локально перед merge

# Локально
$ git switch feature
$ git rebase main
$ git push --force-with-lease     # переписываем remote feature

# В GitHub
[click] Squash and merge

После rebase + squash инфа двойная. Команда может ожидать одно, видеть другое. Не комбинируй rebase локально + squash на GitHub.

Manual merge через terminal

$ git switch main
$ git merge feature
$ git push origin main

Это работает, но обходит PR-процесс: нет approve, нет CI check на merge-коммите, нет audit trail в GitHub UI. В team setting почти всегда запрещено branch protection (push в main только через PR merge button).

Force-push main после merge

Никогда. Подробно — в модуле 10 урок 03.


Реальный pattern: dbt-репо на GitHub

Команда dbt на GitHub с такими settings:

  • Branch protection на main:
    • Require PR before merge
    • Require 1 approval
    • Require status checks (dbt parse, dbt test on PR branch)
    • Restrict pushes (только через PR merge)
    • Allowed merge types: Squash only

Workflow:

$ git switch -c feat/customer_ltv main
# работа, possibly много мелких коммитов (WIP, fix, refactor)
$ git push -u origin feat/customer_ltv

$ gh pr create --title "feat(marts): customer LTV model" \
    --body "..."

# CI зелёный, reviewer approve
$ gh pr merge --squash --delete-branch
# Один squashed коммит на main, feature ветка удалена

Результат:

  • git log main --oneline — чистая история одна-фича-один-коммит.
  • Хочешь подробности feature — открой PR в GitHub, видна детальная история.
  • Revert одного PR — один git revert <commit>.

Это standard DE pattern в 2026.


Killer takeaway

GitHub предлагает 3 merge strategies: Merge commit (preserve history, шумный log), Squash (один коммит, чистая main — most common в DE), Rebase merge (линейная история, требует строгий commit hygiene). 70% DE teams юзают squash. Команда настраивает разрешённые стратегии через branch protection. Не комбинируй local rebase + squash on GitHub — выбери одно.

CI/CD для данных: стратегии деплоя через PR
Проверка знанийKnowledge check
ОтветAnswer

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 5. Что точно происходит при 'Squash and merge' на GitHub?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5