Skip to main content
Sometimes you commit changes you did not intend to commit. Git provides several ways to undo actions:

git revert

Creates a new commit that undoes a previous commit. Safe for shared branches — preserves history.

git reset

Moves the branch pointer back to an earlier commit. Has three modes: soft, mixed, and hard.

Revert

Use git revert when you want to undo a commit while keeping the full Git history intact.
git revert creates a new commit that reverses all the changes made in the specified commit. The original commit remains in the history. For example, given this history:
docs: create first story
docs: create second story
docs: create programming
docs: create test         <-- want to undo this
Run:
git revert <commit-id>
Git creates a new “Revert” commit that deletes the test file, leaving your history as:
docs: create first story
docs: create second story
docs: create programming
docs: create test
Revert "docs: create test"

Reset

git reset moves the branch pointer back to an earlier commit. There are three modes:

soft

All changes from the undone commits are moved to the staging area. Nothing is lost — you can review and recommit them.
git reset --soft <commit-id>
git reset --soft HEAD~1    # undo the last commit
After a soft reset, run git status to see the staged changes.

hard

git reset --hard permanently discards all changes from the undone commits. This cannot be undone easily — use with caution.
All changes from the undone commits are permanently deleted.
git reset --hard <commit-id>
git reset --hard HEAD~1    # undo the last commit and discard its changes

mixed

All changes from the undone commits are moved to the working directory (unstaged). This is the default mode if no flag is specified.
git reset --mixed <commit-id>
git reset --mixed HEAD~1   # undo the last commit, keep changes unstaged
After a mixed reset, run git status to see the unstaged changes.

Comparison

Use git revert when the commit has already been pushed to a shared remote branch. It adds a new commit to undo the change without rewriting history, which is safe for collaboration.
Use --soft when you want to undo a commit but keep all the changes staged and ready to be rewritten into a new commit.
Use --mixed (the default) when you want to undo a commit and review the changes before deciding what to stage and recommit.
Use --hard only when you are certain you want to permanently discard all changes from the undone commits. This is destructive and cannot be easily undone.

Build docs developers (and LLMs) love