В мире Git традиционно сложилась странная ситуация, когда документация на важные команды не полностью объясняет что происходит в репозитарии, и вокруг таких команд появляется много мифов. Это отражается и в сторонних статьях, посвященных таким командам, что только добавляет путанницы.
Одна из таких команд - это команда git reset, а особенно её опция --hard, которой пугают новых пользователей Git. Дескать, она полностью обнуляет историю откаченных коммитов, и вернуть их невозможно. Пользуйтесь ей с осторожностью!
На самом деле, вот что нужно знать об этой команде:
- Есть несколько простых ситуаций, в которые может попасть пользователь-новичек, и из которых естественным образом можно выйти с помощью git reset --hard.
- Жесткий сброс не удаляет коммиты, и их можно свободно поместить в дополнительную ветку.
Вот типичная ситуация, в которой может оказаться программист:
Программист на протяжении нескольких коммитов писал неудачный код в ветке dev. Ему нужно откатиться до некоего предыдущего коммита a1b2c3, сделать развилку так, чтобы новый код продолжил добавляться в ветку dev, а все откаченные изменения оказались бы в ветке badExperiment для истории. Воркфлоу в конторе предполагает, что другие программисты сидят в других ветках, и наш программист полностью владеет веткой dev (это важно).
Как проще всего поступить в такой ситуации программисту? Надо дать следующие команды:
Находясь на конце ветки dev, нужно создать ветку badExperiment:
git checkout dev - переход на конец ветки dev
git branch badExperiment - создание ветки badExperiment
Здесь надо обратить внимание, что команда git branch вызвана без опции -b, то есть ветка создается, но на нее переключения не происходит. Тут нужно напомнить, что имена веток - это просто указатели на коммиты. И после таких команд указатель dev и указатель badExperiment будут указывать на один и тот же последний коммит.
Далее, находясь в ветке dev, нужно сделать хардресет до нужного коммита:
git reset --hard a1b2c3
Указатель dev переместится на этот коммит. А благодаря тому, что была сделана ветка badExperiment, все коммиты, сделанные после a1b2c3 останутся в репозитарии, и их всегда можно будет посмотреть, переключившись на ветку badExperiment.
В общем, после этой команды репозитарий считает, что ветка dev заканчивается на коммите a1b2c3. Об этом изменении надо оповестить удаленный репозитарий. Делается это командой:
git push --force
Опция --force обязательна, так как по сути, происходит откат назад по истории коммитов.
Кроме того, на удаленный репозитарий нужно залить ветку badExperiment чтобы руководитель проекта видел, что программист не балду пинал, а неистово работал, хоть и не плодотворно. Залитие ветки badExperiment в удаленный репозитарий прозводится командами:
# переключение на ветку badExperiment
git checkout badExperiment
# Заливка текущей ветки на удаленный репозитарий origin как badExperiment
git push --set-upstream origin badExperiment
После этих команд можно переключиться на ветку dev и продолжить программировать. Все новые коммиты будут продолжать укладываться в ветку dev.