Undoing Changes in Git

Safely undo mistakes at every stage: unstaged edits, staged files, the last commit and older commits.

Lesson 9 of 30Beginner18 min read

Everyone makes mistakes: editing the wrong file, committing too early, writing a typo in a commit message or committing a change that breaks the site. One of Git's best features is that almost every mistake can be undone.

The right command depends on where the mistake is. Has the change only been made in your files? Has it been staged? Has it been committed? And has that commit already been shared with other people? Each situation has its own safe fix.

In this lesson you'll learn the five undo tools beginners need: git restore, git commit --amend, git revert, git reset and git stash.

Undoing changes that aren't committed

  • Discard edits to a file and go back to the last committed version:
Terminal
git restore index.html
  • Unstage a file you added by mistake, keeping your edits:
Terminal
git restore --staged index.html

git status even suggests these commands next to each file. Be careful with the first one: edits you discard were never committed, so Git can't bring them back.

Fixing the last commit with --amend

Forgot a file, or made a typo in the message? If you haven't pushed the commit yet, amend it:

Terminal
git add forgotten-file.css
git commit --amend -m "Add contact page and its styles"

--amend replaces the last commit with a new one that includes the staged changes and the new message. Because it replaces a commit, don't amend commits that other people already have.

git revert: the safe undo for shared commits

git revert <hash> creates a new commit that does the exact opposite of an earlier one. The original commit stays in the history, and a new "Revert ..." commit cancels it out.

Because nothing is deleted or rewritten, revert is the safe choice for commits that have already been pushed and shared. Your teammates simply receive the new commit.

git reset and git stash

git reset moves the current branch back to an earlier commit:

  • git reset --soft HEAD~1 removes the last commit but keeps its changes staged.
  • git reset HEAD~1 removes the last commit and keeps the changes as unstaged edits.
  • git reset --hard HEAD~1 removes the last commit and throws its changes away.

HEAD~1 means "one commit before HEAD". Only reset commits that haven't been pushed.

git stash is different: it puts your uncommitted changes on a shelf so you can switch tasks, then git stash pop brings them back.

Undoing Changes in Git Syntax

Undo commands

git restore <file>            # discard edits
git restore --staged <file>   # unstage
git commit --amend -m "msg"   # fix last commit
git revert <hash>             # undo a commit with a new commit
git reset --soft HEAD~1       # remove last commit, keep changes staged
git stash                     # shelve changes
git stash pop                 # bring them back

Undoing Changes in Git Summary

  • git restore <file> discards uncommitted edits; git restore --staged <file> unstages.
  • git commit --amend fixes the last commit before it's pushed.
  • git revert <hash> adds a new commit that undoes an old one, safe for shared history.
  • git reset moves a branch back; --hard also discards changes. Only use it on unpushed commits.
  • git stash and git stash pop park and restore unfinished work.

Undoing Changes in Git Examples

Each example shows the code, the output it produces and what each part does.

Example 1

Discard and unstage

Terminal
git status --short
git restore --staged notes.txt
git restore index.html
git status --short
Output
A  notes.txt
 M index.html
?? notes.txt
Line-by-line explanation
  1. Line 1notes.txt is staged (A) and index.html has unstaged edits (M).
  2. Line 2Unstage notes.txt. It becomes untracked (??) again, but the file is kept.
  3. Line 3Throw away the edits to index.html. It no longer appears in the status.
Example 2

Fix the last commit message

Terminal
git commit -m "Add contcat form"
git commit --amend -m "Add contact form"
git log --oneline -1
Output
[main 8a2f6c0] Add contcat form
 1 file changed, 24 insertions(+)
[main 1e93b47] Add contact form
 Date: Mon Sep 2 10:14:03 2024 +0100
 1 file changed, 24 insertions(+)
1e93b47 (HEAD -> main) Add contact form
Line-by-line explanation
  1. Line 1A typo in the message.
  2. Line 2--amend replaces the commit. Notice the new hash.
  3. Line 3Only the corrected commit is in the history.
Example 3

Revert a pushed commit

Terminal
git log --oneline -3
git revert 0c3b9d4 --no-edit
git log --oneline -3
Output
e7d0b3c (HEAD -> main) Merge branch 'footer-links'
0c3b9d4 Change button colour to red
52ac9e1 Add dark colour scheme
[main 6f1d8e9] Revert "Change button colour to red"
 1 file changed, 1 insertion(+), 1 deletion(-)
6f1d8e9 (HEAD -> main) Revert "Change button colour to red"
e7d0b3c Merge branch 'footer-links'
0c3b9d4 Change button colour to red
Line-by-line explanation
  1. Line 2revert creates a new commit that undoes 0c3b9d4. --no-edit accepts the default message.
  2. Line 3The original commit is still in the history, followed by the revert.
Example 4

Stash work to switch tasks

Terminal
git stash
git switch main
# fix the urgent bug and commit it here
git switch dark-mode
git stash pop
Output
Saved working directory and index state WIP on dark-mode: 52ac9e1 Add dark colour scheme
Switched to branch 'main'
Switched to branch 'dark-mode'
On branch dark-mode
Changes not staged for commit:
	modified:   styles.css
Dropped refs/stash@{0}
Line-by-line explanation
  1. Line 1Unfinished changes are shelved, leaving a clean working tree.
  2. Lines 2 to 4You can now switch branches and work on something else.
  3. Line 5stash pop puts the changes back and removes them from the shelf.

Common Undoing Changes in Git Mistakes

Using reset --hard on shared commits

Don't
git reset --hard HEAD~2
git push --force
Do
git revert <hash-of-bad-commit>
git push

Rewriting pushed history breaks your teammates' copies. Revert adds a fix without rewriting anything.

Discarding work you meant to keep

Don't
git restore styles.css   # all uncommitted edits are gone
Do
git stash                # keep them safely on the shelf

If you're not sure you want to throw changes away, stash them instead.

Amending after pushing

Don't
git push
git commit --amend -m "Better message"
git push      # rejected: your branch and origin have diverged
Do
git push
git commit -m "Fix typo in heading"   # make a new commit instead
git push

Undoing Changes in Git in Real Projects

Undo in practice

When a release breaks the live site, teams usually git revert the bad commit and deploy again within minutes, then fix the problem properly later. Developers use git stash constantly when an urgent bug interrupts a half-finished feature, and --amend to tidy commits before opening a pull request.

Undoing Changes in Git FAQ

How do I undo git commit --amend?

Run git reset --soft HEAD@{1}. HEAD@{1} is where your branch pointed before the amend, so this puts the branch back on the original commit and leaves the amended changes staged. You can then commit them separately or adjust them.

How do I change the message of an older commit?

Use an interactive rebase: git rebase -i HEAD~3, change pick to reword on the commit you want, save, and Git lets you edit that message. This rewrites the commit and everything after it, so only do it on commits you haven't pushed or shared.

How do I restore a file to how it was in an earlier commit?

Run git restore --source=3f9c2ab path/to/file, using the hash of the commit that has the version you want. Only that file changes in your working folder; the history stays as it was. Commit the file afterwards if you want to keep the old version.

How do I undo a git revert?

A revert is just a normal commit, so you can revert it too: git revert <hash-of-the-revert> brings the original changes back. If the revert hasn't been pushed yet, git reset --hard HEAD~1 removes it instead, as long as you have no uncommitted work to lose.

Can I get my work back after git reset --hard?

Committed work, yes: run git reflog, find the commit your branch was on before the reset, and run git reset --hard with that entry, such as HEAD@{1}. Changes that were never committed or stashed can't be recovered this way, because Git never stored them.

Undoing Changes in Git Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Fill in the blankseasy

Complete the command to unstage logo.png without losing your changes.

git   logo.png
Multiple choicemedium

A bad commit has already been pushed and your teammates have pulled it. How should you undo it?

Multiple choicemedium

What does git reset --soft HEAD~1 do?

Predict the outputeasy

After git stash, what does git status show?

Multiple choicehard

A bad commit is already pushed and shared. What's the safest way to undo it?

Undoing Changes in Git Quiz

5 questions to check what you learned.

  1. Which command discards uncommitted edits to a file?

    • git revert file
    • git restore file
    • git remove file
    • git stash pop file
  2. What does HEAD~1 refer to?

    • The first commit ever
    • The commit before the current one
    • The next commit
    • The main branch
  3. Why is git revert safe for shared history?

    • It adds a new commit instead of changing existing ones
    • It deletes the bad commit everywhere
    • It asks teammates for permission
    • It only works offline
  4. Which command brings back changes saved with git stash?

    • git stash undo
    • git restore --stash
    • git unstash
    • git stash pop
  5. What does git restore --staged file do?

    • Deletes the file
    • Restores the file from GitHub
    • Unstages the file but keeps your edits
    • Commits the file