Rebase: новая база для своей неопубликованной работы
Основная линия продвинулась
Вы начали небольшую правку от старого main. Пока работали, main получил новое описание. Хотите проверить свою правку поверх актуальной основы до публикации. Merge сохранит обе линии и их интеграцию, а rebase воспроизведёт изменения ваших коммитов на новой базе. Это выбор формы истории, а не автоматическое улучшение качества кода.
Rebase создаёт новые коммиты. Изменения могут выглядеть одинаково, но родители другие, поэтому идентификаторы тоже меняются. Старые объекты не «редактируются внутри». Ссылка рабочей ветки переходит на новую последовательность. Даже понятные сообщения не означают, что история осталась прежней.
Граница курса проста: переписывайте только собственные коммиты, на которые другие люди ещё не опираются. Не применяйте rebase к main общей точки и не решайте последующий отказ push принуждением. Если ветку уже получили коллеги, обсудите способ интеграции и используйте сохранение общей истории. Руководство rebase отдельно разбирает последствия переписывания upstream.
Наблюдайте изменение родителей
lab=$(mktemp -d "${TMPDIR:-/tmp}/git-10.XXXXXX")
cd "$lab"
git init -b main
git config user.name "Учебный автор"
git config user.email "learner@example.invalid"
git config commit.gpgsign false
printf 'Project\n' > README.txt
git add README.txt
git commit -m "Add base description"
git switch -c topic
printf 'queue=16\n' > queue.txt
git add queue.txt
git commit -m "Add queue limit"
printf 'workers=2\n' > workers.txt
git add workers.txt
git commit -m "Add worker limit"
git branch topic-before
git switch main
printf 'Project\nRun locally\n' > README.txt
git add README.txt
git commit -m "Document launch"
git switch topic
git log --graph --oneline --all
git rebase main
git log --graph --oneline --all
git diff topic-before topicДо rebase topic расходится с main от первого коммита. После её новые записи идут поверх Document launch. Topic-before сохраняет прежнюю линию для сравнения. Diff между прежней и новой вершиной содержит добавленную инструкцию main; файлы лимитов должны остаться такими же. Наличие дополнительной старой ветки в graph не является провалом rebase: мы специально оставили её как доказательство.
Проверьте родителей через git log --format='%h %p %s' main..topic. Их цепочка начинается от нового main. Переключитесь в main и выполните git merge --ff-only topic: теперь возможен fast-forward, потому что новые коммиты продолжают основную линию. Это действие не требует удалённого сервера или force push.
Конфликт во время воспроизведения
Если новая база меняет ту же строку, что ваш коммит, rebase остановится на попытке воспроизвести конкретное изменение. Прочитайте status и текущую правку через git rebase --show-current-patch, исправьте файл, добавьте его и вызовите git rebase --continue. Для отказа от всего опыта используйте git rebase --abort. Не запускайте обычный новый commit вместо продолжения, не понимая текущего состояния.
Обозначения ours/theirs во время rebase легко спутать с merge: операция воспроизводит ваши изменения на выбранной базе. Не выбирайте сторону по привычному слову. Прочитайте исходное требование и оба содержимых варианта, затем проверьте результат. Конфликт здесь снова означает отсутствие автоматического решения, а не указание «правильной» стороны.
Подготовка своей серии
Интерактивный git rebase -i main позволяет пересобрать неопубликованную серию: оставить записи, изменить сообщения, объединить соседние коммиты. Он открывает редактор списка действий. Прежде чем пользоваться, создайте ветку сохранения, прочитайте строки и инструкции, убедитесь, что выбран нужный диапазон. В обязательном опыте достаточно обычного rebase; интерактивную форму можно исследовать на отдельной копии.
Пересборка ради одного красивого коммита может скрыть полезные этапы рассуждения. Согласуйте ожидаемую форму с проверяющим. Для большой независимой правки одно сообщение всё равно не объяснит все причины. Проверяемость каждого состояния и ясное содержание важнее соревнования по минимальному числу точек в graph.
Проверьте результат независимо от формы графа
После rebase ваши лимиты остались, а новое описание main тоже появилось. Достаточно ли этого? Для учебного текста сравните файлы и договор; для программы понадобится повторить проверку поведения. Новая база могла изменить предпосылку вашей правки, даже если конфликт не возник. На собственной серии сначала назовите, от чего она зависит, затем подтвердите это на новой основе.
Посмотрите и промежуточные коммиты: если первый уже требует файл, появляющийся только во втором, такую серию неудобно проверять по шагам. Решение зависит от договорённости ревью, а не только от линейности. Запишите, что хотите сохранить для проверяющего: отдельные законченные шаги или один согласованный снимок. Rebase помогает оформить личную работу, но не принимает этот выбор за вас.
Самостоятельная лаборатория
Практика — 40–60 минут. Повторите опыт с собственными файлами. Запишите хеши двух старых коммитов, создайте backup-ветку, обновите main и выполните rebase. Найдите новые хеши и объясните различие родителей. Сравните содержимое своих файлов до и после, а не только итоговый graph.
Во второй новой временной папке устройте конфликт одной строки. Сначала отмените rebase и подтвердите возврат ветки; затем повторите и разрешите осмысленно. Сохраните короткую записку: какие коммиты были личными и почему их допустимо переписать. Не публикуйте обе альтернативные истории в общий проект ради демонстрации.
Критерии готовности
Ваши файлы сохранили требуемое поведение, новая серия продолжает main, старые хеши доступны через backup. Вы знаете continue и abort, объясняете, почему переписанная общая ветка заставила бы других авторов чинить свои линии.
Разбор
Если хеши не изменились, возможно новая база уже являлась основанием и Gitу нечего было воспроизводить.
Следующая глава покажет перенос одной правки и временное откладывание текста. Дополнительные первичные источники: reflog для наблюдения перемещений и merge для сравнения формы интеграции.