Чтобы отменить последний локальный коммит и сохранить все изменения подготовленными к повторному коммиту, выполните:
git reset --soft HEAD~1
Команда переместит указатель текущей ветки на один коммит назад, но не изменит индекс и рабочие файлы. Изменения из отменённого коммита останутся в состоянии staged, поэтому их можно сразу закоммитить заново.
Предпосылки и ограничения
- Команда должна выполняться внутри нужного Git-репозитория.
- Текущая ветка должна содержать хотя бы один родительский коммит.
- Отменяемый коммит не должен быть опубликован в общей удалённой ветке, если переписывание истории не согласовано с другими участниками.
- Незакоммиченные изменения, существовавшие до выполнения команды, также останутся в рабочем каталоге и индексе.
Сначала проверьте текущий репозиторий и последние коммиты:
git status
git log --oneline -3
Убедитесь, что верхняя строка журнала соответствует коммиту, который требуется отменить. После этого выполните мягкий сброс:
git reset --soft HEAD~1
Обозначение HEAD~1 указывает на первого предка текущего коммита, то есть на предыдущий коммит в истории текущей ветки.
Проверка результата
После сброса проверьте состояние репозитория:
git status
Файлы отменённого коммита должны отображаться в разделе изменений, подготовленных к коммиту. Дополнительно можно проверить содержимое индекса:
git diff --cached
Команда покажет изменения, которые войдут в следующий коммит. Чтобы убедиться, что последний коммит действительно удалён из текущей истории ветки, снова посмотрите журнал:
git log --oneline -3
Бывший последний коммит больше не должен быть вершиной текущей ветки. Его данные при этом обычно ещё доступны через журнал перемещений ссылок Git, поэтому ошибочный сброс можно восстановить.
Повторный коммит после исправлений
Если содержимое файлов менять не требуется, создайте новый коммит с исправленным сообщением:
git commit -m "Исправленное сообщение коммита"
Если нужно изменить файлы, отредактируйте их, затем добавьте исправления в индекс:
git add путь/к/файлу
git commit -m "Исправленное сообщение коммита"
Для добавления всех отслеживаемых и новых файлов из текущего каталога используйте:
git add .
git commit -m "Исправленное сообщение коммита"
Перед повторным коммитом рекомендуется проверить подготовленный набор изменений:
git diff --cached
Как оставить изменения неподготовленными
Если после отмены коммита изменения должны остаться в рабочих файлах, но не в индексе, используйте смешанный сброс:
git reset --mixed HEAD~1
Параметр --mixed является стандартным режимом команды git reset, поэтому допустима сокращённая запись:
git reset HEAD~1
В этом режиме Git перемещает текущую ветку на предыдущий коммит и обновляет индекс, но не перезаписывает рабочие файлы. После выполнения изменения будут отображаться как неподготовленные:
git status
git diff
Далее можно выборочно подготовить нужные файлы:
git add путь/к/первому-файлу
git add путь/к/второму-файлу
git commit -m "Новое сообщение коммита"
| Команда | Положение HEAD | Индекс | Рабочие файлы |
|---|---|---|---|
git reset --soft HEAD~1 |
Перемещается назад | Не изменяется | Не изменяются |
git reset --mixed HEAD~1 |
Перемещается назад | Сбрасывается к выбранному коммиту | Не изменяются |
git reset --hard HEAD~1 |
Перемещается назад | Сбрасывается | Перезаписываются |
Не используйте
git reset --hard HEAD~1для этой задачи. Режим--hardобновляет не только историю и индекс, но и рабочее дерево. Незакоммиченные изменения в затронутых файлах могут быть потеряны.
Если нужно исправить только последний коммит
Отменять коммит необязательно, если требуется лишь изменить его сообщение или добавить забытые изменения. Для локального последнего коммита можно использовать git commit --amend.
Чтобы изменить только сообщение, выполните:
git commit --amend
Git откроет настроенный редактор сообщения коммита. Для передачи нового сообщения непосредственно в командной строке:
git commit --amend -m "Исправленное сообщение коммита"
Чтобы добавить забытый файл в последний коммит:
git add путь/к/файлу
git commit --amend --no-edit
Параметр --no-edit сохраняет прежнее сообщение. Операция amend создаёт новый объект коммита с другим идентификатором, поэтому применять её к уже опубликованной общей истории следует только при понимании последствий.
Что делать, если коммит уже отправлен на сервер
Если последний коммит уже попал в ветку, которой пользуются другие разработчики, безопаснее не переписывать историю, а создать обратный коммит:
git revert HEAD
git revert создаёт новый коммит, отменяющий изменения выбранного коммита. Существующая история при этом сохраняется. Такой подход обычно предпочтительнее для общих веток.
После выполнения проверьте результат:
git status
git log --oneline -3
git show --stat HEAD
Если опубликованный коммит принадлежит только вашей личной ветке и историю допустимо переписать, технически можно применить reset и затем принудительно обновить удалённую ветку. Однако это уже отдельная операция с риском перезаписи чужих изменений. Для простой отмены локального коммита принудительная отправка не требуется.
Восстановление после ошибочного reset
Git записывает перемещения HEAD в журнал ссылок. Посмотреть недавние позиции можно командой:
git reflog
Найдите запись, соответствующую состоянию до сброса. Она может выглядеть как ссылка вида HEAD@{1}, но фактический номер зависит от последующих операций. Не используйте номер из примера без проверки собственного вывода.
Для возврата ветки к найденному коммиту укажите его идентификатор:
git reset --soft <идентификатор-коммита>
Если требуется полностью вернуть ветку, индекс и рабочее дерево к найденному состоянию, применяется --hard, но только после сохранения всех нужных незакоммиченных файлов:
git reset --hard <идентификатор-коммита>
Перед такой операцией можно создать страховочную ветку:
git branch backup-before-recovery
Проверка версии и локальной документации
Описанные режимы относятся к стандартной команде Git reset. Установленную версию можно проверить так:
git --version
Точные правила для установленной версии доступны во встроенной документации:
git help reset
git help commit
git help revert
git help reflog
Это особенно полезно в окружениях, где используется старая или модифицированная сборка Git.
Итоговый чек-лист
- Выполнить
git statusи убедиться, что открыт нужный репозиторий. - Проверить последний коммит через
git log --oneline -3. - Для сохранения изменений в индексе выполнить
git reset --soft HEAD~1. - Для сохранения изменений только в рабочих файлах выполнить
git reset --mixed HEAD~1. - Проверить результат командами
git statusиgit diff --cached. - Исправить файлы или сообщение и создать новый коммит.
- Не применять
--hard, если требуется сохранить изменения. - Для уже опубликованного общего коммита рассмотреть
git revert HEADвместо переписывания истории.