Небольшая статья, посвященная вопросу отката коммитов в GitHub.
В чем заключается вопрос, собственно? В том, что имеется определенный репозиторий, размещенный на сервере GitHub. У этого удаленного репозитория есть локальная синхронизированная версия на рабочей машине автора. Этот репозиторий изменяется с большей или меньшей периодичностью; все изменения фиксируются соответствующими коммитами.
И вот в один прекрасный момент в репозиторий было внесено изменение, которое затем было закоммичено и отправлено на GitHub. Однако, от этого изменения нужно избавиться - оно ошибочное.
Но как это сделать, если коммит уже находится на GitHub? В интерфейсе сервиса GitHub я не нашел нужной кнопки, чтобы удалять конкретный коммит и тем самым возвращать репозиторий до нужного состояния.
Это потому, что управление коммитами на GitHub производится через локальный репозиторий. Ниже приведу три несложных шага для того, чтобы показать, каким образом это выполняется.
Шаг первый
Первое - необходимо получить список hash-сумм последних коммитов репозитория. Это и понятно - нужно иметь перед собой дерево коммитов, чтобы видеть - куда двигаться. В дереве коммитов hash-суммы являются опорными точками, идентификационными номерами каждого из коммитов:
$ git log
Ниже показан краткий вывод команды
- четыре самых поздних коммита репозитория:1
git log
commit ee3a2ae6888fb87d5013786f6cf3b18da63f7bbb
Author: gearmobile <gearmobile@gmail.com>
Date: Mon Apr 6 17:48:08 2015 +0300
End
commit 6d92268e42eace0c78a5150144645333b769623d
Author: gearmobile <gearmobile@gmail.com>
Date: Mon Apr 6 17:06:35 2015 +0400
Close to end
commit 855404bf39b5fabd45ba0c6f5702e7a28949a02e
Author: gearmobile <gearmobile@gmail.com>
Date: Mon Apr 6 15:24:04 2015 +0400
End 2014-07-16
commit 3eb55145a79f9f8f732338a0e80bd71b2325b6da
Author: gearmobile <gearmobile@gmail.com>
Date: Mon Apr 6 12:48:17 2015 +0400
End
Мне нужно вернуть репозиторий из состояния, описанного в коммите
, в состояние, зафиксированное в коммите 1
ee3a2ae6888fb87d
.1
6d92268e42eace0c
Шаг второй
Для этого я воспользуюсь командой
, с ключом 1
reset
. Эта команда мне подходит потому, что я не собираюсь сохранять изменения, зафиксированные в коммите 1
--hard
, так как они полностью ошибочны.1
ee3a2ae6888fb87d
Как подробно описывается в статье Отмена изменений в Git, такую задачу можно выполнить командой:
$ git reset --hard 6d92268e42eace0c
где
- начальные 16 символов hash-суммы коммита, на который я хочу “перепрыгнуть”. Полный вид hash-суммы в 40 символов можно не использовать - достаточно 16 символов для надежной идентификации конкретного коммита.1
6d92268e42eace0c
После выполнения этой команды локальный репозиторий будет сброшен к состоянию, зафиксированному в коммите
. Другими словами, я избавился от последних ошибочных изменений и вернул репозиторий в предыдущее его состояние.1
6d92268e42eace0c
Однако, это всего лишь половина дела, так как откат коснулся только локального репозитория. В этой статье речь идет прежде всего об удаленном репозитории, размещенном на GitHub. Как добиться внесения аналогичных изменений на GitHub?
Казалось бы - просто! Достаточно выполнить команду:
$ git push
Но, на самом деле это не получится сделать - Git не позволит это выполнить. По той причине, что на данный момент состояние локального репозитория имеет более раннюю версию, нежели состояние удаленного репозитория.
Вместо этого Git предложит выполнить комнаду
, чтобы привести локальный репозиторий к удаленному.1
git pull
Шаг третий
Чтобы заставить Git выполнить обратную задачу - привести удаленный репозиторий к локальному, необходимо использовать ключ
.1
-f
То есть, форсировать внесение изменений и тем самым “сказать” Git - синхронизировать удаленный репозиторий с локальным репозиторием несмотря на то, что последний имеет более ранюю версию:
$ git push -f
Заключение
Теперь, если проверить состояние удаленного репозитория на сервере GitHub, то увидим, что оно идентично состоянию локального репозитория. Но самое главное - удален последний ошибочный коммит, чего я и добивался.
На этом все,