First: Did You Already Push?
The right command depends on one question above all else: have you pushed the commit to a remote yet? If not, you have full freedom. If yes, your options narrow because you need to avoid rewriting history that others may already have pulled.
Use the decision tree below, then jump to your scenario.
Did you push the commit?
│
├── NO (local only)
│ ├── Keep your changes? → git reset --soft HEAD~1
│ ├── Discard changes? → git reset --hard HEAD~1
│ └── Fix commit message? → git commit --amend
│
└── YES (already pushed)
├── On a feature branch → git revert HEAD (safe)
├── On main/protected → git revert HEAD (only option)
└── Shared history → NEVER use reset --hard
Scenario 1: Undo the Last Commit, Keep Your Changes
You committed too early. The code changes are correct, you just want to recommit differently — maybe to fix the message, split into smaller commits, or add a forgotten file.
git reset --soft HEAD~1
This moves the branch pointer back one commit but leaves your changes staged, ready to recommit. Your working directory is untouched.
To go back two commits:
git reset --soft HEAD~2
Scenario 2: Undo the Last Commit, Discard All Changes
You want to completely erase the commit and the changes it introduced — start fresh as if it never happened.
git reset --hard HEAD~1
Warning: This permanently discards your working directory changes. There is no undo for --hard unless you use git reflog (see Scenario 6 below).
Scenario 3: Undo the Last Commit, Keep Changes Unstaged
You want to undo the commit but keep the changes in your working directory without staging them — useful when you want to review what changed before deciding what to do next.
git reset HEAD~1 # or equivalently: git reset --mixed HEAD~1
Scenario 4: Fix the Commit Message (Not Pushed)
The commit is fine but you made a typo in the message, or you want to update it to follow Conventional Commits format.
git commit --amend -m "fix(auth): correct typo in login error message"
If you want to open your editor instead of passing the message inline:
git commit --amend
You can also stage additional files before amending to include them in the same commit.
Scenario 5: Undo a Commit That Was Already Pushed
The commit is on the remote. git reset would rewrite history — if anyone else has pulled, you will create divergence and force-push problems. The safe solution is git revert, which creates a new commit that undoes the changes without erasing history.
# Revert the last commit git revert HEAD # Revert a specific commit by its hash git revert a1b2c3d # Revert without immediately committing (review first) git revert HEAD --no-commit git revert --continue
git revert is always safe on shared branches. It adds a revert commit to history but never removes commits.
Scenario 6: Recover a Commit After git reset --hard
You ran git reset --hard and realized you needed those changes. Git does not immediately delete commits — they still exist in the reflog for 30–90 days.
# See the reflog — find the commit hash you want to recover
git reflog
# Output looks like:
# a1b2c3d HEAD@{0}: reset: moving to HEAD~1
# f4e5d6c HEAD@{1}: commit: feat: add user dashboard ← this is what you lost
# Recover it
git checkout f4e5d6c
# or restore the branch to that point
git reset --hard f4e5d6c
The reflog is your safety net. It records every change to HEAD, including resets and amends.
Scenario 7: Undo a Commit in the Middle of History
You want to undo a commit from 5 commits ago, not the most recent one.
# Find the commit hash git log --oneline # Revert it specifically (creates a new revert commit) git revert a1b2c3d # If the commit is not pushed and history is local-only: # Use interactive rebase to drop it git rebase -i HEAD~5 # In the editor, change 'pick' to 'drop' on the commit to remove
Quick Reference
| Scenario | Command | Safe to push? |
|---|---|---|
| Undo commit, keep changes staged | git reset --soft HEAD~1 |
Not pushed only |
| Undo commit, keep changes unstaged | git reset HEAD~1 |
Not pushed only |
| Undo commit, discard all changes | git reset --hard HEAD~1 |
Not pushed only |
| Fix commit message | git commit --amend |
Not pushed only |
| Undo pushed commit safely | git revert HEAD |
Yes — always safe |
| Recover lost commit | git reflog then git reset --hard <hash> |
Not pushed only |
The golden rule: never rewrite history on a shared branch. If the commit is on a branch that others use, always use git revert. For personal git workflows, git reset is fine and cleaner. Use our Diff Checker to review changes before committing, and our Conventional Commits Formatter to write structured messages that make your git history easier to navigate.