git rebase: перенос коммитов поверх чужих

Обновлено 31 июля 2026 г.

git rebase переписывает твои коммиты так, будто ты начал работу уже после того, как коллега закончил свою. Вместо развилки и коммита слияния получается одна прямая линия.

Слияние сохраняет историю как было: две линии сходятся в коммите слияния, и в git log --graph видно, кто от чего отводился. Rebase даёт другой результат: сначала чужие коммиты, потом твои, без развилок. Многим командам такая история читается легче.

$ git log --graph --oneline --all
* 01393b3 style the search box
* 14b6745 add search box
| * a66eee4 bob fixes typo
|/
* df02c61 alice adds a note
$ git switch feature-search
$ git rebase main
Successfully rebased and updated refs/heads/feature-search.

$ git log --graph --oneline
* 1ba6e8c style the search box
* 22eded3 add search box
* a66eee4 bob fixes typo
* df02c61 alice adds a note

Посмотри на хеши: 14b6745 стал 22eded3. Никакого переноса на самом деле нет. Git создал новые коммиты с тем же содержимым, но с другим родителем, а старые бросил.

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

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

Проверка встроена в сам git: обычный git push после rebase отвергается, потому что серверная ветка больше не предок твоей. Отправить получится только с --force, и это сигнал остановиться и вспомнить, кто ещё видел эту ветку. Более щадящий --force-with-lease откажется работать, если на сервере успели появиться чужие коммиты.

Конфликты и отмена

Rebase применяет коммиты по одному, поэтому конфликт останавливает его посередине:

$ git rebase main
CONFLICT (content): Merge conflict in conf.txt
error: could not apply 042569a... alice edits line1
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".

Дальше как с обычным конфликтом: правишь файл, git add, потом git rebase --continue. Передумал в любой момент - git rebase --abort возвращает ветку ровно в то состояние, в котором она была до команды.

Отдельный режим - интерактивный rebase, git rebase -i HEAD~5. Список последних пяти коммитов открывается в редакторе, и строки можно переставить, склеить (squash), переписать сообщение (reword) или выбросить (drop). Им причёсывают собственную историю перед отправкой: пять правок опечаток превращаются в один коммит. Правило про общие ветки действует здесь так же.

Частые ошибки

Считать rebase «более правильной» заменой merge. Это выбор стиля истории, а не техники: git merge сохраняет ход работы как было, rebase выпрямляет линию. В команде договариваются об одном варианте и держатся его.

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

Где это в учебнике

Раздел «Что дальше» в итоговом проекте. Почему в командах не любят force push, разобрано здесь: Глава 7. Как git используют в командах.

Потренироваться руками - в Песочнице: настоящий терминал с git и проверка шагов.