DevOps & CI/CD

git rebase

Команда Git, переносящая коммиты ветки на новое основание — история становится линейной, но коммиты пересоздаются с новыми хешами.

Что такое git rebase

git rebase — команда Git, которая переносит коммиты вашей ветки на новое основание (base). Git берёт коммиты, которых нет в целевой ветке, откладывает их, перематывает ветку на новую вершину и применяет коммиты заново — по одному, поверх.

Ключевой момент: коммиты не перемещаются, а пересоздаются. У них новые хеши, хотя автор, сообщение и содержимое сохраняются. Формально это уже другие коммиты, и именно отсюда растут все правила безопасности вокруг rebase.

До rebase:                     После git rebase main:

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

rebase vs merge

Обе команды решают одну задачу — забрать изменения из main в свою ветку, — но оставляют разную историю.

git merge main git rebase main
Результат Merge-коммит, история ветвится Линейная цепочка
Хеши коммитов Сохраняются Пересоздаются
Что было на самом деле Видно точно Приукрашено
Разрешение конфликтов Один раз Возможно на каждом коммите
Безопасно для общей ветки Да Нет

Merge честнее, rebase — читаемее. Практический компромисс: rebase внутри своей ветки (пока никто её не видел), merge — при вливании готовой ветки в main.

Базовое применение

git switch feature/auth
git fetch origin
git rebase origin/main        # перенести свои коммиты на свежий main

# при конфликте
git status                    # какие файлы конфликтуют
# ... правим файлы ...
git add file.py
git rebase --continue         # продолжить

git rebase --skip             # пропустить коммит (редко)
git rebase --abort            # передумать и вернуть всё как было

git rebase --abort возвращает ветку в исходное состояние на любом шаге — rebase не тот случай, где легко потерять работу безвозвратно.

Интерактивный rebase

rebase -i — инструмент для причёсывания собственной истории перед code review: склеить пять коммитов «фикс», переписать сообщения, выбросить отладочный.

git rebase -i HEAD~4
pick a1b2c3d feat: добавить эндпоинт
squash b2c3d4e fix: опечатка
squash c3d4e5f fix: ещё раз опечатка
reword d4e5f6a добавить тесты

Команды: pick — оставить, squash — склеить с предыдущим (сообщения объединятся), fixup — то же, но сообщение выбросить, reword — изменить сообщение, edit — остановиться и поправить содержимое, drop — удалить коммит.

Золотое правило rebase

Не делайте rebase веток, которые уже видят другие.

Причина механическая: rebase создаёт новые коммиты вместо старых. Если коллега работает со старой версией ветки, у него и у вас теперь разные истории с разными хешами для одних и тех же изменений. Следующий git pull породит дубликаты и конфликты на ровном месте.

Rebase личной ветки — норма. Rebase main, develop или ветки, куда кто-то смотрит через pull request, — источник аварии.

Push после rebase

Так как хеши изменились, обычный git push будет отвергнут — сервер видит расхождение историй.

git push --force-with-lease   # правильный способ
git push --force              # опасно: затирает чужие коммиты молча

--force-with-lease проверяет, что на сервере ничего не появилось с момента вашего последнего fetch, и отказывается пушить, если появилось. Разница между «переписал свою ветку» и «стёр чужую работу» — ровно в этом флаге.

pull --rebase

Полезная настройка на каждый день: при git pull вместо merge-коммита ваши локальные коммиты переносятся поверх скачанных.

git config --global pull.rebase true

Без неё история проекта быстро зарастает бессмысленными коммитами вида «Merge branch 'main' of github.com...».

Связанные термины

Готовы запустить GPU-задачу?

Запустить GPU-сервер