Mistakes happen constantly in software development.
Git makes it safe to experiment, and more importantly, safe to undo.
Three commands handle most undo scenarios:
git revertundoes a commit by creating a new onegit resetmoves the branch pointer backwardgit restorediscards uncommitted changes
The right choice depends on whether the commit was shared and what you want to undo.
Undo a committed change with git revert
If you pushed a commit to a shared branch and need to undo it:
git revert HEAD
This creates a new commit that reverses the changes from the most recent commit.
You can also revert any commit by its hash:
git revert abc1234
Why revert is safe for shared history
git revert does not rewrite history.
It adds a new commit on top of the existing history.
That means:
- other people’s clones stay in sync
- the remote branch accepts the new commit normally
- no force pushing is needed
The original commit remains in history, but its effects are neutralized by the revert commit.
Undo local commits with git reset
If the commit has not been shared yet:
git reset HEAD~1
This moves the current branch back one commit and leaves the changes in your working tree as unstaged modifications.
The three modes of git reset
git reset behaves differently depending on the flag:
git reset --soft HEAD~1
git reset HEAD~1
git reset --hard HEAD~1
--soft moves the branch pointer back but keeps all changes staged.
No flag (the default) moves the branch pointer back and keeps changes in the working tree as unstaged.
--hard moves the branch pointer back and discards all changes completely.
When to use reset versus revert
Use git reset when:
- the commit only exists locally
- you want to redo the work differently
- you are preparing to push for the first time
Use git revert when:
- the commit was already pushed to a shared branch
- other people may have pulled the branch
- you want to keep a clear audit trail of what happened
Discard uncommitted changes with git restore
Sometimes you want to throw away changes you have not committed yet:
git restore file.txt
This replaces the file with the last committed version.
To discard all unstaged changes in the working tree:
git restore .
Unstage a file without losing changes
If you staged something by mistake:
git restore --staged file.txt
This removes the file from the staging area but keeps your changes in the working tree.
Before Git 2.23, people used git reset file.txt to unstage. git restore is the newer, more explicit way to handle this.
A practical undo decision tree
When you need to undo, ask:
-
Was the commit pushed to a shared branch?
- Yes → use
git revert - No → continue to question 2
- Yes → use
-
Do you want to keep the changes to edit them?
- Yes → use
git reset --softorgit reset(no flag) - No → use
git reset --hard
- Yes → use
-
Are the changes uncommitted?
- Yes → use
git restoreto discard them
- Yes → use
Revert does not erase history
One important mental model: git revert does not pretend the original commit never happened.
The history will show:
- the original commit that introduced the change
- the revert commit that undid it
That is usually what you want in a shared project because it keeps an honest record of what happened.
If you need to pretend a commit never existed, that is a different operation and usually involves rewriting history with reset or amend on local-only commits.
The main idea to carry forward
Git makes it safe to make mistakes.
git revert undoes shared commits by adding a new commit.
git reset rewinds local commits while optionally preserving the changes.
git restore discards uncommitted work in the working tree or staging area.
Understanding which tool to use prevents unnecessary history rewrites and keeps shared branches stable.
Quick Check
One answerYou already pushed a bad commit to a shared branch. What is the safest default?
Choose the best answer and use it to track your progress through the lesson.
Why that answer is correct
`git revert` preserves shared history and adds a new commit that undoes the old one. Reset is mainly for local history that has not been shared.