Как я могу отменить git reset --hard HEAD ~ 1?

Можно ли отменить изменения, вызванные следующей командой? Если так, то как?

git reset --hard HEAD~1
вопрос задан 7.08.2008
Paul Wicks
23843 репутация

13 ответов


  • 0 рейтинг

    Ответ скрыт в подробном ответе выше, вы можете просто сделать:

    $> git reset --hard HEAD@{1}
    

    (См. Вывод git reflog show )

    ответ дан markmc, с репутацией 2176, 26.02.2011
  • 0 рейтинг

    Прежде чем ответить, давайте добавим некоторый фон, объяснив, что это за HEAD.

    First of all what is HEAD?

    HEAD - это просто ссылка на текущий коммит (последний) в текущей ветке.
    Может быть только один HEAD в любой момент времени. (исключая git worktree)

    Содержимое HEAD хранится внутри .git/HEAD и содержит 40 байтов SHA-1 текущего коммита.


    detached HEAD

    Если вы не используете последний коммит - это означает, что HEAD указывает на предыдущий коммит в истории, он называется detached HEAD .

    enter image description here

    В командной строке это будет выглядеть так - SHA-1 вместо имени ветви, так как HEAD не указывает на верхушку текущей ветви

    enter image description here


    Несколько вариантов восстановления после отсоединенной головки:


    git checkout

    git checkout 
    git checkout -b  
    git checkout HEAD~X // x is the number of commits t go back
    

    Это извлечет новую ветку, указывающую на желаемый коммит.
    Эта команда вернется к данному коммиту.
    На этом этапе вы можете создать ветку и начать работать с этого момента.

    # Checkout a given commit. 
    # Doing so will result in a `detached HEAD` which mean that the `HEAD`
    # is not pointing to the latest so you will need to checkout branch
    # in order to be able to update the code.
    git checkout 
    
    # create a new branch forked to the given commit
    git checkout -b 
    

    git reflog

    Вы также всегда можете использовать reflog.
    git reflog будет отображать любые изменения, которые обновили HEAD, и проверка желаемой записи reflog вернет HEAD к этой фиксации.

    Каждый раз, когда ГЛАВА изменяется, будет новая запись в reflog

    git reflog
    git checkout HEAD@{...}
    

    Это вернет вас к желаемой фиксации

    enter image description here


    git reset HEAD --hard

    «Переместите» свою голову назад к желаемому коммиту.

    # This will destroy any local modifications.
    # Don't do it if you have uncommitted work you want to keep.
    git reset --hard 0d1d7fc32
    
    # Alternatively, if there's work to keep:
    git stash
    git reset --hard 0d1d7fc32
    git stash pop
    # This saves the modifications, then reapplies that patch after resetting.
    # You could get merge conflicts, if you've modified things which were
    # changed since the commit you reset to.
    
    • Примечание: ( С Git 2. 7 )
      Вы также можете использовать git rebase --no-autostash.


    git revert

    "Отменить" указанный диапазон фиксации или фиксации.
    Команда сброса «отменит» любые изменения, сделанные в данном коммите.
    Новый коммит с патчем отмены будет зафиксирован, в то время как оригинальный коммит также останется в истории.

    # add new commit with the undo of the original one.
    # the  can be any commit(s) or commit range
    git revert 
    

    Эта схема иллюстрирует, какая команда что делает.
    Как вы можете видеть там reset && checkout изменить HEAD.

    enter image description here

    ответ дан CodeWizard, с репутацией 46220, 21.04.2018
  • 0 рейтинг

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

    Когда вы делаете «git add» или перемещаете что-либо из верхнего левого угла в нижний левый в git gui, содержимое файла сохраняется в большом двоичном объекте, и содержимое файла можно восстановить из этого большого двоичного объекта.

    Таким образом, можно восстановить файл, даже если он не был зафиксирован, но его необходимо добавить.

    git init  
    echo hello >> test.txt  
    git add test.txt  
    

    Теперь BLOB-объект создан, но на него ссылается индекс, поэтому он не будет указан с помощью git fsck, пока мы не сбросим его. Итак, мы сбрасываем. , ,

    git reset --hard  
    git fsck  
    

    вы получите болтающийся шарик ce013625030ba8dba906f756967f9e9ca394464a

    git show ce01362  
    

    вернет вам содержимое файла "привет"

    Чтобы найти несвязанные коммиты, я нашел подсказку, где это предлагается.

    gitk --all $(git log -g --pretty=format:%h)  
    

    У меня есть это как инструмент в git gui, и это очень удобно.

    ответ дан martin, с репутацией 231, 20.01.2014
  • 0 рейтинг

    Пэт Нотц прав. Вы можете вернуть коммит, если он был в течение нескольких дней. git собирает мусор только через месяц или около того, если только вы явно не скажете ему удалить более новые BLOB-объекты.

    $ git init
    Initialized empty Git repository in .git/
    
    $ echo "testing reset" > file1
    $ git add file1
    $ git commit -m 'added file1'
    Created initial commit 1a75c1d: added file1
     1 files changed, 1 insertions(+), 0 deletions(-)
     create mode 100644 file1
    
    $ echo "added new file" > file2
    $ git add file2
    $ git commit -m 'added file2'
    Created commit f6e5064: added file2
     1 files changed, 1 insertions(+), 0 deletions(-)
     create mode 100644 file2
    
    $ git reset --hard HEAD^
    HEAD is now at 1a75c1d... added file1
    
    $ cat file2
    cat: file2: No such file or directory
    
    $ git reflog
    1a75c1d... HEAD@{0}: reset --hard HEAD^: updating HEAD
    f6e5064... HEAD@{1}: commit: added file2
    
    $ git reset --hard f6e5064
    HEAD is now at f6e5064... added file2
    
    $ cat file2
    added new file
    

    Вы можете видеть в примере, что file2 был удален в результате аппаратного сброса, но был возвращен на место при сбросе через reflog.

    ответ дан Brian Riehman, с репутацией 16819, 22.08.2008
  • 0 рейтинг

    Если вы еще не собрали мусор в вашем хранилище (e. г. используя git repack -d или git gc, но обратите внимание, что сборка мусора также может происходить автоматически), тогда ваш коммит все еще там - он просто больше не доступен через HEAD.

    Вы можете попытаться найти свой коммит, просмотрев выходные данные git fsck --lost-found.

    В более новых версиях Git есть нечто, называемое «reflog», которое представляет собой журнал всех изменений, внесенных в ссылки (в отличие от изменений, которые вносятся в содержимое хранилища). Так, например, каждый раз, когда вы переключаете свою ГОЛОВКУ (т.е. е. каждый раз, когда вы делаете git checkout для переключения филиалов), который будет зарегистрирован. И, конечно же, ваш git reset также манипулировал HEAD, поэтому он также был зарегистрирован. Вы можете получить доступ к более старым состояниям ваших ссылок таким же образом, как вы можете получить доступ к более старым состояниям вашего хранилища, используя знак @ вместо ~, например, git reset HEAD@{1}.

    Мне потребовалось некоторое время, чтобы понять, в чем разница между HEAD @ {1} и HEAD ~ 1, поэтому здесь есть небольшое объяснение:

    git init
    git commit --allow-empty -mOne
    git commit --allow-empty -mTwo
    git checkout -b anotherbranch
    git commit --allow-empty -mThree
    git checkout master # This changes the HEAD, but not the repository contents
    git show HEAD~1 # => One
    git show HEAD@{1} # => Three
    git reflog
    

    Итак, HEAD~1 означает «перейти к коммиту до того коммита, на который в данный момент указывает HEAD», а HEAD@{1} означает «перейти к коммиту, на который указал HEAD, до того, как он указал на тот, на который в данный момент указывает».

    Это позволит вам легко найти потерянный коммит и восстановить его.

    ответ дан Jörg W Mittag, с репутацией 283376, 27.08.2008
  • 0 рейтинг

    В большинстве случаев да.

    В зависимости от состояния, в котором находился ваш репозиторий при запуске команды, эффекты git reset --hard могут варьироваться от тривиальных до отменных, в принципе невозможных.

    Ниже я перечислил ряд возможных сценариев и способы их устранения.

    Все мои изменения были зафиксированы, но коммиты исчезли!

    Эта ситуация обычно возникает, когда вы запускаете git reset с аргументом, как в git reset --hard HEAD~. Не волнуйтесь, это легко восстановить!

    Если вы только что запустили git reset и с тех пор больше ничего не делали, вы можете вернуться туда, где находились, с помощью одной строки:

    git reset --hard @{1}
    

    Это сбрасывает вашу текущую ветку в любое состояние, в котором она находилась до того, как в последний раз она была изменена (в вашем случае самой последней модификацией ветки будет полная перезагрузка, которую вы пытаетесь отменить).

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

    7c169bd master@{0}: reset: moving to HEAD~
    3ae5027 master@{1}: commit: Changed file2
    7c169bd master@{2}: commit: Some change
    5eb37ca master@{3}: commit (initial): Initial commit
    

    Найдите в этом списке операцию, которую вы хотите отменить. В приведенном выше примере это будет первая строка с надписью «сброс: переход к HEAD ~». Затем скопируйте представление коммита перед (ниже) этой операции. В нашем случае это будет master@{1} (или 3ae5027, они оба представляют одну и ту же фиксацию) и запустите git reset --hard , чтобы сбросить текущую ветвь обратно к этой фиксации.

    Я поставил свои изменения с git add, но никогда не фиксировал. Теперь мои изменения исчезли!

    Восстановить немного сложнее. У git есть копии , которые вы добавили, но поскольку эти копии никогда не были привязаны к какому-либо конкретному коммиту, вы не можете восстановить изменения сразу. Вместо этого вам нужно найти отдельные файлы в базе данных git и восстановить их вручную. Вы можете сделать это, используя git fsck .

    Подробнее об этом см. Undo git reset --hard с незафиксированными файлами в области подготовки .

    У меня были изменения в файлах в моем рабочем каталоге, которые я никогда не ставил с git add и никогда не фиксировал. Теперь мои изменения исчезли!

    Э-э-э Ненавижу тебе это говорить, но тебе, вероятно, не повезло. git не хранит изменения, которые вы не добавляете или не фиксируете, и в соответствии с документацией для git reset :

    - жесткий

    Сбрасывает индекс и рабочее дерево. Любые изменения в отслеживаемых файлах в рабочем дереве, начиная с , отменяются.

    Возможно, что может быть в состоянии восстановить ваши изменения с помощью какой-либо утилиты восстановления диска или профессиональной службы восстановления данных, но на данный момент это, вероятно, больше проблем, чем стоит.

    ответ дан Ajedi32, с репутацией 23951, 16.01.2015
  • 0 рейтинг

    Пример случая IRL:

    $ git fsck --lost-found

    Checking object directories: 100% (256/256), done.
    Checking objects: 100% (3/3), done.
    dangling blob 025cab9725ccc00fbd7202da543f556c146cb119
    dangling blob 84e9af799c2f5f08fb50874e5be7fb5cb7aa7c1b
    dangling blob 85f4d1a289e094012819d9732f017c7805ee85b4
    dangling blob 8f654d1cd425da7389d12c17dd2d88d318496d98
    dangling blob 9183b84bbd292dcc238ca546dab896e073432933
    dangling blob 1448ee51d0ea16f259371b32a557b60f908d15ee
    dangling blob 95372cef6148d980ab1d7539ee6fbb44f5e87e22
    dangling blob 9b3bf9fb1ee82c6d6d5ec9149e38fe53d4151fbd
    dangling blob 2b21002ca449a9e30dbb87e535fbd4e65bac18f7
    dangling blob 2fff2f8e4ea6408ac84a8560477aa00583002e66
    dangling blob 333e76340b59a944456b4befd0e007c2e23ab37b
    dangling blob b87163c8def315d40721e592f15c2192a33816bb
    dangling blob c22aafb90358f6bf22577d1ae077ad89d9eea0a7
    dangling blob c6ef78dd64c886e9c9895e2fc4556e69e4fbb133
    dangling blob 4a71f9ff8262701171d42559a283c751fea6a201
    dangling blob 6b762d368f44ddd441e5b8eae6a7b611335b49a2
    dangling blob 724d23914b48443b19eada79c3eb1813c3c67fed
    dangling blob 749ffc9a412e7584245af5106e78167b9480a27b
    dangling commit f6ce1a403399772d4146d306d5763f3f5715cb5a    <- it's this one
    

    $ git show f6ce1a403399772d4146d306d5763f3f5715cb5a

    commit f6ce1a403399772d4146d306d5763f3f5715cb5a
    Author: Stian Gudmundsen Høiland 
    Date:   Wed Aug 15 08:41:30 2012 +0200
    
        *MY COMMIT MESSAGE IS DISPLAYED HERE*
    
    diff --git a/Some.file b/Some.file
    new file mode 100644
    index 0000000..15baeba
    --- /dev/null
    +++ b/Some.file
    *THE WHOLE COMMIT IS DISPLAYED HERE*
    

    $ git rebase f6ce1a403399772d4146d306d5763f3f5715cb5a

    First, rewinding head to replay your work on top of it...
    Fast-forwarded master to f6ce1a403399772d4146d306d5763f3f5715cb5a.
    
    ответ дан Stian Høiland, с репутацией 2885, 15.08.2012
  • 0 рейтинг

    Возможно восстановить его, если Git еще не собирал мусор.

    Получите обзор оборванных коммитов с fsck:

    $ git fsck --lost-found
    dangling commit b72e67a9bb3f1fc1b64528bcce031af4f0d6fcbf
    

    Восстановить оборванный коммит с rebase:

    $ git rebase b72e67a9bb3f1fc1b64528bcce031af4f0d6fcbf
    
    ответ дан sverrejoh, с репутацией 7725, 22.08.2008
  • 0 рейтинг

    , насколько я знаю, --hard будет отклонять незафиксированные изменения. Так как они не отслеживаются Git. но вы можете отменить discarded commit.

    $ git reflog
    

    будет списки:

    b0d059c HEAD@{0}: reset: moving to HEAD~1
    4bac331 HEAD@{1}: commit: added level introduction....
    ....
    

    , где 4bac331 - discarded commit.

    Теперь просто переместите голову в этот коммит ::

    $ git reset --hard 4bac331
    
    ответ дан simple_human, с репутацией 8496, 2.04.2015
  • 0 рейтинг

    Сделал крошечный скрипт, чтобы немного легче было найти коммит, который искали:

    git fsck --lost-found | grep commit | cut -d ' ' -f 3 | xargs -i git show \{\} | egrep '^commit |Date:'

    Да, его можно сделать намного красивее с помощью awk или чего-то в этом роде, но это просто, и я просто нуждался в этом. Может спасти кого-то еще 30 секунд.

    ответ дан neuron, с репутацией 933, 11.03.2014
  • 0 рейтинг

    Я только что сделал полный сброс на неправильный проект. То, что спасло мою жизнь, было местной историей Затмения. Говорят, что у IntelliJ Idea тоже есть такой же, как и у вашего редактора, стоит проверить:

    1. Раздел справки Eclipse по локальной истории
    2. http: // wiki. затмение. org / FAQ_Where_is_the_workspace_local_history_stored% 3F
    ответ дан Maciek Łoziński, с репутацией 381, 7.04.2017
  • 0 рейтинг

    Если вам действительно повезло, как и мне, вы можете вернуться в свой текстовый редактор и нажать «Отменить».

    Я знаю, что это не совсем правильный ответ, но это сэкономило мне половину рабочего дня, так что, надеюсь, он будет делать то же самое для кого-то другого!

    ответ дан Chris, с репутацией 25772, 13.01.2012
  • 0 рейтинг

    То, что вы хотите сделать, это указать sha1 коммита, в который вы хотите восстановить. Вы можете получить sha1, изучив reflog (git reflog), а затем выполнив

    .

    git reset --hard

    Но не ждите слишком долго. , , через несколько недель git увидит этот коммит как не имеющий ссылки и удалит все BLOB-объекты.

    ответ дан Pat Notz, с репутацией 124449, 9.08.2008