Git: Beginner to Advanced
Undo and recovery
Choose the right way to reverse a change.
Lesson 7 of 12
Reading: about 6 min
Lesson + practice: about 15 min
Difficulty: Intermediate
On this page5 sections
Choose the right way to reverse a change. Follow the animated example, then use the sections below to review each idea.
Visual walkthrough
Use the player controls or jump menu to inspect each step. The diagram changes as the example moves forward.
The player shows one focused example. The sections below explain the ideas behind each topic.
Every Git mistake has a matching undo, and the right one depends on where the change is: still in your working file, staged for the next commit, or already saved in a commit. Pick the wrong tool and you either undo too little or throw away work you meant to keep.
This lesson follows one file, notes.md, through each case, in the same order as the walkthrough above. Commit IDs in your repository will differ.
| Situation | Command |
|---|---|
| Throw away an edit in a working file | git restore file |
| Unstage a file but keep the edit | git restore --staged file |
| Fix the latest commit (not pushed yet) | git commit --amend |
| Undo any commit, even a pushed one | git revert commit |
| Find a commit lost after amend, reset or deleting a branch | git reflog |
Restore a working file
You edited notes.md and want to go back to the last saved version. Look before you discard: git diff shows exactly what you are about to lose.
Check, then discard the edit
M in the second column means the file is changed but not staged. git restore copies the staged version back over your working file, so the edit is gone and git status is clean.
git status --short
git diff
git restore notes.md
git status --short
cat notes.md$ git status --short
M notes.md
$ git diff
diff --git a/notes.md b/notes.md
index e965047..670a245 100644
--- a/notes.md
+++ b/notes.md
@@ -1 +1 @@
-Hello
+Hello, Git!
$ git restore notes.md
$ git status --short
$ cat notes.md
HelloReset staged changes
You staged a file by mistake. Unstaging takes it out of the next commit but leaves your edit in the file, so nothing is lost.
Unstage without losing the edit
The status changes from M (staged) to M (changed, not staged). The file still contains “Hello again”.
git status --short
git restore --staged notes.md
git status --short
cat notes.md$ git status --short
M notes.md
$ git restore --staged notes.md
$ git status --short
M notes.md
$ cat notes.md
Hello againYou will also see the older command git reset file in tutorials. With a file name, it does the same job:
$ git reset notes.md
Unstaged changes after reset:
M notes.mdRevert a commit
Once a change is committed, and especially once you have pushed it, do not try to remove it from history. git revert makes a new commit that does the opposite of the old one. The history stays honest, and anyone who already pulled the old commit can simply pull the revert too.
Undo the latest commit with a new one
HEAD means the commit you are on. --no-edit accepts Git's default message. The original commit is still in the log; the new commit puts the file back to “Hello”.
git commit -m "Add greeting"
git revert --no-edit HEAD
git log --oneline
cat notes.md$ git commit -m "Add greeting"
[main b1ba2a7] Add greeting
1 file changed, 1 insertion(+), 1 deletion(-)
$ git revert --no-edit HEAD
[main a972fd0] Revert "Add greeting"
1 file changed, 1 insertion(+), 1 deletion(-)
$ git log --oneline
a972fd0 Revert "Add greeting"
b1ba2a7 Add greeting
da840bf Add notes
$ cat notes.md
HelloTo revert an older commit, give its ID instead of HEAD, for example git revert b1ba2a7. If later commits changed the same lines, Git may stop with a conflict, which you resolve exactly as in the Merging lesson.
Amend and reflog
git commit --amend replaces the latest commit with a new one. Use it to fix a typo in the message, or stage a forgotten file first and amend to include it.
Replace the latest commit
The log shows Undo greeting where Revert "Add greeting" used to be, with a new ID. Git may also print the original commit's date on a Date: line.
git commit --amend -m "Undo greeting"
git log --oneline$ git commit --amend -m "Undo greeting"
[main 4611932] Undo greeting
1 file changed, 1 insertion(+), 1 deletion(-)
$ git log --oneline
4611932 Undo greeting
b1ba2a7 Add greeting
da840bf Add notesThe old commit is not deleted straight away. git reflog lists every place HEAD has recently pointed, so you can get back to commits that no longer appear in git log.
Find and rescue the replaced commit
HEAD@{1} means “where HEAD was one move ago”: the commit before the amend. Creating a branch there brings it back into view.
git reflog -4
git branch rescue HEAD@{1}
git log --oneline rescue -1$ git reflog -4
4611932 HEAD@{0}: commit (amend): Undo greeting
a972fd0 HEAD@{1}: revert: Revert "Add greeting"
b1ba2a7 HEAD@{2}: commit: Add greeting
da840bf HEAD@{3}: commit (initial): Add notes
$ git branch rescue HEAD@{1}
$ git log --oneline rescue -1
a972fd0 Revert "Add greeting"You committed a password file and already pushed to the shared repository. revert or amend?
Reveal answer
git revert is the safe way to undo the commit for everyone, because it does not rewrite shared history. But the password has already been exposed in history, so treat it as leaked and change it straight away.
You ran git restore --staged notes.md. Is your edit lost?
Reveal answer
No. It is only removed from the staging area. The edit is still in your working file, shown as M notes.md, ready to stage again.
Your progress
Reveal the check answer or reach the end to complete this lesson.