Перейти к содержанию

Возврат опубликованного изменения

Представим, что в каталог попала ошибочная ссылка: адрес курса изменили, но страницу по новому пути не создали. После этого другой автор добавил полезную заметку README. Хочется вернуть рабочий URL, сохранив эту заметку и не стирая историю, на которую уже могла опираться общая работа.

Для такого случая подходит git revert: он создаёт новый коммит с обратным изменением выбранного коммита. Рассмотрим это на нашем каталоге и различим исправление исходников и действительный возврат сайта на хостинге. Оглавление курса и архив дают сценарий lesson-08. Все действия здесь подготовлены локально и ещё не выполнялись; публикация моделируется, а не производится.

Ошибочный адрес и последующая задача

Начните с чистой основной линии после предыдущего урока. В README есть заметка о согласовании изменений, в CSS — отступ каталога. В content/courses.md измените только URL ссылки JavaScript: вместо /courses/javascript/ укажите /courses/javascript-next/. Название ссылки оставьте прежним.

- [JavaScript](/courses/javascript-next/)
- [HTML и CSS](/courses/html-css/)

Это полный изменяемый список, остальная часть Markdown сохраняется. В модели курса по новому адресу нет страницы. Следовательно, задача меняет не только косметику текста: она разрывает переход с каталога. Как при обновлении старого ProfessorWeb, постоянный путь является частью договора с существующими ссылками.

Сохраните ошибочное изменение в отдельном лабораторном коммите:

git add content/courses.md
git commit -m "Изменить адрес курса JavaScript"
git log -1 --oneline

Обозначим его U и запишите действительный идентификатор из своего лога. Затем добавьте в конец README абзац «Пример содержит два курса.» и сохраните его отдельным коммитом:

git add README.md
git commit -m "Уточнить состав учебного примера"
git log --oneline -3

Второй коммит обозначим V. История теперь содержит U, затем V; текущий снимок включает и неверную ссылку, и полезную заметку. В нашей лаборатории ни один коммит не отправляется на сервер. Предположим для разбора, что U уже стал общей точкой работы, поэтому хотим сохранить существующие вершины.

Выбор обратного изменения

Сначала прочитайте выбранный коммит. В следующем фрагменте ACTUAL_COMMIT_ID — заполнитель, который нужно заменить настоящим идентификатором U, а не набирать буквально:

git show ACTUAL_COMMIT_ID -- content/courses.md
git status --short
git revert ACTUAL_COMMIT_ID

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

Ожидается новый коммит R, в котором URL вновь /courses/javascript/. README при этом продолжает содержать абзац «Пример содержит два курса.». В отличие от возврата всей папки к старому снимку, обратная операция относится к изменению выбранного U, а не отменяет автоматически все последующие задачи.

… — U — V — R  main

Оба прежних коммита остаются в истории. Их идентификаторы не заменяются новыми. Поэтому разработчик, который уже видел U и V, может получить дополнительный шаг R, сохранив связь с прежними вершинами. Новая запись также объясняет причину изменения: проблема обнаружена после первоначального решения.

Документация git-revert описывает запись обратных изменений. Для каталога это удобная модель исправления: история показывает ошибку и её устранение, а текущий снимок возвращает нужный путь. Она не требует считать старую правку никогда не существовавшей.

Содержимое после возврата

Прочитайте текущий Markdown и README, затем сравните последнее изменение:

git show --stat --oneline HEAD
git show HEAD -- content/courses.md
git status --short

В нашем заданном случае ожидается обратная замена одной ссылки. Пустой статус подтверждает завершение записи. Как и раньше, точный хеш и сообщение, добавленное редактором, могут отличаться. Значимым результатом является текущий URL и сохранение независимого абзаца README.

Обратите внимание: Git не проверяет, существует ли страница по восстановленному адресу. Эта предпосылка задана моделью проекта. В реальном сайте после исправления исходников нужно отдельно построить страницы и проверить ссылки в подходящем окружении. Наш текущий режим не выполняет тесты, учебные команды или публикацию, поэтому здесь речь только о подготовленном сценарии.

Revert не является резервной копией сервера и не меняет хостинг. Даже после создания R опубликованный сайт может продолжать показывать прежние файлы до отдельного выпуска. Сохранённый исходник и доступная посетителю версия имеют разные жизненные циклы. Это различие помогает обсуждать исправление, не приписывая локальному коммиту несуществующий деплой.

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

Наши U и V меняют разные файлы, поэтому обратная замена не должна затрагивать заметку. Если после U другой коммит снова изменил ту же строку ссылки, обратное применение может остановиться с конфликтом. Git не знает, какую из последующих редакционных целей нужно сохранить.

В таком случае прочитайте статус, исправьте итоговый файл по смыслу и добавьте выбранное решение. Для действительно начатой операции доступны:

git add content/courses.md
git revert --continue

Если решили отказаться до завершения, используйте git revert --abort. Эти команды относятся к состоянию незавершённого revert. Не вызывайте --continue после уже успешно созданного обратного коммита: операция к тому моменту закончена. Само отсутствие маркеров не доказывает, что все нужные правки согласованы, поэтому читайте соседний текст.

Отмена merge-коммита требует ещё выбрать основного родителя и имеет дополнительные последствия для будущих слияний. Наш U — обычный коммит с одним родителем, поэтому соответствующий параметр здесь не нужен. Не подставляйте номер родителя наугад, если позднее задача касается объединения большой ветки.

Также обратный коммит не удаляет старые данные из истории. Если проблема была в раскрытом секрете, возврат текста не лишит старое значение доступа и не скроет его в U. Для учебной ссылки это не препятствие: нам важно восстановить адрес и сохранить объяснение ошибки. Для разных видов проблемы требуются разные действия.

Перед обратной записью полезно сформулировать желаемый текущий результат независимо от команд: ссылка опять ведёт на постоянный путь, заметка README остаётся. Эта формулировка помогает не перепутать возврат одной задачи с возвратом всего состояния проекта. Если после операции ссылки исправлены, но другая полезная работа исчезла, механический успех команды не означает выполнения требования. В нашем сценарии разные файлы позволяют увидеть это различие особенно ясно.

Первый блок курса завершён: у нас есть модель индекса, веток, объединения, переноса локальной истории и обратной записи. В плане дальше — восстановление отдельных файлов, поиск причины изменения, удалённые репозитории и инструменты браузера. Эти уроки пока готовятся; их последовательность можно увидеть в оглавлении курса.