Типичный рабочий процесс.
Допустим ты работаешь в 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
Она делает:
git fetchgit 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 делает следующее:
- временно снимает твой коммит
D - обновляет ветку до
C - применяет
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.