Урок курса

Исправить последний собственный коммит

Git и GitHub с нуля: бесплатный курс с практикой

git log --oneline и git show читают историю, а git restore восстанавливает рабочий файл из текущего индекса, не меняя коммиты. git commit --amend заменяет последний собственный неопубликованный коммит снимком индекса и выбранным сообщением.

Механизм git commit --amend: замена коммита новым объектом

Когда вы выполняете git commit --amend, Git не редактирует существующий коммит на месте. Вместо этого он формирует замещающий коммит: берёт снимок из текущего индекса, прикрепляет к нему родителей прежнего последнего коммита, и записывает его как новую вершину истории. Прежний коммит при этом перестаёт быть последним в текущей ветке, но сам объект в хранилище Git никуда не исчезает — он просто больше не виден в обычном git log.

Из этого вытекает ключевое следствие: в рассматриваемых исправлениях меняется сообщение или снимок, поэтому ID замещающего коммита отличается от прежнего. Хеш вычисляется по всему содержимому коммита — снимку файлов, сообщению, временной метке, данным об авторе, ссылке на родителей. Даже если вы поменяли только одну букву в сообщении и индекс остался прежним, хеш будет другим.

Визуально в git log --oneline вы увидите ту же одну строку на месте последнего коммита — но с другим идентификатором. Количество коммитов в истории не изменится: amend заменяет последний, а не добавляет новый поверх него.

Граница безопасного применения amend

Смена хеша при amend — не просто техническая деталь. Если коммит уже опубликован (отправлен в удалённый репозиторий), его хеш известен другим участникам проекта: они могут работать поверх него, ссылаться на него в ветках или задачах. Когда вы заменяете такой коммит через amend, ваша локальная история расходится с общей. При следующей попытке отправить изменения Git откажет, потому что истории больше не совпадают. Коллеги, уже скачавшие прежний коммит, окажутся в ситуации, когда их история и ваша описывают одно место в репозитории по-разному.

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

Важно не попасться на интуитивно привлекательное исключение: «я исправил только опечатку в сообщении, снимок файлов не тронул — хеш же останется тем же?» Нет. Сообщение коммита входит в данные, по которым вычисляется хеш. Если сообщение фактически изменилось, хеш изменится тоже, независимо от того, совпадают ли снимки файлов. Это означает, что даже косметическая правка в сообщении уже опубликованного коммита создаёт расхождение истории.

Исправление сообщения и добавление забытого файла через amend

Есть две типичные ситуации, когда нужен amend: неточное сообщение или забытый файл.

Создайте новую отдельную учебную папку и откройте в ней терминал. Выполните команды по одной:

git init -b main
git config user.name "Учебный автор"
git config user.email "learner@example.invalid"

В обычном текстовом редакторе создайте README.md со строкой «# Проект», сохраните файл. Затем выполните:

git add README.md
git commit -m "Добавить данные"
git status

В этой папке main содержит один коммит, файл отслеживается, рабочая папка и индекс чисты. Это первый и единственный собственный коммит опыта; его ещё никуда не отправляли. До исправления выполните git log --oneline и запишите его фактический ID и сообщение. Оба дальнейших исправления относятся к этому одному коммиту.

Исправить только сообщение

Перед тем как менять сообщение, убедитесь, что в индексе нет посторонних изменений:

git diff --staged

Вывод должен быть пустым. Если он не пуст, в заменяющий коммит войдут не только правки сообщения, но и всё, что сейчас в индексе — это может быть нежелательно.

Когда diff пуст, выполните:

git commit --amend -m "docs: добавить README"

Флаг --amend сообщает Git, что нужно создать замещающий коммит вместо последнего. Флаг -m передаёт новое сообщение напрямую, без открытия редактора. Git берёт снимок из текущего индекса — а поскольку индекс чистый, снимок файлов останется таким же, каким был в исходном коммите.

Добавить забытый файл

Допустим, вы уже сделали amend с новым сообщением, но вспомнили, что забыли добавить CHANGELOG.md. Создайте в текстовом редакторе CHANGELOG.md со строкой «история изменений», сохраните его, затем:

git add CHANGELOG.md

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

git diff --staged

Вы должны увидеть только добавление CHANGELOG.md. Если в вывод попало что-то лишнее — разберитесь с этим до amend, иначе лишнее тоже войдёт в коммит.

Теперь выполните:

git commit --amend --no-edit

Флаг --no-edit говорит Git сохранить сообщение последнего коммита без изменений и не открывать редактор. Git создаст замещающий коммит с полным снимком текущего индекса — то есть со всеми ранее отслеживаемыми файлами плюс новым CHANGELOG.md. Хеш снова изменится, сообщение "docs: добавить README" останется.

Что показывает git log --oneline и git show после amend

Чтобы убедиться, что amend сработал правильно, достаточно двух команд, которые вы уже знаете: git log --oneline и git show.

git log --oneline выводит по одной строке на каждый коммит: сначала короткий хеш, затем сообщение. Сравните вывод до и после amend. Ниже условные допустимые шестнадцатеричные ID; ваши фактические значения будут другими:

# до amend
a1b2c3d Добавить данные

# после amend -m
e4f5a6b docs: добавить README

# после amend --no-edit с добавлением CHANGELOG.md
c7d8e9f docs: добавить README

Три наблюдаемых признака корректной работы:

  • Количество строк в git log --oneline не изменилось — коммитов столько же, сколько было.
  • Хеш в первой строке отличается от предыдущего после каждого amend.
  • Сообщение соответствует тому, что вы передали в -m или оставили через --no-edit.

git log --oneline не показывает, какие файлы вошли в коммит. Для этого нужен git show — он выведет метаданные коммита и diff по каждому изменённому файлу:

git show

В подготовленном опыте заменяется первый и единственный коммит, поэтому после amend с добавлением CHANGELOG.md вы увидите в его diff оба файла — и README.md (добавленный изначально), и CHANGELOG.md (добавленный через amend). Если CHANGELOG.md в выводе git show есть — amend включил его в снимок корректно.

В этих двух исправлениях новое сообщение и добавленный файл дают другой ID. При попытке amend без изменения сообщения и снимка одного сравнения ID недостаточно: на него влияют также метаданные коммитера, включая время. При изменении этих данных ID может смениться; при совпадении всех данных может остаться тем же. Неизменный ID сам по себе не доказывает отказ команды или пропуск amend. Проверяйте нужное сообщение и снимок по log и show.

Задача 1

Последний собственный коммит учебного репозитория ещё не публиковался. Автор изменил и подготовил notes.md, но теперь выполняет git commit --amend -m "Исправленное описание". Сообщение отличается от прежнего. Что попадёт в заменяющий коммит?

Выберите один вариант
Без регистрации · результат не сохраняется

Задача 2

Нужно исправить сообщение одного коммита через amend по правилу этого курса. Какой кандидат соответствует разрешённому учебному случаю?

Выберите один вариант
Без регистрации · результат не сохраняется

Задача 3

Практика: создайте отдельный учебный репозиторий известным циклом init -b main, обе локальные настройки автора, README через редактор, add и commit. Индекс чист, коммит ваш и нигде не публиковался. Исправьте его сообщение на «docs: добавить README», предварительно проверив staged diff. Затем создайте CHANGELOG.md через редактор, подготовьте файл и включите его в последний коммит без редактирования сообщения. Проверьте историю и diff через show. Запишите ID и сообщения до и после каждого amend, количество коммитов и файлы, показанные diff итогового коммита. Письменно объясните коллеге, почему новый текст сообщения меняет ID даже при прежнем снимке файлов.

Платформа проверяет только ответ ниже; действия в своём репозитории и письменные ответы вы проверяете самостоятельно.

В отдельном контрольном случае до amend было три коммита. Через add подготовили новый забытый файл и выполнили amend --no-edit. Как проверить смысл получившегося результата?

Выберите один вариант
Без регистрации · результат не сохраняется

Продолжить с сохранением прогресса

Перейдите к уроку в учебном кабинете.

Перейти к интерактивному уроку