# git rebase
_Ветки и слияния · GitLab Knowledge Base_
**TL;DR:** Переписывает коммиты ветки, делая их потомками другого коммита.
Создаёт новые SHA, история становится линейной. Безопасен только
для веток, которые ещё никто, кроме автора, не видел.
`git rebase ` берёт коммиты текущей ветки от общего предка с
`` до HEAD и пересаживает их поверх ``. У каждого
коммита меняется родитель → меняется SHA.
## Базовый сценарий
```
до: main: A → B → E
\
feat: C → D
git switch feat
git rebase main
после: main: A → B → E
\
feat: C' → D' ← новые SHA
```
Логика правок в C' и D' та же, что в C и D. Но это другие
объекты - для Git «новые коммиты».
## Когда применять
- **Перед PR**, чтобы feature-ветка стояла на свежем main, без
merge-коммитов.
- **Очистить локальную историю** через `rebase -i` (см.
[interactive-rebase](/courses/git/kb/interactive-rebase.md)).
- **Переместить ветку** на другой базис через `--onto`.
## Главное правило
**Не rebase'ить публичные ветки.** Если ветку кто-то склонил, у
него останутся старые SHA. После твоего force-push возникает
каша. Безопасно - только на личной feature до или сразу после
ревью.
## Конфликты
Если на каком-то коммите возникает конфликт - Git останавливается,
показывает файлы с маркерами, ждёт разрешения:
```bash
# править файлы, убирать маркеры
git add
git rebase --continue # продолжить со следующего коммита
# или отказаться от текущего коммита:
git rebase --skip
# или отменить всё:
git rebase --abort
```
Конфликт может возникать на каждом коммите подряд (если каждый
трогает спорные строки). После rebase каждый промежуточный
результат уже разрешён.
## После rebase
Если ветка была запушена - обычный push откажет, потому что SHA
поменялись:
```bash
git push --force-with-lease
```
`--force-with-lease` проверяет, что remote не успел уйти вперёд
(никто другой не запушил). Лучше всегда `--force-with-lease`, не
`--force`.
## Подводные камни
- Rebase копирует автор-даты коммитов как есть, но обновляет
committer-даты. После rebase `git log --pretty=fuller` может
показывать «странные» расхождения.
- На большом количестве коммитов rebase может занять заметное
время и потребовать разрешения конфликтов на каждом шаге.
- `git pull --rebase` объединяет fetch с rebase'ом твоих
локальных коммитов поверх удалённых. Удобно как дефолт:
`git config --global pull.rebase true`.
## Команды
```bash
git rebase main
```
Пересадить текущую ветку поверх main
```bash
git rebase -i HEAD~5
```
Interactive rebase: переименовать/сжать/удалить последние 5 коммитов
```bash
git rebase --continue
```
Продолжить rebase после разрешения конфликта
```bash
git rebase --abort
```
Отменить начатый rebase, вернуться в исходное состояние
## См. также
- [git merge](/courses/git/kb/merge.md)
- [Interactive rebase](/courses/git/kb/interactive-rebase.md)
- [git cherry-pick](/courses/git/kb/cherry-pick.md)