LearnAI ToolsCareerPractice BuildsPlayDevelopmentContact
Lesson 516 min read

Undoing Changes: restore, amend, revert and reset

Discard edits with git restore, unstage files, fix your last commit with --amend, safely reverse commits with git revert, and understand the three modes of git reset.

On this page 11 sections

Introduction

Everyone makes mistakes: deleting the wrong line, staging the wrong file, committing with a typo, or committing something that breaks the site. One of Git’s biggest benefits is that almost every mistake can be undone — as long as you pick the right command. This lesson covers the five you need, from the gentlest to the most powerful.

What You Will Learn
  • How to throw away edits you have not committed (git restore).
  • How to take a file out of the staging area (git restore --staged).
  • How to fix the message or contents of your last commit (git commit --amend).
  • How to undo a commit safely on shared history (git revert), and how git reset moves a branch back in time.

Discard Changes to a File

Priya accidentally deletes the heading from index.html and saves the file. Git notices immediately:

git status
Output

Click Run to see what this code prints.

Git even suggests the fix. git restore replaces the file in your working directory with the version from the last commit:

git restore index.html
git status
Output

Click Run to see what this code prints.

This Cannot Be Undone

git restore throws your uncommitted edits away for good — they were never committed, so Git has no copy of them. Check with git diff before you restore.

Unstage a File

Next, Priya tries a red text colour in style.css and stages it with git add style.css — then decides it should not be in the next commit. git restore --staged removes it from the staging area but keeps the edit in the file:

git restore --staged style.css
git status --short
Output

Click Run to see what this code prints.

M in the second column means the file is modified but no longer staged. To throw the edit away completely, she follows up with git restore style.css.

Fix the Last Commit

Priya changes the text colour and commits quickly — with a typo in the message:

git commit -am "Updte colours"
Output

Click Run to see what this code prints.

(The -a option stages every modified tracked file before committing, a handy shortcut when you have reviewed the changes.) To fix the most recent commit, use --amend. It replaces that commit with a new one:

git commit --amend -m "Update text colour"
Output

Click Run to see what this code prints.

git log --oneline
Output

Click Run to see what this code prints.

Look closely: the commit ID changed from bc5f55f to b04b6de. Amending does not edit a commit; it creates a replacement. If you forgot to include a file, stage it and run git commit --amend --no-edit to add it while keeping the same message.

Only Amend Commits You Have Not Shared

Because amend creates a new commit ID, never amend a commit you have already pushed to GitHub. Anyone who downloaded the old commit would end up with a conflicting history.

Safely Reverse a Commit

Suppose the colour change turns out to be a bad idea after it has been shared. git revert creates a new commit that does the exact opposite of an earlier one. History is not rewritten — it records both the change and its undo, which is why revert is the safe choice for commits other people already have:

git revert --no-edit HEAD
Output

Click Run to see what this code prints.

git log --oneline
Output

Click Run to see what this code prints.

HEAD means the latest commit; you can revert any commit by its ID, such as git revert b04b6de. Without --no-edit, Git opens your editor so you can explain why you are reverting.

Mini Challenge · Fix the Command

A commit you pushed to GitHub yesterday broke the contact page, and your teammates have already pulled it. What is the safe way to undo it?

Choose one answer

Move Back in History: git reset

git reset moves your current branch back to an earlier commit. It is powerful and useful for tidying up local work that you have not shared yet. Its three modes differ in what happens to the changes from the commits you move past:

ModeBranch moves back?Staging areaYour filesUse it to
--softYesChanges stay stagedUnchangedRedo the last commit(s) with a different message or split
--mixed (default)YesChanges unstagedUnchangedUncommit and restage selectively
--hardYesClearedChanges deletedThrow away commits and edits completely

Priya commits a draft blog page, then decides it is not ready. A soft reset undoes the commit but keeps the file staged:

git reset --soft HEAD~1
git status --short
Output

Click Run to see what this code prints.

A in the first column means “added, staged”. Running git reset with no options (a mixed reset of nothing) now unstages it, leaving an untracked file:

git reset
git status --short
Output

Click Run to see what this code prints.

Finally, a hard reset. She commits the draft again and then decides to delete it entirely:

git reset --hard HEAD~1
ls
Output

Click Run to see what this code prints.

The commit is gone from the branch and blog.html is gone from the folder. Lesson 16 shows how git reflog can still rescue commits after a hard reset — but uncommitted edits wiped by --hard are lost for good.

Mini Challenge · Spot the Problem

Priya has an hour of unsaved-to-Git edits in index.html and wants to undo her last commit. She runs git reset --hard HEAD~1. What is the problem?

Choose one answer

Which Command Should I Use?

I want to…Command
Throw away uncommitted edits to a filegit restore <file>
Unstage a file but keep my editsgit restore --staged <file>
Fix the message of my last (unpushed) commitgit commit --amend -m "new message"
Add a forgotten file to my last (unpushed) commitgit add <file> then git commit --amend --no-edit
Undo a commit that is already pushed or sharedgit revert <commit>
Uncommit my last local commit but keep the changesgit reset --soft HEAD~1 (staged) or git reset HEAD~1 (unstaged)
Delete my last local commit and its changesgit reset --hard HEAD~1
Older Commands You Will See Online

git restore was added in Git 2.23 (2019). Older tutorials use git checkout -- <file> instead of git restore <file>, and git reset HEAD <file> instead of git restore --staged <file>. They still work, but the newer commands are clearer.

Common Mistakes

Avoid These Mistakes
  • Using git reset --hard without checking git status for uncommitted work first.
  • Amending or resetting commits that are already on GitHub, which forces everyone else to repair their history.
  • Running git restore . to discard “one” change and losing edits to every file in the folder.
  • Deleting and re-cloning a repository to “undo” something — there is almost always a precise command instead.

Frequently Asked Questions

Yes. Reverting the revert commit re-applies the original change. This is a common way to bring back a feature once a bug in it is fixed.

revert adds a new commit that cancels an old one, so history only grows — safe for shared branches. reset moves the branch pointer back, removing commits from the branch — fine for local work, risky for anything shared.

Yes. The original commit still exists for a while; git reflog (lesson 16) shows its ID, and git reset --soft <that-id> brings it back.

Key Takeaways

  • git restore <file> discards uncommitted edits; git restore --staged <file> only unstages.
  • git commit --amend replaces your last commit — use it only before pushing.
  • git revert creates a new commit that undoes an old one; it is the safe choice for shared history.
  • git reset moves a branch back: --soft keeps changes staged, --mixed unstaged, --hard deletes them.
  • Uncommitted edits removed by restore or reset --hard cannot be recovered, so check git status first.

Summary

You now have a toolkit for every kind of mistake, from a stray edit to a bad commit on a shared branch. The best mistake, of course, is the one you never make — and one of the most common is committing files that should never be in a repository at all. That is what .gitignore is for.

Next Lesson →

Ignoring Files with .gitignore