While working on a recent project, I accidentally committed some files. Instead of using git reset --soft <prev-commit-id>
to unstage them, I used git reset --hard HEAD
and all of my new changes gone with the wind. After panicking for a few minutes, I determined to learn how git reset
works and how I can revert the damages.
git reset --hard
resets the current branch tip, and also deletes any changes in the working directory and staging area (although files under git stash
will not be affected). It resets index entries to a specified commit, or the HEAD location. git reset --hard
should be used with caution, since it can lead to losing work in your staging area and working directory.
Below is the demonstration of what happened to a new file test2.txt
after a git reset --hard
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
test2.txt
$ git add test2.txt
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: test2.txt
$ git commit -m "Add test2"
[master 2d7949d] Add test2
1 file changed, 10 insertions(+)
create mode 100644 test2.txt
$ git reset --hard 6122c04
HEAD is now at 6122c04 add test
After doing the get reset --hard
to commit id 6122c04, the file test2 will be removed from the working directory
On the contrary, git reset --soft
revert your commit without removing your files from the working directory. After that you can unstage the files you don’t want to commit
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
test2.txt
$ git add test2.txt
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: test2.txt
$ git commit -m "Add test2"
[master 2d7949d] Add test2
1 file changed, 10 insertions(+)
create mode 100644 test2.txt
$ git reset --soft 6122c04
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: test2.txt
$ git restore --staged test2.txt
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
test2.txt
git reset --hard
in 3 scenariosIf you do a git reset --hard
after git add
and git commit
retrace the commit that you need to recover
git reflog
switch to the commit you want to recover, now your repo will be in ‘detached HEAD’ state
git checkout <commit-id>
to fix the detached HEAD state, create a new branch and merge the branch back to master
git branch <new-branch> <commit-id>
git checkout master
git merge <new-branch>
If you do a git reset --hard
after git add
but before git commit
Use git fsck
to check dangling blob hash id (blob that has no commits associated to it). This will help us retrieve the content of the files that were staged but not yet committed
git show <dangling blob id> > recover.txt
to send the content of the blob to a file
Another option is to use git fsck --lost-found
to move all the dangling blobs to lost-found directory. Then, cd .git/lost-found/other
to check all the dangling blob content
If you do a git reset --hard
after git add
and git commit
, your new changes before staging will still be in your directory.