Ошибки при разработке – не редкость. Можно закоммитить не тот файл, забыть про опечатку в коде или случайно смешать несколько задач в одном коммите. Git – система контроля версий, которая хранит полную историю изменений проекта и позволяет откатить практически любую оплошность буквально одной командой.
В этой статье разберем, как отменять коммиты с помощью git reset и git revert и чем они отличаются друг от друга, а также рассмотрим дополнительные инструменты отката – git checkout, git restore, git merge --abort, git reflog и git commit --amend.
Три зоны Git
Прежде чем переходить к работе с командами, полезно вспомнить, как устроен Git изнутри. Любой файл в проекте последовательно проходит через три области:
- Рабочая директория (working directory) – папка на диске, где вы редактируете файлы.
- Индекс (staging area) – промежуточный буфер, в который попадают файлы после команды
git add. Именно из индекса Git берет данные для следующего коммита. - Репозиторий – хранилище, куда изменения фиксируются окончательно командой
git commit.
Таким образом, путь файла выглядит так: сначала правки вносятся в рабочей директории, затем git add переносит их в индекс, а git commit записывает их в историю репозитория в виде нового коммита.
git reset
Разберем, что делает git reset. Эта команда умеет откатывать состояние сразу в одной, двух или во всех трех зонах Git, в зависимости от того, какой режим вы укажете.
Общий вид команды:
git reset [--<режим>] [<коммит>]Где:
<коммит>– это точка в истории, к которой нужно вернуться. Например,HEAD~1– на один коммит назад,HEAD~3– на три коммита назад либо конкретный хэш коммита.<режим>– определяет, что именно произойдет с индексом и рабочей директорией. Всего есть три режима:soft,mixedиhard.
Режим soft: откат только указателя HEAD
git reset --soft двигает указатель HEAD (то есть текущую точку истории) на нужное число коммитов назад, но не трогает ни индекс, ни рабочую директорию. Все изменения, которые были в отмененном коммите, останутся проиндексированными – их не придется заново добавлять командой git add.
Синтаксис:
git reset --soft [<коммит>]Допустим, вы создали файл new-file.txt, добавили его в индекс и закоммитили с некорректным сообщением:
git add new-file.txt
git commit -m "wrong commit"Чтобы отменить этот коммит, но сохранить изменения в индексе, выполните:
git reset --soft HEAD~1Проверить результат можно командой git status – она покажет, что файл new-file.txt снова находится в состоянии «Changes to be committed», то есть готов к коммиту. Осталось сделать коммит с правильным сообщением:
git commit -m "correct commit"История репозитория остается чистой: вместо ошибочного коммита появляется корректный, а сами изменения при этом никуда не пропадают.
Режим mixed: поведение по умолчанию
Если запустить git reset без указания режима, Git применит mixed – это поведение по умолчанию. Оно отменяет последний коммит и сбрасывает индекс, но не изменяет файлы в рабочей директории: правки остаются на месте, просто перестают быть проиндексированными.
Синтаксис:
git reset --mixed [<коммит>]Допустим, вы закоммитили сразу три файла, хотя один из них, something.txt, добавлять было не нужно:
git add main_file.txt
git add updates.txt
git add something.txt
git commit -m "добавил файлы"Отменяем коммит:
git reset HEAD~1HEAD переместится на коммит назад, а все три файла снова окажутся в статусе неотслеживаемых/непроиндексированных изменений. Теперь в индекс можно добавить только нужные файлы:
git add main_file.txt
git add updates.txtИ зафиксировать новый корректный коммит:
git commit -m "Added files 1 and 2, excluding file 3"Что делает git reset hard: полный откат изменений
git reset --hard – самый радикальный вариант, предназначенный для отмены изменений. Он отменяет коммит, очищает индекс и полностью возвращает файлы в рабочей директории к состоянию указанного коммита. Все несохраненные изменения будут безвозвратно потеряны, поэтому пользоваться этим режимом стоит осторожно.
Вы случайно закоммитили ненужный файл:
git add another_new_file.txt
git commit -m "Added incorrect file"Чтобы полностью удалить этот коммит вместе с файлом из рабочего каталога:
git reset --hard HEAD~1После выполнения команды файл another_new_file.txt исчезнет не только из истории, но и с диска.
git revert
В отличие от git reset, который перемещает HEAD и может стирать коммиты из истории, git revert commit работает иначе: он создает новый коммит, который отменяет изменения указанного коммита, но при этом ничего не удаляет из истории. Это делает git revert более безопасным инструментом, что особенно важно для отмены изменений в публичных ветках, с которыми уже работают другие участники команды.
Сначала нужно найти идентификатор коммита, который требуется отменить:
git logПример вывода:
commit 2e3c670bfe46a5d7c5
Author: Ivanov Ivan <ivivanov@example.com>
Date: Fri Jul 24 15:32:46 2026 -0400
Test commitДалее выполняем отмену по хэшу коммита:
git revert 2e3c670bfe46a5d7c5Git создаст новый коммит, откатывающий указанные изменения, и откроет редактор для ввода сообщения – там можно указать причину отката. Стоит учитывать, что при отмене может возникнуть конфликт слияния, если после нужного коммита файл менялся еще раз – в этом случае конфликт придется разрешить вручную.
Если нужно отменить сразу несколько коммитов подряд одним итоговым коммитом, а не по одному, можно указать диапазон и добавить флаг --no-commit (сокращенно -n): он применит все отмены к рабочей директории и индексу, но не будет создавать коммит после каждой из них, оставив это на ваше усмотрение:
git revert --no-commit HEAD~3..HEAD
git commit -m "Откат трех последних коммитов" git reset или git revert: что выбрать
git reset подходит для локальной, еще не опубликованной работы. Он передвигает HEAD назад и, в зависимости от режима, освобождает индекс (mixed) и рабочую директорию (hard) или оставляет их нетронутыми (soft). Все три режима переписывают историю. Отмененные коммиты перестают быть частью текущей ветки, а публиковать такую переписанную историю в общий репозиторий, где уже работают другие, небезопасно.
git revert подходит, когда коммит уже отправлен в общую ветку и его видят другие участники команды. Вместо того чтобы стирать или двигать историю, git revert добавляет новый коммит, который отменяет изменения старого. История остается линейной и полной, поэтому git revert – более безопасный выбор для командной работы и публичных веток.
git checkout и git restore
Изначально команда git checkout создавалась для переключения между ветками, но ее также можно использовать, чтобы вернуть отдельный файл к состоянию последнего коммита.
Например, вы внесли и закоммитили правки в test.sh, но результат вас не устроил:
git checkout HEAD -- test.shФайл вернется к состоянию, в котором был до последнего коммита. Если нужно откатиться не к предыдущему, а к конкретному более раннему коммиту, сначала найдите его хэш через git log, а затем укажите его вместо HEAD:
git checkout [<идентификатор коммита>] -- script.shНачиная с версии Git 2.23, для восстановления файлов рекомендуется использовать более новую и однозначную по смыслу команду git restore – она была выделена из git checkout специально для отмены изменений в файлах, тогда как за переключением веток теперь закреплена отдельная команда git switch. Тот же результат, что и в примере выше, можно получить так:
git restore --source=HEAD -- test.shА для отката к более раннему коммиту:
git restore --source=[<идентификатор коммита>] -- script.shgit checkout по-прежнему работает и встречается в старых инструкциях, но для новых проектов рекомендуется использовать git restore (для файлов) и git switch (для веток) – так меньше риска перепутать назначение команды.
git merge --abort
Слияние (merge) объединяет изменения из одной ветки в другую. Если в процессе что-то пошло не так и слияние нужно прервать, выполните следующие шаги:
- Проверьте, идет ли сейчас слияние:
git statusпокажет соответствующее сообщение. - Прервите операцию:
git merge --abort. - Снова выполните
git status, чтобы убедиться, что репозиторий вернулся в исходное состояние.
git reflog
Если в процессе работы с git reset вы отменили больше, чем нужно, все действия можно восстановить с помощью команды git reflog. Она хранит полный журнал перемещений указателя HEAD – переключения веток, коммиты, сбросы. Это позволяет вернуться к любому из этих состояний.
Смотрим журнал:
git reflogВ выводе каждая строка отмечена своим индексом вида HEAD@{N}. Найдя нужную точку, возвращаемся к ней:
git reset --hard HEAD@{индекс}Таким образом можно «отменить отмену» и восстановить коммиты, которые казались потерянными.
git reflog хранятся не бесконечно: по умолчанию Git удаляет их примерно через 90 дней для коммитов, которые еще достижимы из текущих веток, и через 30 дней – для тех, которые уже ничем не удерживаются. Поэтому git reflog – это подстраховка на ближайшее время, а не постоянный архив, и восстанавливать нужные коммиты стоит как можно быстрее после ошибки. Редактирование истории коммитов
Изменение текста последнего коммита
Если нужно поправить только сообщение последнего коммита (или добавить в него забытые изменения из индекса), используется команда:
git commit --amendОна не создает новый коммит, а объединяет содержимое индекса с предыдущим коммитом и позволяет отредактировать его сообщение. Для Git такой измененный коммит выглядит как совершенно новый – у него меняется хэш.
Объединение нескольких коммитов в один
Для склеивания нескольких последних коммитов в один применяется интерактивный режим перебазирования:
git rebase -i HEAD~3Команда откроет в текстовом редакторе список последних трех коммитов, например:
pick hfdjhj23 что-то исправляем
pick 5556f9n классное изменение
pick egrhth1 последнее изменениеЧтобы объединить второй и третий коммит с первым, замените команду pick на squash у тех коммитов, которые нужно слить:
pick hfdjhj23 что-то исправляем
squash 5556f9n классное изменение
squash egrhth1 последнее изменениеПосле сохранения файла Git предложит объединить сообщения коммитов в одно – его можно отредактировать. Проверить результат удобно командой git log.
Заключение
Git – незаменимый инструмент для контроля версий, который избавляет от страха потерять код или чужие правки: практически любое действие можно отменить или исправить.
Освоив команды из данной статьи, вы сможете уверенно исправлять ошибки в истории проекта и не бояться экспериментировать с кодом, а о том, как установить и настроить Git на сервере Ubuntu 22.04, вы можете узнать из отдельной инструкции.
git reset, git commit --amend и git rebase – переписывают историю коммитов. У измененных коммитов меняется хэш, а старые версии как будто исчезают из истории. Если такие коммиты уже отправлены (запушены) в общий репозиторий и с ними мог начать работать кто-то из команды, переписывать их не стоит, так как локальная история разойдется с удаленной, что приведет к конфликтам и потере чужих изменений.Если возникнут вопросы, напишите нам, пожалуйста, тикет из панели управления аккаунта (раздел “Помощь и поддержка”), а если вы захотите обсудить эту статью или наши продукты с коллегами по цеху и сотрудниками Beget – ждем вас в нашем сообществе в Telegram.