Skip to content

Instantly share code, notes, and snippets.

@solilin
Created November 10, 2016 13:21
Show Gist options
  • Save solilin/364c8268619c97588e0b0b43706a1c9b to your computer and use it in GitHub Desktop.
Save solilin/364c8268619c97588e0b0b43706a1c9b to your computer and use it in GitHub Desktop.
Самые страшные команды в гите: git reset --hard и git push --force.
Команда на все случаи, когда нужно что-то отменить:
$ git reset --hard <commit>
<commit> в данном случае — та точка, к которой нужно откатиться.
Гит — лапочка и записывает абсолютно всё, что делает: новые коммиты, переключения между ветками, переписывание истории.
Всё, что вам нужно — научиться читать логи.
Отменить git push --force
Если вы сделали форс-пуш и быстро поняли, что сделали его не туда, ситуацию легко поправить.
Главное — не паниковать.
$ git push --force origin master
Counting objects: 3, done.
...
a1a1a1..b2b2b2 master -> master
Последняя строка говорит, что до пуша последний коммит в удалённом мастере был a1a1a1, а после пуша последним коммитом стал b2b2b2.
Вооружённые этим знанием, делаем reset и ещё один форс-пуш, на этот раз возвращая предыдущее состояние ветки:
$ git reset --hard a1a1a1
$ git push origin +master
git push -f origin master и git push origin +master — одно и то же.
Если провернуть всё быстро, никто ничего не заметит.
Отменить git reset --hard
Этот трюк сработает только для закоммиченных изменений.
Бывает, что пара последних коммитов в ветке — лишние.
Вы делаете git reset --hard HEAD~3, но случайно удаляете 1 лишний коммит.
На сервер ещё ничего не запушено, сделать git pull неоткуда.
Что делать?
Открываем reflog:
$ git reflog
c3c3c3 HEAD@{0} reset: moving to HEAD~3
b2b2b2 HEAD@{1} commit: Clean up
a1a1a1 HEAD@{2} commit (amend): Fix #42
...
Ваша задача — найти в этом логе тот пункт, к которому вы хотите вернуться.
В нашем случае мы хотим отменить последнее действие, то есть вернуться ко второй строке.
Делаем хитрый reset:
$ git reset --hard HEAD@{1}
HEAD is now at b2b2b2 Clean up
Вуаля, неудачного reset --hard как не бывало.
Что же мы сделали?
git reset --hard HEAD@{1} буквально значит: «Хэй, гит, покажи мне файлы в том виде, в каком они были 1 действие назад».
Обратите внимание, что под действием имеется в виду запись в рефлоге. Например, если вы сделаете git reset -i HEAD~6, в зависимости от того, что вы натворите во время рибейза, в логе может появиться хоть 20 новых записей.
И каждую из них можно использовать для reset.
Вместо HEAD@{1} можно использовать более замысловатые указания, например:
$ git reset --hard master@{one.week.ago}
Этой командой мы просим показать мастер недельной давности.
О том, как ещё можно указать нужный коммит, читайте в документации.
Отменить git rebase -i
По тому же принципу можно отменить и недавний rebase:
$ git reflog
c3c3c3 HEAD@{1}: rebase -i (finish): returning to refs/heads/branch
b2b2b2 HEAD@{2}: rebase -i (pick): Add cool method
a1a1a1 HEAD@{3}: checkout: moving from branch to a1a1a1
a1a1a1 HEAD@{4}: commit (amend): Add cool method
...
Ищем коммит перед чекаутом и откатываемся:
$ git reset --hard HEAD@{4}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment