Как отменить reset hard
Перейти к содержимому

Как отменить reset hard

  • автор:

Как я могу отменить git reset —hard HEAD

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

12 ответов

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

В примере показано, что файл2 был удален из жесткого reset, но был вставлен на место, когда я reset через reflog.

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

git reset —hard <sha1 of desired commit>

Но не ждите слишком долго. через несколько недель git в конечном итоге увидит, что commit как unreferenced и удаляет все капли.

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

(Смотрите вывод git reflog show)

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

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

Восстановите оборванную фиксацию с помощью rebase:

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

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

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

$ git fsck —lost-found

$ git show f6ce1a403399772d4146d306d5763f3f5715cb5a

$ git rebase f6ce1a403399772d4146d306d5763f3f5715cb5a

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

где 4bac331 — discarded commit .

Теперь просто переместите голову в команду commit:

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

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

В более новых версиях Git есть что-то, называемое «reflog», которое является журналом всех изменений, внесенных в ref (в отличие от изменений, внесенных в содержимое репозитория). Так, например, каждый раз, когда вы переключаете HEAD (т.е. Каждый раз, когда вы делаете git checkout для переключения ветвей), которые будут регистрироваться. И, конечно же, ваш git reset также управлял HEAD, поэтому он также записывался в журнал. Вы можете получить доступ к старым состояниям ваших ссылок таким же образом, что вы можете получить доступ к более старым состояниям вашего репозитория, используя знак @ вместо

Мне потребовалось некоторое время, чтобы понять, какая разница между HEAD @ <1>и HEAD

1, так что вот небольшое объяснение:

1 означает «перейти к фиксации до фиксации, которую HEAD в настоящее время указывает на», а [email protected] <1>означает «перейти к фиксации, на которую указал HEAD, прежде чем он указал на то, где он сейчас указывает на».

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

1 означает перейти к «родителю HEAD», а HEAD @ <1>— «вернуться на один шаг назад в истории HEAD».

идет назад в истории коммитов , тогда как @ идет назад в хронологической или временной истории . Но ни одна из трех версий не особенно хороша.

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

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

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

Все мои изменения были совершены, но теперь коммиты исчезли!

Эта ситуация обычно возникает, когда вы запускаете git reset с аргументом, как в git reset —hard HEAD

. Не беспокойтесь, это легко восстановить!

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

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

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

Найдите операцию в этом списке, которую вы хотите «отменить». В приведенном выше примере это будет первая строка, в которой говорится «reset: переход к HEAD

«. Затем скопируйте представление фиксации до (ниже) этой операции. В нашем случае это будет [email protected] <1>(или 3ae5027 , они оба представляют одно и то же commit), и запустите git reset —hard <commit> в reset вашу текущую ветку обратно на эту фиксацию.

Я выполнил свои изменения с помощью git add , но никогда не совершал. Теперь мои изменения ушли!

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

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

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

— жесткий

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

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

How can I undo git reset —hard HEAD

Is it possible to undo the changes caused by the following command? If so, how?

jub0bs's user avatar

20 Answers 20

Pat Notz is correct. You can get the commit back so long as it’s been within a few days. git only garbage collects after about a month or so unless you explicitly tell it to remove newer blobs.

You can see in the example that the file2 was removed as a result of the hard reset, but was put back in place when I reset via the reflog.

What you want to do is to specify the sha1 of the commit you want to restore to. You can get the sha1 by examining the reflog ( git reflog ) and then doing

But don’t wait too long. after a few weeks git will eventually see that commit as unreferenced and delete all the blobs.

The answer is hidden in the detailed response above, you can simply do:

(See the output of git reflog show)

It is possible to recover it if Git hasn’t garbage collected yet.

Get an overview of dangling commits with fsck :

Recover the dangling commit with rebase:

As far as I know, —hard will discard uncommitted changes. Since these aren’t tracked by git. But you can undo the discarded commit .

where 4bac331 is the discarded commit .

Now just move the head to that commit:

Amir Shabani's user avatar

suhailvs's user avatar

If you’re really lucky, like I was, you can go back into your text editor and hit ‘undo’.

I know that’s not really a proper answer, but it saved me half a day’s work so hopefully it’ll do the same for someone else!

In most cases, yes.

Depending on the state your repository was in when you ran the command, the effects of git reset —hard can range from trivial to undo, to basically impossible.

Below I have listed a range of different possible scenarios, and how you might recover from them.

All my changes were committed, but now the commits are gone!

This situation usually occurs when you run git reset with an argument, as in git reset —hard HEAD

. Don’t worry, this is easy to recover from!

If you just ran git reset and haven’t done anything else since, you can get back to where you were with this one-liner:

This resets your current branch whatever state it was in before the last time it was modified (in your case, the most recent modification to the branch would be the hard reset you are trying to undo).

If, however, you have made other modifications to your branch since the reset, the one-liner above won’t work. Instead, you should run git reflog <branchname> to see a list of all recent changes made to your branch (including resets). That list will look something like this:

Find the operation in this list that you want to «undo». In the example above, it would be the first line, the one that says «reset: moving to HEAD

«. Then copy the representation of the commit before (below) that operation. In our case, that would be master@ <1>(or 3ae5027 , they both represent the same commit), and run git reset —hard <commit> to reset your current branch back to that commit.

I staged my changes with git add , but never committed. Now my changes are gone!

This is a bit trickier to recover from. git does have copies of the files you added, but since these copies were never tied to any particular commit you can’t restore the changes all at once. Instead, you have to locate the individual files in git’s database and restore them manually. You can do this using git fsck .

I had changes to files in my working directory that I never staged with git add , and never committed. Now my changes are gone!

Uh oh. I hate to tell you this, but you’re probably out of luck. git doesn’t store changes that you don’t add or commit to it, and according to the documentation for git reset :

—hard

Resets the index and working tree. Any changes to tracked files in the working tree since <commit> are discarded.

It’s possible that you might be able to recover your changes with some sort of disk recovery utility or a professional data recovery service, but at this point that’s probably more trouble than it’s worth.

Отмена действий в Git

Git

Мы всегда готовы подчеркивать бесчисленные возможности, которые предлагает Git, и эта статья не станет исключением. Git известен своей потрясающей способностью отменять практически любые действия! Наверняка на память вам уже приходят тысячи печальных случаев, когда вы делали объединение, а потом понимали, что в ваши планы оно не входило. Даже если вам кажется, что ошибочное объединение— это величайшая неудача всей вашей жизни, сделайте глубокий вдох и дочитайте статью до конца.

Не существует какого-то одного традиционного способа отмены действий в Git. Отмена производится с помощью некоторых других команд. Мы рассмотрим “первую пятерку” сценариев, которые помогут вам исправить ошибку и двинуться дальше.

Отмена Git Add

Один из самых распространенных вопросов в сообществе Git звучит так: “Как откатить git add перед коммитом?” Вы можете отменить действия над конкретным файлом или все внесенные изменения.

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

Для отмены всех изменений запустите следующее:

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

Как откатить Git Merge

Объединение может привести к нежелаемым результатам. Но, как уже было сказано, вы можете с легкостью исправить свою ошибку! Давайте представим сценарий, в котором вы уже отправили изменения и осознали, что вам нужно отменить сделанное объединение.

Здесь на помощь приходит еще одна команда класса “отмена”: git revert . Начнем с того, что переключимся на мастер-ветку, используя команду git checkout :

Следующий шаг — запустить команду git log , чтобы получить ID сделанного объединения:

Затем вернитесь к упомянутому коммиту, выполнив следующее:

Используя -m 1 , вы даете Git указание: вернуться к первому родительскому элементу мастер-ветки, куда был совершен коммит объединения. Например, использование -m 2 сказало бы Git вернуться к первому родительскому элементу ветки, откуда пришел запрос на объединение.

Git также предлагает возможность предварительного просмотра, если вы хотите увидеть, что произойдет при объединении веток.

Как откатить Git Reset

Предлагаем суперкороткий способ отменить команду git reset:

Следом можно запустить команду git reflog , чтобы просмотреть журнал всех обновлений (т.е. переключение веток, сброс, коммит, объединение).

Отмена последних коммитов в Git

Существует несколько методов для отмены git commit . Давайте рассмотрим их по очереди.

Команду git reset можно использовать для отмены внесенных изменений:

x введите число. Например, если вы укажете

4 , то команда повлияет на четвертый снизу коммит. Если вы не укажете никакое конкретно число, git reset — soft HEAD применится к последнему коммиту.

Когда вы используете команду git reset — soft HEAD , то просто отменяете последний коммит, при этом внесенные изменения останутся в вашем рабочем дереве и в вашем индексе. Поэтому git commit создаст в будущем коммит с теми же самыми изменениями, которые вы “обнулили” перед этим.

Другой метод — это команда git revert HEAD

x ( git reset — hard commit hash ), которая отменяет изменения, указанные последним коммитом в HEAD , и создает новый с возвращенными изменениями:

Этот метод лучше всего работает в случае с общими публичными репозиториями.

Отмена Git Rebase

Допустим, вы выполнили команду git rebase в локальной ветке git и отправили ее в удаленную ветку. Следом вы поняли, что это не отвечает вашим ожиданиям, и захотели отменить сделанное.

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

Следом необходимо установить туда текущую ветку, воспользовавшись git reset .

В данном случае старым коммитом был HEAD5 .

Заключение

Вот и все о том, как вы можете отменить наиболее часто используемые команды в Git. Хоть никакой традиционной команды отмены и нет, другие команды git могут помочь вам откатить то, что вы могли сделать по ошибке.

How To: Recover From a Git Hard Reset

(Or, This is Why We Probably Shouldn’t but Totally Can Have Nice Things)

Here is the logistical information about this post.

Target Audience: Github beginners working via command line who also have ADHD, insomnia, or a fever.

Question Addressed: I did a hard reset. I did a hard reset after adding files to be committed but BEFORE committing them. Git deleted all the files on my actual working directory. (Or, Git replaced all my new fancy clean files with old ugly bad files.) Can I recover from this?

Answers According to the Internet:

This is the first git command I’ve come across so far that’s irreversible… added a warning so others don’t get too trigger happy… — jmort253 Apr 1 at 21:41

Erm… no you cannot get the index back from before a reset —hard. You can only get back what has been commited/stashed — sehe Sep 10 ‘11 at 19:32

“This tells Git to replace the files in your working copy with the “HEAD” revision (which is the last committed version), discarding all local changes. Discarding uncommitted changes cannot be undone. This is because they have never been saved in your repository. Therefore, Git has no chance to restore this kind of changes.” — git-tower.com

Actual Answer:

YES, YOU CAN RECOVER FROM THIS. There’s no undo button, and it’s a tedious process, but you haven’t just irrevocably lost hours or days or weeks of work. There seem to be a few solutions that have worked for other people, which I’ll link to at the bottom of this post, but here I’ll lead you step-by-step through the one that worked for me.

One other relevant detail: Medium automatically displays two side-by-side hyphens as an em-dash. (One loooong hyphen.) I’ve tried to go through and reformat all of these, but in case I’ve missed a couple, if you see what looks like an em-dash in any of the Git commands, translate that in your brain eyeball to two hyphens. (This: “—” should be this: “—").

Off we go! First, some background:

Basically it tells Git to replace the files in your working directory (AKA on your actual computer, not on Github) with the last version of the project you committed and pushed to Github. Evidently there are times when this is the #1 most useful option for people who know what they are doing. In the hands of a beginner, this command is basically just saying DELETE ALL THE THINGS, HIDE THEM WHERE THEY MAY NEVER AGAIN BE FOUND.

Why you may have found yourself in this situation (Or, how I ended up in this situation). This meanders. Feel free to skip ahead to the actual how-to:

I was working on redesigning and rebuilding my website. I was not committing early and often. Making this mistake is definitely a good way to learn why committing early and often is important. When I went to do my first commit, I already had pretty much a full working version of my site ready to go.

It was a new project, so there were many new files that I wanted to push. Instead of individually adding each file, I added all the files in my project folder (“git add .”)

I’d forgotten to create a .gitignore file (Google this if you don’t know what it is — super useful and easy to use) so this added everything everything, not just everything, and there were a lot of things that I did not want to commit. Most problematically, this added infinite “node_modules” folders and all the files within them because I’d been running Grunt and using fun extensions.

So I was like, OH NO, this is exactly what you are not supposed to do. This is why you do $ git status, and hand select the stuff you want to add, commit, and push. I do not want to commit all of these files that I have added to be committed.

There are many, many things, or at least two very easy things you can do at this point—the point at which you have added files to the staging area and want to unstage them. If you are at this point, and wondering what to do, just go ask the internet, and do ANYTHING, I repeat ANYTHING other than git reset —hard. (Unless you know how to use that properly and are just here reading this to laugh and laugh and laugh at the pain of other, lesser beings. In which case ugh go do whatever you want.) Some other form of git reset may be appropriate, just not $ git reset —hard. Read more about what git reset does, and how to use it properly, here.

The first thing I tried was “git rm —cached .” This tells git to unstage the changes without deleting them from the working directory. (The keyword here is “—cached”, as without it you’ll also be removing the files from your local working directory.) The “.” refers to all files. Since I’ve added like 700 of them to the staging area and unstaging each one individually would be a nightmare (although less of a nightmare than I ultimately created for myself), I use “.”

I then get the following message: “fatal: not removing ‘.’ recursively without –r”

Here’s what that means: I had added all of my files to the staging area, including files within folders. “Recursive” refers to files within folders (within files within folders etc.) Git adding “.” will automatically add all your files recursively to the staging area, but when you remove “.” you need to specify that you mean all recursive files or git won’t listen. You know, FOR SAFETY. Thanks for having our backs, Git.

In order to unstage all of these files, including the ones within folders, while leaving them intact in my working directory, I needed to say “git rm –r —cached .”

Unfortunately, I read “fatal: not removing ‘.’ recursively without –r” as “FATAL, HERE ARE SOME NONSENSE WORDS, BOOP BOOP BOOP. TRY TYPING SOME OTHER THINGS THAT YOU FIND ON THE INTERNET UNTIL YOU GET A MESSAGE THAT DOES NOT INCLUDE THE WORD FATAL.”

So I was like, I guess I broke Git, I just added literally hundreds of .js and .md and .json files that I definitely did not intend to add. Then when I tried to undo the add, I did something that was apparently “fatal.” I will go ask ibrokegit.com what to do.

Under “I broke git while trying to remove changes from staging,” it said:

An excellent suggestion that would not have screwed me over. To which my brain replied, “(files changed)”? I don’t know what that means! Do I actually type “(files changed)”? Do I do this with each individual file name? Do I [etc., etc., etc.]? NO TIME FOR FURTHER ANALYSIS! Moving on.

So I looked at the next option:

I should have recognized the giant Do Not Enter sign, but instead I was like oh, cool, I bet that means it will be like a big fancy undo button for the adds I just did since those are the “changes” I have made via command line. I will mindlessly type it in and press enter without actually processing what “Reset all changes and revert to the last commit” really means.

Trial and error is frequently a great way to learn when you are coding, but trial and error is NOT a good way to learn how to use command line.

So, Git did exactly what I asked it to do, and exactly what ibrokegit.com said it would do: It reset all changes I had made on my local directory and reverted to the last commit I had pushed to Github.

(I’m phrasing it this way to place emphasis on the relationship [and distinction] between the stuff on your hard drive and the stuff in your online repository. Pushing might be irrelevant in this situation. It’s possible if I had added and committed but not pushed I would have been OK. I haven’t looked into this.)

Regardless, I had never committed or pushed anything to this new Github repository. So “all changes” was the existence of every single file in my local project folder, and “last commit” was nothing. Entering “git reset —hard” turned my site into an empty folder. (With the exception of a few Grunt-related folders that Git left as empty shells inside my empty shell of a site folder.)

At that point, I realized a few things. I did not have my files backed up anywhere. Not on Dropbox, not on an external hard drive, and obviously not on Github. I had not made a copy of anything at any point while playing around, as I usually do, because thanks to everything I’d been learning and practicing, things had actually been working the way I wanted them to (hurray…) and I never needed to, for example, turn my index.html file into an indexperiment.html file or my stylesheet.css file into a stylecheat.css file (cute, ammiright?) to mess around. There was no such thing as a git/command line undo button, and because my files had been essentially written over, not deleted, it’s not like they were just hanging out in the trash folder.

It was one of those moments where the main thought you keep coming back to is ok, come on, I can just not have done that, right? Let’s just go back in time 30 seconds and I’ll not do that.

Since that’s not possible, here’s how to (mostly) fix it:

So. You’ve created new files. You’ve staged them. You haven’t committed them. For whatever reason, you’ve run “git reset —hard”.

It’s time to find your lost blobs.

Quick but important note moving forward: Within this post, any punctuation inside the quotation marks is punctuation you should actually type into command line. Any punctuation outside of the quotation marks is just punctuation I have to use so you know when I am ending my sentences. The quotation marks themselves I’m just using to distinguish the commands from the rest of the content. Unless otherwise instructed, don’t actually enter the quotation marks into your command line. And, to repeat what I mentioned above, if you see one very long dash in a Git command, type it as two short dashes.

To recover your files, you’re going to be using “git fsck”. This stands for File System Check. When you do a hard reset, all your stuff goes out and dangles nebulously in the git dataverse. It’s not gone yet, but it’s like if you threw your retainer in the garbage and now it’s in a dumpster out back. You’re going to have to wade through a lot of garbage to find the items you’re looking for, and when you do find them, they may not be totally recognizable, and they’ll need some serious cleaning up.

STEPS:

1. If you type “git fsck” and press enter, you’ll get a list of dangling blobs. There might be other things in there, like missing trees. It will look something like this:

Hidden in these dangling blobs are your html files, your CSS files, your Sass files, your images, everything. Every dangling blob is essentially a file without its corresponding name or extension.

2. Enter “git fsck —lost-found”. (That’s two dashes up front there in front of lost-found, if my edit didn’t work.) Running this saves the blobs to an invisible path: .git/lost-found/other

Your path may not be invisible. Mine was super invisible.

3. Now copy and paste the following and press enter. This will take all the blobs in your possibly invisible new path and save them as 100% visible .txt files in your project folder:

4. Your files are in there somewhere, but maybe you now have a list of 1517 .txt files and no way to figure out what you need and what you don’t. For example, somewhere in there, I don’t know why, will be this file. It belongs to Git:

5. Recover your HTML files by searching for key words within the content of the files. (On a Mac, open your finder window, go to File > Find, change the search to target only your project folder, and change the dropdown menu field from “Kind” to “Contents.” Now you’ll have a little search bar.) Maybe there’s a menu bar on every page that includes “bio” and “contact.” Maybe there’s a page about rocket fuel, and you can filter that list of 1517 .txt files for only the ones that contain the words “rocket fuel.” Or just search for “doctype.” For me, “doctype” narrowed the search for my HTML files from 1517 .txt files to just 23 .txt files.

6. Your .css, .scss, .js and other files can be found the same way. Use your imagination. (Or, use your newly recovered HTML files to find class and id tag names to search for.)

7. Images and PDFs are trickier, but not impossible. An image saved as a .txt file will just look like pages and pages of this:

So, there are two things you can do right away:

(i) Change all the file extensions to, for example, .jpg — the ones that really are images will turn back into images, like in Cinderella, and they’ll show up as thumbnail images instead of that blank jpeg file icon. For the love of all that is holy, do not do this by hand. I used Renamer, which has a free fourteen day trial.

(ii) Sort the files by size. For the most part, your image files will be larger than the other files, and drift up towards the top of the list, making the thumbnails easier to spot.

Make sure you’ve renamed everything correctly and recreated all your folders. Use your HTML files to figure out what your CSS files were called, what your image extensions were, etc.

LINKS:

Here’s a really useful thread on Stack Overflow where Mark Longair saves a bunch of people from hellfire. This technique didn’t work for me, but it seems to have worked for most of the other people who tried it. All the comments/answers on the page are useful, and there’s one that tells you what to do if you’ve only lost one file. (You cherry-pick!): http://stackoverflow.com/questions/7374069/undo-git-reset-hard/7376959#7376959

Good luck. Hope this helped. If it didn’t, keep digging. I tried probably every single thing suggested on Stack Overflow before I found the Cambridge Technology Partners’ solution that finally worked.

Also, you can rest easy knowing that you’ve just screwed yourself over in one of the most thorough possible ways. You’ve pretty much hit rock bottom. Welcome! This is a safe space. Everything will be hilarious and nothing will be stressful for at least two weeks. (At least nothing related to coding. I make no promises about life outside coding, if you happen to have one of those.)

Lastly: If, after doing a git hard reset, you find yourself never wanting to use command line again, remember that with git patching you get to work with hunks.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *