Интерактивное перебазирование - git rebase -i

17 декабря 2025
Автор

Олег Марков

Введение

Интерактивное перебазирование в Git — это инструмент, который позволяет вам аккуратно переписать историю коммитов. С его помощью вы можете:

  • объединять несколько мелких коммитов в один;
  • разбивать один большой коммит на несколько логичных частей;
  • менять порядок коммитов;
  • редактировать сообщения;
  • удалять лишние или неудачные коммиты;
  • исправлять старые коммиты задним числом.

Смотрите, ключевая идея проста: вы берете диапазон своих коммитов и говорите Git, что хотите их проиграть заново, но с возможностью «отредактировать сценарий» по ходу. Интерактивный режим rebase как раз и является этим редактором сценария.

В этой статье я покажу вам, как работает git rebase -i, на что обратить внимание, какие ошибки часто допускают разработчики и как их избегать.


Что такое rebase и чем интерактивный режим отличается от обычного

Прежде чем разбираться с интерактивным режимом, давайте коротко напомним, что делает обычный rebase.

Базовая идея rebase

Обычное перебазирование переписывает историю ветки так, будто ваши коммиты были сделаны поверх другой «базы».

Представьте ситуацию:

  • у вас есть ветка main;
  • вы создали ветку feature от main;
  • в main кто-то продолжил работу и добавил новые коммиты;
  • теперь вы хотите перенести свои коммиты из feature так, как будто они были сделаны после последних коммитов в main.

Для этого вы используете:

git checkout feature            # Переключаемся на ветку feature
git rebase main                 # Перебазируем feature на верхушку main

Git берет ваши коммиты из feature и «проигрывает» их поверх последнего коммита main. История становится более линейной и понятной.

Что добавляет интерактивный режим

Интерактивный режим включается опцией -i:

git rebase -i main

Вместо того чтобы просто автоматически проиграть ваши коммиты, Git открывает редактор и показывает список коммитов, которые собирается перебазировать. Теперь вы можете:

  • управлять этим списком;
  • менять команды для каждого коммита;
  • останавливать процесс на коммитах для их редактирования.

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


Как запустить интерактивное перебазирование

Выбор диапазона коммитов

Чаще всего интерактивное перебазирование запускают относительно другой ветки или относительно HEAD~N.

Примеры:

git rebase -i main          # Перебазировать все коммиты, которых нет в main
git rebase -i HEAD~5        # Работаем с последними 5 коммитами
git rebase -i <hash>^       # Список начнётся с коммита, следующего за <hash>

Обратите внимание на запись HEAD~5:

  • HEAD — текущий коммит;
  • HEAD~5 — это «5 коммитов назад» от текущего;
  • когда вы пишете git rebase -i HEAD~5, в список попадут последние 5 коммитов, идущих после HEAD~5.

Что откроется при запуске rebase -i

Когда вы выполните команду, Git откроет редактор (обычно Vim, Nano или тот, который настроен в Git). Внутри вы увидите примерно такое:

pick a1b2c3d Первый коммит
pick b2c3d4e Второй коммит
pick c3d4e5f Третий коммит

# Rebase 1234567..c3d4e5f onto 1234567 (3 commands)
# 
# Команды:
#  p, pick  = использовать коммит как есть
#  r, reword = использовать коммит, но изменить сообщение
#  e, edit  = остановиться на этом коммите для правки
#  s, squash = объединить с предыдущим коммитом, объединить сообщения
#  f, fixup = объединить с предыдущим коммитом, отбросив сообщение
#  x, exec  = выполнить команду оболочки
#  d, drop  = удалить коммит

Здесь я намеренно показываю комментарии, которые Git добавляет сам. Они помогают вспомнить, что означает каждая команда.

Все, что вам нужно сделать — отредактировать строки с командами и сохранить файл. После сохранения rebase начнется.


Основные команды в интерактивном rebase

Теперь давайте по шагам разберем, что значат команды, которые вы можете использовать в этом списке.

Команда pick — оставить коммит как есть

Команда по умолчанию — pick:

pick a1b2c3d Первый коммит
pick b2c3d4e Второй коммит

Здесь Git «возьмет» коммиты и перепроиграет их без изменений. Вы можете использовать сокращение:

p a1b2c3d Первый коммит

Но, как правило, удобнее оставлять полное слово для читабельности.

Команда reword — изменить только сообщение коммита

Если вам нужно поправить только текст сообщения, но не содержимое файлов, используйте reword:

reword a1b2c3d Первый коммит
pick   b2c3d4e Второй коммит

После сохранения файла rebase:

  1. дойдет до этого коммита;
  2. создаст новый коммит с теми же изменениями;
  3. откроет редактор сообщения, чтобы вы могли переписать текст.

Давайте разберемся на примере:

git rebase -i HEAD~3         # Берем последние 3 коммита
# В редакторе меняем pick на reword у нужного коммита
# Сохраняем файл
# Git откроет редактор для изменения сообщения

Такой подход удобен, если вы хотите привести сообщения к одному стилю перед тем, как отправлять изменения в общий репозиторий.

Команда edit — изменить содержимое коммита

Команда edit позволяет остановиться на конкретном коммите, чтобы изменить его содержимое (добавить или убрать файлы, подправить код и т.п.).

Пример списка:

pick  a1b2c3d Первый коммит
edit  b2c3d4e Второй коммит
pick  c3d4e5f Третий коммит

Что произойдет:

  1. Git перепроиграет первый коммит;
  2. дойдет до второго и остановится, выведя сообщение вроде:

    Stopped at b2c3d4e... Второй коммит
    You can amend the commit now
    
  3. Теперь вы можете менять файлы как обычно.

Пример действий:

# Меняем файлы, как обычно
vim file.go               # // Открываем и правим файл
git add file.go           # // Добавляем изменения к коммиту

# Переписываем текущий коммит
git commit --amend        # // Обновляем коммит, не создавая новый

# Продолжаем rebase
git rebase --continue

Git двинется дальше по списку и продолжит применять оставшиеся коммиты.

Команды squash и fixup — объединение коммитов

Часто к концу работы над задачей у вас появляется несколько «шумных» коммитов:

  • «Исправить опечатку»;
  • «Правка форматирования»;
  • «Еще исправление» и т.п.

Интерактивный rebase позволяет объединить их в один аккуратный коммит.

squash — объединить коммиты и их сообщения

Пример списка:

pick   a1b2c3d Реализация фичи
squash b2c3d4e Исправление ошибки в фиче
squash c3d4e5f Рефакторинг после ревью

Как это работает:

  • первый коммит (pick) становится «основным»;
  • последующие с squash «приклеиваются» к нему;
  • Git объединяет все изменения в один коммит;
  • откроет редактор, чтобы вы объединили или отредактировали итоговое сообщение.

Вы увидите текст вроде:

# Это сообщение нового коммита
Реализация фичи
Исправление ошибки в фиче
Рефакторинг после ревью

Вы можете переписать это сообщение в одно логичное, например:

Реализация фичи X с исправлением ошибки и рефакторингом

fixup — объединить изменения, отбросив сообщение

fixup похож на squash, но не сохраняет текст сообщения «слипаемых» коммитов.

Пример:

pick  a1b2c3d Реализация фичи
fixup b2c3d4e Исправление опечатки

После rebase у вас будет один коммит с сообщением:

Реализация фичи

и внутри уже будут изменения из обоих коммитов.

Часто используют в связке с опцией --autosquash, о ней поговорим позже.

Команда drop — удалить коммит

Если вы понимаете, что какой-то коммит был лишним, вы можете удалить его из истории.

Варианты:

drop a1b2c3d Лишний коммит

или просто удалить строку целиком:

# Было:
pick a1b2c3d Лишний коммит
pick b2c3d4e Полезный коммит

# Стало:
pick b2c3d4e Полезный коммит

Git просто не будет заново создавать этот коммит при перебазировании.

Используйте с осторожностью, если коммиты уже ушли в общий репозиторий — об этом мы поговорим отдельно.

Команда exec — выполнить команду по ходу rebase

Команда exec позволяет вам вставить выполнение произвольной команды оболочки во время rebase.

Например, вы хотите, чтобы после каждого коммита запускались тесты:

pick a1b2c3d Добавить функцию
exec go test ./...     # // Запустить тесты после этого коммита
pick b2c3d4e Оптимизация

Git после применения первого коммита выполнит команду go test ./..., и только если она пройдет успешно, пойдет дальше.

Это уже более продвинутый сценарий, но он полезен, если вы хотите убедиться, что каждый коммит в истории «здоровый».


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

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

Давайте посмотрим на пример:

pick a1b2c3d Добавить модель пользователя
pick b2c3d4e Добавить API для пользователя
pick c3d4e5f Добавить тесты API

Логика здесь правильная: сначала модель, затем API, потом тесты. Но если вдруг вы случайно закоммитили тесты раньше API, вы можете исправить это.

Пример списка с неправильным порядком:

pick a1b2c3d Добавить модель пользователя
pick c3d4e5f Добавить тесты API
pick b2c3d4e Добавить API для пользователя

Вы просто переставляете строки:

pick a1b2c3d Добавить модель пользователя
pick b2c3d4e Добавить API для пользователя
pick c3d4e5f Добавить тесты API

Сохраняете, и Git применяет их в новом порядке.

Обратите внимание: если между коммитами есть зависимости по коду (например, тесты используют функции, которых еще нет), при неверном порядке вы можете получить конфликты или неработающую сборку. Тогда вам придется разбираться с ними во время rebase.


Объединение коммитов: практический сценарий

Давайте разберемся на практическом сценарии, который встречается почти у всех.

Представьте, что вы работали над задачей и сделали такую историю:

pick a1b2c3d Реализация фичи X
pick b2c3d4e Исправление опечатки
pick c3d4e5f Переименование переменных
pick d4e5f6a Исправление тестов

Вы понимаете, что все это по сути — одна фича, и хотите оставить один чистый коммит.

Шаг 1. Запустить rebase -i

git rebase -i HEAD~4

Git покажет:

pick a1b2c3d Реализация фичи X
pick b2c3d4e Исправление опечатки
pick c3d4e5f Переименование переменных
pick d4e5f6a Исправление тестов

Шаг 2. Пометить коммиты для squash

Теперь вы говорите Git, что первый коммит — основной, а остальные нужно прилепить к нему:

pick   a1b2c3d Реализация фичи X
squash b2c3d4e Исправление опечатки
squash c3d4e5f Переименование переменных
squash d4e5f6a Исправление тестов

Сохраняете файл.

Шаг 3. Объединить сообщения

Git применит первый коммит, затем добавит к нему остальные, и откроет редактор сообщения с чем-то вроде:

Реализация фичи X

Исправление опечатки

Переименование переменных

Исправление тестов

Вы можете переписать все это в одно:

Реализация фичи X

- начальная реализация
- правки кода и переменных
- исправление тестов

Сохраняете, rebase завершается, и в истории у вас один аккуратный коммит.


Правка старого коммита через edit

Теперь давайте посмотрим, как исправить ошибку в среднем коммите, не трогая позже идущие.

Предположим, история такая:

commit c3d4e5f (HEAD)   Добавить тесты
commit b2c3d4e          Добавить API
commit a1b2c3d          Добавить модель

Вы обнаружили, что в коммите «Добавить модель» забыли добавить поле в структуру. Но после него уже написан API и тесты. Вы хотите:

  • поправить модель в том месте, где она была добавлена;
  • при этом сохранить существующие коммиты API и тестов, но уже поверх исправленной модели.

Шаг 1. Запустить rebase для нужного диапазона

Нам нужно захватить все коммиты, начиная с того, который хотим править:

git rebase -i HEAD~3

Git покажет:

pick a1b2c3d Добавить модель
pick b2c3d4e Добавить API
pick c3d4e5f Добавить тесты

Шаг 2. Пометить коммит как edit

Меняем:

edit a1b2c3d Добавить модель
pick b2c3d4e Добавить API
pick c3d4e5f Добавить тесты

Сохраняем.

Шаг 3. Внести правки и amend

Git остановится на первом коммите и скажет, что вы можете его изменить.

Теперь вы делаете изменения:

vim user_model.go              # // Добавляем недостающее поле
git add user_model.go          # // Добавляем файл в индекс
git commit --amend             # // Обновляем текущий коммит

Комментарий:

  • commit --amend не создает новый логический коммит, а переписывает текущий, создавая новый объект коммита с обновленным содержимым.

Шаг 4. Продолжить rebase

git rebase --continue          # // Продолжаем проигрывать коммиты

Git заново применит коммиты «Добавить API» и «Добавить тесты» уже поверх обновленной модели.


Разрешение конфликтов во время rebase -i

При перебазировании часто возникают конфликты — это нормально, особенно если вы меняете историю или базу ветки.

Как выглядит конфликт при rebase

Если Git не может автоматически применить коммит, он выводит что-то вроде:

CONFLICT (content): Merge conflict in file.go
error: could not apply b2c3d4e... Добавить API

И при этом rebase приостанавливается.

Ваша задача:

  1. Открыть конфликтующие файлы.
  2. Разрешить конфликты.
  3. Продолжить rebase.

Шаги по разрешению конфликтов

Пример:

# Смотрим статус
git status

Git покажет файлы в состоянии «both modified».

Вы открываете файл:

vim file.go

Внутри увидите маркеры конфликта:

// Ваша версия
<<<<<<< HEAD
func DoSomething() {
    // Реализация А
}
=======
// Версия из коммита, который применяется
func DoSomething() {
    // Реализация Б
}
>>>>>>> b2c3d4e (Добавить API)

Вы руками оставляете нужный вариант (или объединяете их):

// Здесь мы объединяем нужные части реализаций
func DoSomething() {
    // Итоговая реализация
}

Далее:

git add file.go            # // Отмечаем конфликт как решенный
git rebase --continue      # // Продолжаем rebase

Если вы понимаете, что зашли в тупик и не хотите продолжать rebase, используйте:

git rebase --abort         # // Отменить rebase и вернуться к исходному состоянию

Важное правило безопасности: переписывание «общей» истории

Интерактивный rebase переписывает историю, а это значит:

  • хэши коммитов меняются;
  • Git по сути создает новые коммиты взамен старых.

Здесь важно отличать два случая:

1. Локальная ветка, которую вы еще не пушили

Тут вы можете переписывать все что угодно:

  • объединять;
  • удалять;
  • править;
  • менять порядок;

и это безопасно, потому что никто, кроме вас, не опирается на эти коммиты.

2. Ветка, которую вы уже отправили на удаленный репозиторий

Если вы сделали push, а после этого делаете интерактивный rebase, история на сервере и у вас начнет отличаться.

Чтобы запушить такую ветку, вам придется использовать:

git push --force-with-lease

Эта команда перезапишет историю на сервере.

Риски:

  • коллеги, которые уже успели выкачать старые коммиты, получат несостыковки и будут вынуждены вручную разруливать ситуацию;
  • если кто-то от вашей ветки создал другую, его история тоже окажется поврежденной.

Поэтому общий практический совет:

  • интерактивный rebase безопасен для локальных веток до первого push;
  • для веток, которыми пользуются другие, лучше обсуждать такие изменения в команде и использовать их аккуратно.

Быстрая очистка истории с autosquash

Git умеет автоматически подготавливать rebase -i для фиксации заранее помеченных коммитов. Смотрите, как это работает.

Подготовка fixup-коммитов

Представьте, что вы уже сделали основной коммит:

git commit -m "Реализация фичи X"

Потом обнаружили ошибку и решили сделать «фиксирующий» коммит:

git commit --fixup=<hash_основного_коммита>

или, если используете Git 2.35+:

git commit --fixup=amend:HEAD   # // Создать коммит, который будет склеен с HEAD

Git сам создаст сообщение вида:

fixup! Реализация фичи X

Автоматическое расположение с autosquash

Теперь вы запускаете:

git rebase -i --autosquash main

Git:

  • сам отыщет коммиты с префиксом fixup! или squash!;
  • переставит их сразу за соответствующие базовые коммиты;
  • автоматически проставит для них команды fixup или squash в файле rebase.

В редакторе вы увидите уже подготовленный порядок и команды, останется только сохранить.

Это очень удобно, когда вы сначала делаете основной коммит, а затем несколько исправлений, которые хотите в итоге слить в один.


Полезные практики при работе с rebase -i

Работайте с небольшими диапазонами

Старайтесь не брать сразу 30–40 коммитов. Лучше:

  • работать с последними 3–10;
  • чистить историю по мере работы над задачей.

Так ниже риск запутаться и столкнуться с масштабными конфликтами.

Используйте осмысленные сообщения коммитов

Интерактивное перебазирование особенно полезно, если вы:

  • в процессе работы пишете любые «черновые» сообщения;
  • а в конце приводите их к единому аккуратному виду через reword, squash и fixup.

Хорошая практика:

  • пока вы экспериментируете — «грязные» коммиты;
  • перед пушем — один или несколько чистых логичных коммитов.

Перед rebase делайте бэкап ветки

Если вы только осваиваете rebase -i, полезно подстраховаться:

git branch backup/feature-X   # // Создаем запасную ветку от текущего состояния

Если что-то пошло не так, вы всегда можете:

git checkout feature-X
git reset --hard backup/feature-X   # // Вернуться к исходному состоянию

Заключение

Интерактивное перебазирование в Git — это мощный инструмент для управления историей коммитов. С его помощью вы можете:

  • вычищать историю перед отправкой в общий репозиторий;
  • объединять мелкие исправления в крупные логичные коммиты;
  • исправлять старые ошибки без создания лишних коммитов;
  • поддерживать в репозитории аккуратную, линейную историю.

Основная идея проста: git rebase -i дает вам «черновик сценария», в котором вы описываете, что нужно сделать с каждым коммитом, а Git затем аккуратно исполняет этот сценарий.

По мере того как вы будете чаще пользоваться интерактивным rebase, он станет естественной частью вашего рабочего процесса, особенно при работе с фиче-ветками и перед созданием pull request.


Частозадаваемые технические вопросы по теме и ответы

1. Как изменить только один конкретный старый коммит, не трогая остальные?

  1. Найдите хэш коммита: bash git log --oneline
  2. Запустите rebase от родителя этого коммита: bash git rebase -i <hash>^
  3. В списке коммитов замените pick на edit у нужного коммита.
  4. После остановки: bash # Вносите изменения в файлы git add <files> # // Добавляете изменения git commit --amend # // Переписываете коммит git rebase --continue # // Продолжаете rebase

2. Как отменить уже выполненный интерактивный rebase, если результат не устроил?

Если вы еще не закрыли терминал и rebase только что был выполнен:

  1. Смотрите reflog: bash git reflog
  2. Найдите запись до начала rebase, что-то вроде "rebase: starting".
  3. Перекатитесь туда: bash git reset --hard <hash_до_rebase>

3. Что делать, если во время rebase постоянно возникают конфликты в одних и тех же файлах?

  1. Старайтесь уменьшить диапазон rebase, работая с меньшим количеством коммитов.
  2. Локализуйте конфликтующие изменения:
    • посмотрите, какие коммиты затрагивают проблемный файл: bash git log --oneline -- <file>
    • возможно, имеет смысл сначала объединить часть коммитов в один, чтобы упростить конфликты.
  3. При необходимости временно отмените rebase: bash git rebase --abort и сначала упростите историю (например, через локальный merge), затем снова запустите rebase -i.

4. Как аккуратно форсировать push после интерактивного rebase?

Используйте именно --force-with-lease, а не просто --force:

git push --force-with-lease origin feature-X

Этот вариант проверяет, не изменился ли удаленный бранч по сравнению с тем, что вы видели. Если кто-то успел запушить новые коммиты, push будет отклонен, и вы не затрете чужую работу.

5. Можно ли делать rebase -i поверх другой фиче-ветки, а не main?

Да. Просто указываете базой нужную ветку:

git rebase -i feature-Y

Git возьмет все коммиты, которые есть в вашей ветке и отсутствуют в feature-Y, и откроет интерактивный список. Дальше вы работаете так же, как при перебазировании на main. Это удобно, если ваша фича логически продолжает другую фичу.

Стрелочка влевоПросмотр дерева файлов в Git с помощью git ls-treeСбор мусора в Git с помощью git gcСтрелочка вправо

Постройте личный план изучения Git до уровня Middle — бесплатно!

Git — часть карты развития Frontend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по Git

Открыть базу знаний

Лучшие курсы по теме

изображение курса

Основы Git

Антон Ларичев
AI-тренажеры
Гарантия
Бонусы
иконка звёздочки рейтинга4.9
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий