Как отменить последний коммит
Как отменить
Способ зависит от того, отправлен ли коммит на сервер. Если не помните, посмотрите git status: строка Your branch is ahead of 'origin/main' (в русской версии Git — «Ваша ветка опережает…») значит, что коммит пока есть только у вас.
Коммит ещё не отправленуберите его
Уберите коммит, оставив изменения в файлах:
git reset --soft HEAD~1Коммит исчезнет из истории, а все его изменения вернутся в индекс — как будто вы только что сделали git add. Можно поправить файлы и закоммитить заново. HEAD~1 — коммит перед текущим; убрать два последних — HEAD~2.
Коммит уже отправлен (git push)отмените его новым коммитом
Не удаляйте отправленный коммит, а отмените его новым коммитом с обратными изменениями:
git revert HEAD
git pushПочему так — в разделе Почему отправленный коммит не убирают через reset.
Какой вариант выбрать
| Нужно | Команда |
|---|---|
| Убрать коммит, изменения оставить в индексе | git reset --soft HEAD~1 |
| Убрать коммит, изменения оставить в файлах, но не в индексе | git reset HEAD~1 |
| Убрать коммит вместе с изменениями | git reset --hard HEAD~1 |
| Отменить отправленный коммит | git revert HEAD |
| Только поправить сообщение или добавить забытый файл | git commit --amend — см. Как изменить сообщение коммита |
git reset --hard удаляет изменения убранного коммита и все незакоммиченные правки в рабочей папке. Перед ним проверьте git status: если там есть нужные правки, сначала сохраните их коммитом или через git stash.
Почему отправленный коммит не убирают через reset
reset переписывает историю: у вас коммита больше нет, а на сервере и у коллег он остался. Обычный git push после этого откажется, а принудительный (--force) заменит историю на сервере — и у всех, кто уже забрал коммит, история разойдётся с сервером. git revert ничего не переписывает: он добавляет коммит с обратными изменениями, и обмен идёт как обычно.
Отменить так можно любой коммит, не только последний: git revert 3e677f8. Если коммит — слияние веток, Git попросит указать сторону: git revert -m 1 хеш (1 — основная ветка, в которую сливали).
Если убрали лишнее
После git reset --hard коммит ещё можно найти. Команда git reflog показывает, где был HEAD после каждой команды:
$ git reflog
27ca428 (HEAD -> main) HEAD@{0}: reset: moving to HEAD~1
00bcdfd HEAD@{1}: commit: Третий пунктСтрока commit перед reset — нужный коммит. Верните ветку на него:
git reset --hard 00bcdfdНезакоммиченные правки, удалённые reset --hard, так не вернуть — их нет в истории.
Подводные камни
- Самый первый коммит так не убрать: перед ним ничего нет, и
HEAD~1даёт ошибкуambiguous argument 'HEAD~1'. Для него естьgit update-ref -d HEAD— коммит исчезнет, а файлы останутся в рабочей папке и в индексе, как перед первымgit commit. - В командной строке Windows (cmd) знак
^служебный, поэтому в инструкциях сHEAD^пишитеHEAD~1— это одно и то же.