Git rebase: как работает, rebase onto и интерактивный режим

Категория: Git · Язык: Bash · Обновлено:

Git rebase переносит коммиты вашей ветки на новую базу, например на свежий main, и делает историю линейной. Базовый вариант: git rebase main из рабочей ветки. Команда переписывает коммиты, поэтому не применяйте её к веткам, которыми уже пользуются другие.

Обновить ветку поверх main

Bash
git switch feature/login
git fetch origin
git rebase origin/main

Git временно откладывает ваши коммиты, переключает ветку на origin/main и заново применяет коммиты один за другим. У них изменятся хеши, потому что у них новый родитель.

Если возник конфликт

Git остановится на конфликтном коммите. Исправьте файлы и продолжайте:

Bash
git add путь/к/файлу
git rebase --continue    # перейти к следующему коммиту
git rebase --skip        # отбросить текущий коммит целиком
git rebase --abort       # отменить rebase и вернуть ветку как было

Интерактивный режим: склеить и поправить коммиты

Bash
git rebase -i HEAD~4

Git откроет список последних четырёх коммитов. Перед каждым стоит команда, её можно заменить:

Команда

Что делает

pick

Оставить коммит как есть

reword

Оставить, но изменить сообщение

edit

Остановиться на коммите, чтобы изменить содержимое

squash

Влить в предыдущий коммит и объединить сообщения

fixup

Влить в предыдущий коммит, сообщение выбросить

drop

Удалить коммит

Строки идут от старого коммита к новому. Меняйте порядок строк, чтобы поменять порядок коммитов.

Перенести часть ветки через --onto

Допустим, ветка feature/ui выросла из feature/api, а feature/api ещё не готова. Нужно перенести только коммиты feature/ui на main:

Bash
git rebase --onto main feature/api feature/ui

Запись читается так: «возьми коммиты после feature/api, которые есть в feature/ui, и поставь их поверх main».

Rebase при загрузке изменений

Bash
git pull --rebase                       # вместо merge-коммита перенести свои коммиты
git config --global pull.rebase true    # делать так при каждом pull

Merge или rebase

merge

rebase

История

Сохраняет ветвление и создаёт merge-коммит

Линейная, без лишних merge-коммитов

Хеши коммитов

Не меняются

Меняются

Общие ветки

Безопасен

Опасен: другие получат расходящуюся историю

Как отменить rebase после завершения

Bash
git reflog                  # найдите запись до начала rebase
git reset --hard ORIG_HEAD  # вернуть ветку к состоянию до rebase

ORIG_HEAD хранит положение ветки перед последней опасной операцией, но следующая такая операция его перезапишет.

Частые вопросы

Можно ли сделать rebase ветки, которая уже на сервере?

Можно, если над ней работаете только вы. После rebase отправляйте ветку командой git push --force-with-lease.

Чем squash отличается от fixup?

Оба объединяют коммит с предыдущим. squash оставляет оба сообщения для редактирования, fixup оставляет только сообщение первого коммита.