W3docs

git rebase -i (интерактивный)

Научитесь использовать git rebase -i для объединения, переименования, изменения порядка и удаления коммитов перед публикацией.

Что такое интерактивный rebase

Интерактивный rebase, запускаемый командой git rebase -i, позволяет переписать серию коммитов до того, как вы ими поделитесь. Он открывает редактируемый «список задач» коммитов, где вы построчно решаете, что произойдёт с каждым из них — оставить как есть, изменить сообщение, объединить с другим, разбить, изменить порядок или удалить. Это расширение обычного git rebase, дающее вам контроль над каждым шагом.

На этой странице рассматривается, как запустить интерактивный rebase, все команды, доступные в списке задач, самые распространённые сценарии (объединение, переименование, изменение порядка, удаление и разбиение коммитов), как восстановиться при ошибке, а также единственное правило безопасного использования.

Список задач интерактивного rebase: объединение и переименование коммитов

Коммит — это сохранённый снимок вашей работы; HEAD — указатель на текущий коммит. «Переписывание истории» означает создание новых коммитов взамен существующих — Git никогда не изменяет коммит на месте, поэтому каждый переписанный коммит получает совершенно новый хеш.

Запуск интерактивного rebase

Укажите команде коммит перед первым, который вы хотите изменить — rebase воспроизведёт всё, что идёт после него. Чтобы пересмотреть последние три коммита:

git rebase -i HEAD~3

HEAD~3 означает «три коммита назад от HEAD». Можно также указать конкретный коммит (git rebase -i a1b2c3d) или, находясь в ветке, выполнить rebase всего, что добавлено после её отделения от другой ветки (git rebase -i main).

Git откроет настроенный редактор с одной строкой на каждый коммит, старые сверху (в отличие от git log):

pick a1b2c3d add login form
pick b2c3d4e fix typo
pick c3d4e5f more css tweaks

Ниже списка Git добавляет закомментированную шпаргалку по всем командам. Вы меняете слово в начале каждой строки, выбирая действие, при необходимости переставляете строки, затем сохраняете и закрываете файл. Git воспроизводит коммиты сверху вниз в соответствии с вашими инструкциями. Если сохранить файл без изменений (или удалить все строки), rebase ничего не сделает и остановится.

Команды списка задач

Каждая строка начинается с команды. Вот наиболее часто используемые:

КомандаСокращениеДействие
pickpИспользовать коммит как есть.
rewordrИспользовать коммит, но изменить его сообщение.
editeПриостановить выполнение на коммите, чтобы изменить его содержимое (amend, разбить или добавить файлы).
squashsОбъединить с предыдущим коммитом, сливая оба сообщения.
fixupfКак squash, но отбросить сообщение этого коммита.
dropdПолностью удалить коммит (удаление строки даёт тот же результат).
execxВыполнить команду оболочки (например, тесты) в этой точке rebase.

Команды reorder не существует — изменение порядка коммитов выполняется простым перемещением строк вверх или вниз в списке задач. Строки применяются сверху вниз, поэтому оставленный порядок — это порядок, в котором Git создаёт коммиты.

Объединение коммитов

Распространённый вариант очистки истории — сворачивание нескольких мелких коммитов в один. Пометьте первый как pick, а остальные как squash (или fixup, чтобы отбросить их сообщения):

pick a1b2c3d add login form
squash b2c3d4e fix typo
fixup c3d4e5f more css tweaks

squash/fixup всегда объединяют с вышестоящей строкой. При сохранении Git объединяет три коммита в один. Так как b2c3d4e был объединён через squash, Git откроет второй редактор с обоими сообщениями коммитов, чтобы вы могли написать одно чистое сообщение; fixup для c3d4e5f добавляет его изменения, но без сообщения.

Если вам нужно только объединить небольшие «случайные» коммиты с более ранним, обратите внимание на git commit --fixup (см. git commit --amend и git rebase -i --autosquash), который автоматически расставляет метки за вас.

Изменение сообщения коммита

Чтобы исправить опечатку или уточнить сообщение, не трогая код, пометьте строку как reword:

pick a1b2c3d add login form
reword b2c3d4e fix tpyo
pick c3d4e5f more css tweaks

Git воспроизводит a1b2c3d как есть, затем приостанавливается и открывает редактор со старым сообщением b2c3d4e, чтобы вы могли его переписать, после чего продолжает. Изменения коммита остаются нетронутыми — меняются только сообщение (и его хеш).

Изменение порядка и удаление коммитов

Чтобы изменить порядок, переместите строки. Чтобы удалить коммит, пометьте его drop или просто удалите строку. Этот список задач переставляет правку CSS перед исправлением опечатки и полностью удаляет коммит с опечаткой:

pick a1b2c3d add login form
pick c3d4e5f more css tweaks
drop b2c3d4e fix typo

Удаление или изменение порядка может вызвать конфликты, если более поздний коммит зависел от удалённого или перемещённого — Git приостановится и позволит вам их разрешить.

Разбиение коммита

Чтобы разбить один большой коммит на несколько, пометьте его edit. Git приостановится на этом коммите, уже применив его; затем вы откатываете коммит, сохраняя изменения, и фиксируете их частями:

# rebase pauses on the commit marked 'edit'
git reset HEAD~          # move the commit's changes back to the working tree
git add login.js
git commit -m "add login form markup"
git add styles.css
git commit -m "style the login form"
git rebase --continue    # resume the rest of the rebase

git reset HEAD~ отменяет последний коммит, оставляя его изменения в файлах (см. git reset), так что вы можете зафиксировать их отдельными, более мелкими коммитами.

Завершение или отмена

Если на каком-то шаге возникает конфликт, Git приостанавливается, чтобы вы могли его разрешить. Отредактируйте конфликтующие файлы, добавьте исправления через git add, затем продолжите:

git rebase --continue

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

git rebase --abort

Даже после завершения rebase оригинальные коммиты не теряются немедленно — они остаются доступными через git reflog некоторое время, что является страховочной сетью на случай, если вы сделали rebase и пожалели об этом.

Предупреждение

Интерактивный rebase переписывает историю — итоговые коммиты получают новые хеши. Это отлично подходит для приведения в порядок вашей собственной ветки перед созданием pull request, но никогда не делайте rebase коммитов, которые уже получили другие. Переписывание общей истории заставляет всех остальных согласовывать расходящиеся копии, а для публикации результата требуется принудительный push (git push --force-with-lease). Золотое правило: rebase локально, merge публично.

Если вам нужно изменить только самый последний коммит, обычно не требуется полный rebase — git commit --amend проще. Чтобы скопировать один коммит из другого места в вашу ветку, см. git cherry-pick.

Полный пример с объединением коммитов

Ниже приведена полная последовательность команд, которую можно запустить в пустой папке, чтобы увидеть объединение в действии. Создаются четыре коммита, затем последние три сворачиваются в один:

git init -b main demo && cd demo
git config user.email [email protected]
git config user.name You

echo "init"  > base && git add base && git commit -m "initial commit"
echo "a"     > f    && git add f    && git commit -m "add login form"
echo -e "a\nb" > f  && git add f    && git commit -m "fix typo"
echo -e "a\nb\nc" > f && git add f  && git commit -m "more css tweaks"

git log --oneline      # four commits
git rebase -i HEAD~3   # mark line 2 'squash', line 3 'fixup', save
git log --oneline      # now: "initial commit" + one combined commit

После rebase команда git log --oneline показывает всего два коммита — начальный коммит и один объединённый — а файл f по-прежнему содержит все три строки (a, b, c). Работа идентична; история коммитов стала просто аккуратнее.

Практика

Практика
Какие утверждения об интерактивном rebase верны?
Какие утверждения об интерактивном rebase верны?
Was this page helpful?