Перейти к содержимому

3. Merge и Rebase

Иллюстрация к уроку В этом уроке мы разберем два основных способа объединения веток в Git: merge и rebase. Понимание этих операций критически важно для эффективной работы в команде и поддержания чистоты истории проекта.

Merge (слияние) – это операция, которая берет изменения из одной ветки и добавляет их в другую, создавая новый коммит слияния. Этот коммит содержит историю обеих веток.

Представим, что у нас есть основная ветка main и ветка feature/new-feature, в которой мы разработали новую функциональность. Чтобы добавить эту функциональность в main, мы можем использовать merge.

Окно терминала
git checkout main
# Сливаем ветку feature/new-feature в main
git merge feature/new-feature

В результате выполнения этой команды, Git создаст коммит слияния в ветке main, который будет содержать изменения из feature/new-feature. История коммитов останется нетронутой, показывая, как развивались обе ветки.

Rebase (перебазирование) – это операция, которая берет изменения из одной ветки и “переигрывает” их поверх другой ветки. В отличие от merge, rebase не создает новый коммит слияния. Вместо этого, он как бы “перемещает” ветку поверх другой, изменяя историю коммитов.

Используя пример выше, чтобы добавить функциональность из feature/new-feature в main с помощью rebase, мы сделаем следующее:

Окно терминала
# Переключаемся на ветку feature/new-feature
git checkout feature/new-feature
# Перебазируем ветку feature/new-feature на main
git rebase main

Эта команда “переиграет” коммиты из feature/new-feature поверх последних коммитов в main. После этого, можно переключиться на main и слить feature/new-feature, используя merge. Но в этом случае, будет выполнено “fast-forward” слияние (ветка main просто продвинется вперед, указав на последний коммит feature/new-feature), так как нет расхождений в истории.

Окно терминала
git checkout main
git merge feature/new-feature

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

В реальных проектах, таких как разработка веб-приложений на React или фреймворков, merge и rebase используются постоянно.

  • Merge: Часто используется для слияния функциональных веток в основную ветку (например, develop или main) после завершения работы над фичей и прохождения код-ревью. Это позволяет сохранить историю разработки каждой фичи.
  • Rebase: Разработчики часто используют rebase для своей локальной ветки, чтобы синхронизировать ее с последней версией develop. Это позволяет избежать конфликтов при последующем слиянии и делает историю ветки более чистой. Например, перед отправкой запроса на слияние (Pull Request) в GitHub, разработчик может выполнить rebase своей ветки на develop.

Пример конфигурационного файла .gitconfig с alias для часто используемых операций:

[alias]
br = branch
co = checkout
ci = commit -m
st = status
df = diff
lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative
  • Merge сохраняет историю веток, создавая коммит слияния.
  • Rebase изменяет историю, “переигрывая” коммиты поверх другой ветки.
  • Используйте merge для слияния веток, когда важна история разработки.
  • Используйте rebase для локальных веток, чтобы поддерживать их в актуальном состоянии и создавать более чистую историю.
  • Никогда не используйте rebase на публичных ветках, так как это может вызвать проблемы для других разработчиков, работающих с этими ветками.
  • При конфликтах, возникающих при merge или rebase, необходимо разрешить их вручную.

Интерактивное сравнение — как выглядит история коммитов после merge и после rebase: