restore, reset и revert: три способа отмены
Самая частая путаница в git: разбираем три команды отмены и раз навсегда запоминаем, какая для чего.
Коротко: restore отменяет изменения в файлах, reset двигает указатель ветки, revert создаёт обратный коммит.
Почему это путают
Все три команды «что-то отменяют», но работают на разных уровнях и с разными последствиями. Разберём каждую по отдельности, а в конце сведём в таблицу.
git restore — откатить файлы
git restore работает с содержимым файлов, не трогая историю. Два главных сценария:
git restore file.py # выбросить изменения в файле (вернуть как в последнем коммите)
git restore --staged file.py # убрать файл из индекса (но правки в файле сохранить)Первый вариант безвозвратно теряет несохранённые правки в файле — будьте осторожны. Второй просто выводит файл из staging, ничего не удаляя.
git reset — сдвинуть указатель ветки
git reset перемещает указатель текущей ветки на другой коммит, фактически «отматывая» историю назад. У него три режима, отличающихся тем, что происходит с индексом и рабочей директорией:
| Режим | История | Индекс | Файлы |
--soft | откат | сохранён | сохранены |
--mixed (по умолч.) | откат | сброшен | сохранены |
--hard | откат | сброшен | удалены |
Например, отменить последний коммит, но оставить его изменения в рабочей директории:
git reset --soft HEAD~1А вот git reset --hard уничтожает изменения безвозвратно — это самая опасная команда в этом уроке. Используйте её, только если точно понимаете, что теряете.
git revert — безопасная отмена опубликованного
git revert не стирает историю, а создаёт новый коммит, отменяющий изменения указанного коммита. История растёт вперёд, ничего не переписывается.
git revert a1b2c3dВывод:
[main e4f5g6h] Revert "Добавить экспериментальный модуль" 1 file changed, 40 deletions(-)
Главное правило выбора
Ключевой критерий — опубликован ли коммит (запушен ли он, видят ли его другие):
| Хочу... | Команда |
| выбросить правки в файле | git restore file |
| убрать файл из индекса | git restore --staged file |
| отменить локальный (не запушенный) коммит | git reset |
| отменить уже опубликованный коммит | git revert |
Никогда не используйте git reset для опубликованных коммитов — он переписывает историю и сломает её у коллег. Для этого есть revert.
Спасительный git reflog
Даже если вы случайно сделали git reset --hard и «потеряли» коммиты, чаще всего их можно вернуть. Git ведёт журнал перемещений HEAD — git reflog. В нём видны все состояния, где вы недавно были, с их хешами. Найдя нужный хеш, вы возвращаетесь к нему командой reset. Поэтому, прежде чем паниковать из-за «потерянной» работы, всегда загляните в reflog — git редко выбрасывает что-то совсем безвозвратно.
git reflog
git reset --hard a1b2c3d # вернуться к найденному состояниюСводка одной строкой
Запомните мнемонику: restore — про файлы, reset — про ветку, revert — про новый коммит-отмену. И главный предохранитель: всё, что уже опубликовано и видно другим, отменяют только через revert.
Итог
restore— про файлы и индекс, историю не трогает.resetдвигает указатель ветки;--hardопасен (удаляет изменения), только локально.revertсоздаёт обратный коммит — безопасный способ отменить опубликованное.