GIT: rebase
Glossary overview

GIT: rebase

Типичный рабочий процесс.

Допустим ты работаешь в feature.

Пока ты пишешь код, main двигается вперёд.

A---B---C  main
     \
      D---E  feature

Чтобы подтянуть изменения:

git checkout feature
git rebase main

Что происходит. Git берет твои коммиты из feature и переприменяет их поверх последнего main. То есть твоя ветка становится как будто созданной от свежего main.

История превращается из такой:

A---B---C  main
     \
      D---E  feature

в такую:

A---B---C---D'---E'  feature

Теперь твоя ветка не конфликтует с main исторически, потому что она уже построена на его последнем состоянии.

Теперь ты делаешь:

git checkout main
git merge feature

Git видит, что feature просто продолжение main. Поэтому merge будет fast-forward, без merge-коммита.

Получится:

A---B---C---D'---E'

Хорошая практика:

Rebase делают только на своих ветках.

git pull –rebase

Ещё есть мощная команда:

git pull --rebase

Она делает:

  1. git fetch
  2. git rebase origin/main

То есть подтягивает изменения без merge-коммитов.

git pull --rebase не переписывает чужую историю. Он переписывает только твои локальные коммиты. Поэтому это безопасно.

Разберем ее глубже

git pull --rebase – одна из тех команд Git, которые выглядят маленькими, а на деле делают довольно хитрую операцию. Чтобы понять её нормально, нужно сначала разобрать, что вообще делает обычный git pull.

Когда ты пишешь:

git pull

Git на самом деле выполняет две команды подряд:

git fetch
git merge

Сначала fetch скачивает новые коммиты с сервера, но ничего в твоей ветке не меняет.
Потом merge пытается объединить удалённую ветку с твоей локальной.

Представь историю.

Удалённый репозиторий:

A---B---C  origin/main

Ты клонировал проект раньше, поэтому у тебя локально было:

A---B  main

Потом ты сделал свой коммит:

A---B---D  main

Но тем временем на сервере появился C.

Теперь ты делаешь обычный pull:

git pull

Git делает:

git fetch
git merge

История станет такой:

A---B---C------M
     \        /
      D------

M – merge commit.

Иногда это нормально. Но если ты часто делаешь pull, история начинает выглядеть как тарелка спагетти. Куча merge-коммитов, которые ничего полезного не делают.

Вот тут появляется git pull --rebase.

Эта команда делает другое:

git fetch
git rebase

То есть Git сначала скачивает новые коммиты, а потом переносит твои локальные коммиты поверх них.

Git делает следующее:

  1. временно снимает твой коммит D
  2. обновляет ветку до C
  3. применяет D снова

Получается:

A---B---C---D'

История остаётся линейной. Без merge-коммитов.

Конфликт rebase во время pull

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

Ты увидишь что-то вроде:

CONFLICT (content): Merge conflict in file.php

Дальше процесс такой:

исправляешь конфликт

git add .
git rebase --continue

Git берёт следующий коммит и повторяет процесс.

Если всё пошло совсем плохо:

git rebase --abort

Git откатится к состоянию до pull.