Как отменить 'git reset'?


1314

Какой самый простой способ отменить

git reset HEAD~

команда? В настоящее время я могу думать только о том, чтобы сделать «git clone http: // ...» из удаленного репозитория.


2
Если кто-то ищет, как отменить жесткий сброс, отметьте в разделе Отмена сброса git --hard HEAD ~ 1 . Решения очень похожи.


2
Это не дубликат вопросов, связанных с --hard! Риск случайного запуска этой команды намного выше. Например, вы хотите удалить один файл с помощью git reset foo-file. Вы пишете только первую часть имени файла, нажимаете вкладку для автозаполнения, оно фактически завершается именем ветки, вы этого не замечаете и git reset foo-branchвместо этого запускаете команду . Вуаля
Юшин

Ответы:


2391

Короткий ответ:

git reset 'HEAD@{1}'

Длинный ответ:

Git ведет журнал всех обновлений ссылок (например, извлечение, сброс, фиксация, слияние). Вы можете просмотреть его, набрав:

git reflog

Где-то в этом списке находится коммит, который вы потеряли. Допустим, вы только что набрали git reset HEAD~и хотите отменить это. Мой рефлог выглядит так:

$ git reflog
3f6db14 HEAD@{0}: HEAD~: updating HEAD
d27924e HEAD@{1}: checkout: moving from d27924e0fe16776f0d0f1ee2933a0334a4787b4c
[...]

Первая строка говорит, что HEAD0 позиций назад (другими словами, текущая позиция) составляет 3f6db14; он был получен путем сброса на HEAD~. Во второй строке указано, что HEAD1 позиция назад (другими словами, состояние до сброса) - d27924e. Он был получен путем проверки конкретного коммита (хотя сейчас это не важно). Итак, чтобы отменить сброс, запустите git reset HEAD@{1}(или git reset d27924e).

Если, с другой стороны, с тех пор вы обновили HEAD, вы выполнили какие-то другие команды, то требуемый коммит не будет в верхней части списка, и вам нужно будет выполнить поиск по reflog.

Последнее замечание: может быть проще взглянуть на reflogконкретную ветвь, которую вы хотите отменить, скажем master, а не HEAD:

$ git reflog show master
c24138b master@{0}: merge origin/master: Fast-forward
90a2bf9 master@{1}: merge origin/master: Fast-forward
[...]

Это должно иметь меньше шума, чем в целом HEAD reflog.


25
В качестве более наглядной и приятной альтернативы reflogдля этой цели я бы хотел использовать git log --graph --decorate --oneline $(git rev-list -g --all). Он показывает дерево всех коммитов, включая висячие неназванные ветви
texasflood

1
Допустим, у меня есть каталог с существующими файлами в нем. В этом каталоге я бегу git init, а потом сразу после этого git reset --hard. Там нет reflog или даже каких-либо журналов для начала. Эти файлы сейчас довольно просты?
AlanSE

@AlanSE, к сожалению, насколько я знаю, эти файлы - тосты. Если вы никогда этого не делали git add(то есть никогда не ставили эту версию файла), то git checkoutили git reset --hardсдуте единственную копию (рабочий каталог) без резервной копии. Я бы этого не хотел.
Марк Лодато

2
git reset HEAD~12Ой ... git reset HEAD@{12}Нееет .. "Git Reflog" на помощь! о, это простоgit reset HEAD@{1}
Деннис

После прочтения отличной git-scm.com/blog/2011/07/11/reset.html статьи о git-reset я немного менее озадачен.
Андрей Дроздюк

192

Старый вопрос, и опубликованные ответы прекрасно работают. Я включу другой вариант, хотя.

git reset ORIG_HEAD

ORIG_HEADссылается на коммит, на который HEADранее ссылались.


1
Это кажется великолепным - вы могли бы уточнить? «ORIG» здесь означает «оригинал» или «происхождение»? … То есть, он сбрасывается туда, где находился HEAD, прежде чем начать с ним работать? Или где HEAD находится на происхождении? Что произойдет, если вы переместили ГОЛОВУ несколько раз до git reset ORIG_HEAD? Спасибо.
Бенджон

ORIG означает оригинал, ORIG_HEAD означает оригинал HEAD, до сброса
Сэм Галлахер

«Некоторые операции, такие как объединение и сброс, записывают предыдущую версию HEAD в ORIG_HEAD непосредственно перед настройкой ее на новое значение. Вы можете использовать ORIG_HEAD для восстановления или возврата к предыдущему состоянию или для сравнения». Отрывок из книги: «Контроль версий с помощью Git»
Амирреза,

56

Моя ситуация была немного другой, я сделал git reset HEAD~три раза.

Чтобы отменить это я должен был сделать

git reset HEAD@{3}

так что вы должны быть в состоянии сделать

git reset HEAD@{N}

Но если вы сделали git reset используя

git reset HEAD~3

вам нужно будет сделать

git reset HEAD@{1}

Поскольку {N} представляет количество операций в Reflog. Как отметил Марк в комментариях.


2
В принятой опции не приводится пример продвижения вперед. Я был в ситуации, которая была час назад, когда я хотел переслать больше 1. Попытался с несколькими, и это сработало. Хотел добавить это сюда. Будет полезно для людей, которые ищут отмены сброса с помощью git reset HEAD ~ 3
zainengineer

3
но если кто-то выполнил git reset HEAD ~ 3, он может быстро увидеть, как отменить его, требуется git reset HEAD @ {3}, не заходя в reflog, git reset HEAD ~ 3 и т. д. - обычная ситуация
zainengineer

1
Я думаю, что любой, кто увидит {1} / {2}, поймет, что это может быть любой номер ревизии, который reflogвам предоставляет команда. Согласились, что ваша точка зрения о том, что числа одинаковы для обоих направлений ~ 3 / @ {3}, но на самом деле не нужно было нового ответа.
Клинт

30

1. Используйте git reflogдля обновления всех ссылок.

2.git reset <id_of_commit_to_which_you_want_restore>

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.