6. История

Сброс состояния ветки

Иногда хочется отменить целую серию коммитов и вернуть ветку в прошлое.

Представь ситуацию: я экспериментирую с новыми возможностями в отдельной ветке, но после пары коммитов понимаю, что идея провальная. Я хочу выбросить все эти экспериментальные коммиты и начать заново с того места, где ветка отделилась от main.

Что делать в таком случае?

Здесь на помощь приходит команда

. Чтобы воспроизвести эту ситуацию, давай сначала создадим ветку experiment.

Запустить в терминале:
git switch -c experiment
Задача
Пройдено

Создай ветку experiment и переключись на неё.

Отлично! Теперь создай файл experiment.html. Впиши в него строку This is an experiment., подготовь и закоммить изменения.

Задача
Пройдено

Выполни все действия из текста выше.

Супер! Теперь удали строку <!DOCTYPE html> из файла hello.html, подготовь и закоммить.

Задача
Пройдено

Выполни все действия из текста выше.

Итак, допустим, на этом этапе я протрезвел осознал, что эксперимент зашёл в тупик. Я хочу сбросить ветку experiment до изначального состояния и избавиться от всех экспериментальных коммитов.

Для этого можно использовать команду git reset, добавив к ней ссылку на коммит, к которому мы хотим откатиться. В нашем случае это тот самый коммит, от которого изначально ответвилась experiment. То есть последний коммит в ветке main. А значит, вместо хеша коммита можно просто указать имя ветки, на которую мы ориентируемся: main.

Запустить в терминале:
git reset main
Задача
Пройдено

Сбрось ветку experiment к последнему коммиту из main.

Если сейчас проверить статус репозитория, мы увидим, что файл experiment.html всё ещё на месте, но Git считает его untracked. То есть он не подготовлен и не закоммичен.

Если заглянуть в hello.html, то строки <!DOCTYPE html> там по-прежнему нет. Выходит, рабочее дерево не изменилось. В нём всё так же лежат наши экспериментальные правки.

Хм... так что же тогда изменилось?

Git передвинул указатель ветки на тот же коммит, что и main. Коммиты, которые мы сделали в ветке experiment, больше не входят в её историю. Это называется смешанным сбросом (mixed reset) — коммиты удалились, изменения остались в рабочем дереве, но пропали из области подготовки.

Если мы хотим сохранить эти правки, их можно заново подготовить и закоммитить, как обычно. Иногда именно это и нужно. Например, чтобы объединить несколько мелких коммитов в один осмысленный или наоборот — разбить гигантский коммит на несколько маленьких.

Но в нашей ситуации задача другая — окончательно избавиться от экспериментального кода. А значит, нужен жёсткий сброс (hard reset).

Да, мы же хотели сбросить вообще всё!

Вообще-то, мы можем отменить все изменения в рабочем дереве прямо сейчас! Воспользуйся командой, которую мы изучали чуть раньше (подсказка: это git restore). Если не помнишь, как она работает, загляни в .

Задача
Пройдено

Отмени изменения в рабочем дереве.

Отлично! На самом деле, жёсткий сброс можно было сделать одной командой, добавив флаг --hard к git reset. Запуск git reset --hard не раз выручал меня в прошлом.

Давай проверим статус репозитория.

Запустить в терминале:
git status
Задача
Пройдено

Проверь статус репозитория.

Правки в hello.html пропали. Но файл experiment.html всё ещё на месте! Почему так?

Давай разбираться...

Так как файл неотслеживаемый, Git о нём ничего не знает. Такой файл не входит в репозиторий, поэтому команда сброса на него никак не влияет. Чтобы полностью избавиться от файла, его нужно просто удалить с помощью команды

.

Запустить в терминале:
rm experiment.html
Задача
Пройдено

Удали файл experiment.html.

Давай проверим статус репозитория.

Запустить в терминале:
git status
Задача
Пройдено

Проверь статус репозитория.

Супер! Наша ветка вернулась в то состояние, в котором мы её создавали.

Задача
Пройдено

Прежде чем идти дальше, переключись на ветку main.

Если хочется сохранить изменения из отброшенных коммитов, используй git reset --soft вместо обычного git reset. Это сместит указатель ветки, но оставит все правки из отменённых коммитов в области подготовки.

А если нужно стереть любые следы отброшенных коммитов, выполняй git reset --hard. Это переместит указатель ветки и уничтожит все изменения как в рабочем дереве, так и в области подготовки. Использовать с осторожностью!

С командой git reset нужна осторожность, особенно с флагом --hard, так как она может навсегда удалить изменения. Всегда проверяй, к тому ли коммиту ты откатываешься. Если незакоммиченные правки ещё могут пригодиться, перед сбросом спрячь их через git stash.

Команда git reset чем-то похожа на git restore, по крайней мере, по названию. Обе можно использовать для отмены изменений в рабочем дереве. Однако git restore новее и делает меньше вещей: она умеет только восстанавливать файлы в рабочем дереве, но не двигает указатель ветки. Собственно, ради этого её и придумали: чтобы отдельно сдвигать указатель ветки и отдельно восстанавливать файлы. При использовании git restore сложнее случайно что-то сломать, так как команда более предсказуемая и менее разрушительная, чем git reset.

Конечно, тем, у кого уже есть привычка к старому доброму git reset, может потребоваться время, чтобы переучиться. Но если ты только начинаешь изучать Git, лучше сразу понять разницу и стараться использовать git restore, когда это уместно.

Next step
Хочешь попробовать Сюжетный режим?

Пройди курс так, как задумано: порционное обучение, чёткий порядок и постепенное открытие статей в Gitопедии. В любой момент можно продолжить работу с настоящим Git прямо в VS Code, Cursor, Antigravity или Windsurf.

Сюжетный режим
БЕСПЛАТНО
(требуется войти в аккаунт)