Skip to content
Laviyx Learn

Try

Git and GitHub course menu

git reset Soft, Mixed and Hard, and Recovering with git reflog

Understand git reset --soft, --mixed and --hard, undo commits, move work off main, and recover lost commits and deleted branches with git reflog.

Advanced7 min readUpdated
On this page

git reset moves the current branch to another commit. The commits after that point are no longer on the branch. What happens to their changes depends on the mode.

The three modes#

Each mode goes one step further:

ModeMoves the branchClears the staging areaChanges your files
--softYesNoNo
--mixed (default)YesYesNo
--hardYesYesYes

Start from three commits:

Terminal
git log --oneline
Output
bf1c290 Commit three
f5af04c Commit two
83befe6 Commit one

--soft: undo the commit, keep it staged#

Terminal
git reset --soft HEAD~1
git log --oneline
git status --short
Output
f5af04c Commit two
83befe6 Commit one
M  app.txt

The commit is gone, but its changes are staged, ready to commit again. Use this to rewrite the last commit, or to combine commits.

--mixed: undo the commit, keep the edits#

Terminal
git reset HEAD~1
git status --short
Output
Unstaged changes after reset:
M	app.txt
 M app.txt

The changes are back in your files but unstaged. Use this to reorganise work into different commits.

--hard: throw it all away#

Terminal
git reset --hard HEAD~1
git log --oneline
cat app.txt
Output
HEAD is now at f5af04c Commit two
f5af04c Commit two
83befe6 Commit one
one
two

The branch, staging area and files all went back.

The reflog: your safety net#

Commit three has gone from the log, but it is not deleted. Git records every position HEAD has been at, in a local log called the reflog:

Terminal
git reflog -n 4
Output
f5af04c HEAD@{0}: reset: moving to HEAD~1
c2ab56f HEAD@{1}: commit: Commit three
f5af04c HEAD@{2}: reset: moving to HEAD~1
db63e10 HEAD@{3}: commit: Commit three

HEAD@{1} means "where HEAD was one move ago". Go back there:

Terminal
git reset --hard HEAD@{1}
git log --oneline
Output
HEAD is now at c2ab56f Commit three
c2ab56f Commit three
f5af04c Commit two
83befe6 Commit one

The "lost" commit has returned. This works after a bad reset, rebase or amend.

Recover a deleted branch#

Terminal
git switch -q -c experiment
echo "idea" > idea.txt
git add .
git commit -q -m "Try an idea"
git switch -q main
git branch -D experiment
Output
Deleted branch experiment (was d004a4f).

The output shows the ID of the last commit. If you have lost that too, find it in the reflog. Here, HEAD@{1} is the position just before we switched back to main:

Terminal
git branch experiment HEAD@{1}
git log --oneline experiment -n 1
Output
d004a4f Try an idea

How long does the reflog last?#

The reflog is local: it is not pushed, and a fresh clone has none. Entries last 90 days by default, or 30 days for commits no longer on any branch, and after that Git may delete them. Unsaved edits were never committed, so they are never in the reflog.

Fix: commits made on main by mistake#

You should have been on a feature branch. Create the branch where you are, then move main back. Here the last commit belongs on the new branch:

Terminal
git switch -q -c feature
git switch -q main
git reset --hard HEAD~1
git log --oneline --graph --all
Output
HEAD is now at f5af04c Commit two
* d004a4f Try an idea
* c2ab56f Commit three
* f5af04c Commit two
* 83befe6 Commit one

If you had already pushed to main, don't do this: use git revert.

Unstage with reset#

You may see git reset HEAD file in older guides. It does the same as git restore --staged file.

Common mistakes#

Practice#

Practice exercise

On feature, remove the last commit with git reset --hard, confirm it has gone, then bring it back using the reflog and print the log.

Show solution
Terminal
git switch -q feature
git reset -q --hard HEAD~1
git log --oneline -n 1
git reset -q --hard HEAD@{1}
git log --oneline -n 1
Output
f5af04c Commit two
c2ab56f Commit three

Key takeaway#

Next: Finding Bugs with bisect and blame.

Finished this lesson?