Git: как отменить последний коммит — reset, revert, amend

Категория: Git · Язык: Bash · Обновлено:

Чтобы отменить последний коммит в Git и сохранить изменения, выполните git reset --soft HEAD~1. Если коммит уже отправлен на сервер, используйте git revert HEAD: он не переписывает историю.

Какой способ выбрать

Ситуация

Команда

Что станет с изменениями

Коммит только локальный, изменения нужны

git reset --soft HEAD~1

Остаются в индексе (staged)

Коммит только локальный, хочу пересобрать индекс

git reset HEAD~1

Остаются в рабочей папке, не в индексе

Коммит только локальный, изменения не нужны

git reset --hard HEAD~1

Удаляются

Коммит уже на сервере (push выполнен)

git revert HEAD

Создаётся новый коммит, отменяющий старый

Опечатка в сообщении или забыт файл

git commit --amend

Добавляются в тот же коммит

Отменить коммит и сохранить изменения

HEAD~1 означает «на один коммит назад от текущего». Сам коммит исчезнет из истории ветки, а правки останутся у вас.

Bash
# изменения остаются в индексе — можно сразу делать новый git commit
git reset --soft HEAD~1

# изменения остаются в рабочей папке, но не добавлены в индекс
git reset HEAD~1

Режим --mixed используется по умолчанию, поэтому git reset HEAD~1 и git reset --mixed HEAD~1 делают одно и то же. Новые файлы после такой отмены отображаются как неотслеживаемые (?? в git status --short).

Отменить коммит и удалить изменения

Bash
git reset --hard HEAD~1

Если вы отменили коммит по ошибке, его ещё можно вернуть: git хранит записи о перемещениях HEAD в журнале reflog.

Bash
git reflog                 # найдите строку с нужным коммитом, например HEAD@{1}
git reset --hard HEAD@{1}  # вернуться к состоянию до отмены

Сразу после reset в ORIG_HEAD хранится прежнее положение ветки, поэтому часто достаточно git reset --hard ORIG_HEAD.

Отменить коммит, который уже отправлен на сервер

Если коллеги могли забрать ваш коммит, историю переписывать нельзя. git revert создаёт новый коммит с обратными изменениями, и история остаётся целой.

Bash
git revert HEAD            # откроет редактор для сообщения нового коммита
git revert --no-edit HEAD  # оставить сообщение по умолчанию
git push

Если всё же нужно убрать коммит из удалённой ветки (например, в личной ветке, которую никто не использует), перепишите историю и отправьте её принудительно с защитой от перезаписи чужой работы:

Bash
git reset --soft HEAD~1
git push --force-with-lease

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

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

Bash
git commit --amend -m "Новое сообщение коммита"   # изменить сообщение

git add forgotten-file.txt
git commit --amend --no-edit                      # добавить файл в тот же коммит

amend тоже переписывает историю, поэтому для уже отправленных коммитов действуют те же ограничения, что и для reset.

Как проверить результат

Bash
git status --short    # что осталось в индексе и рабочей папке
git log --oneline -3  # последние три коммита

Частые вопросы

Как отменить последний коммит, но оставить файлы на диске?

Выполните git reset HEAD~1. Коммит исчезнет, а файлы останутся изменёнными в рабочей папке.

Как отменить несколько последних коммитов?

Укажите нужное число: git reset --soft HEAD~3 отменит три последних коммита и сохранит все их изменения в индексе.

Можно ли вернуть коммит после git reset --hard?

Обычно да, пока он не удалён сборщиком мусора: найдите его хеш в git reflog и выполните git reset --hard <хеш>. Незакоммиченные правки, потерянные из-за --hard, этим способом не восстановить.

Чем отличаются reset и revert?

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