There's no single undo in Git, because undoing a commit can mean different things. Do you want to fix the last commit, uncommit it but keep your changes, throw the changes away, or reverse a commit that's already shared? Each of these has its own command, and picking the right one matters.
The three main tools are amend, reset, and revert. git commit --amend rewrites the most recent commit, handy for a bad message or a forgotten file. git reset moves your branch pointer back, and depending on the mode it keeps or discards your changes. git revert creates a new commit that undoes an earlier one, which is the safe choice for commits you've already pushed.
The key line to remember: amend and reset rewrite history, so use them only on commits you haven't shared. For anything already pushed, use revert instead. This guide walks through each method, shows how to recover with git reflog if you go too far, and helps you pick the right undo for your situation.
Before you start
What you will learn
- How to undo a commit in Git the right way for your situation: fixing the last commit, uncommitting while keeping your work, discarding it, or safely undoing a pushed commit.
- Everyone commits something by mistake. Knowing the right undo for each case saves you from losing work or disrupting your team's shared history.
Requirements
- A local Git repository with at least one commit you want to change or undo.
- Git installed on your machine and a shell to run commands in.
Good to know
- Each method is a single command. The time is in choosing the right one and, if needed, recovering.
- Commands use the standard Git CLI. They work the same across recent Git versions.
- This tutorial changes your commit history. Most steps are recoverable with git reflog, but a hard reset can discard uncommitted work for good, so read the warnings first.
Quick answer
To fix the most recent commit, run git commit --amend. To uncommit the last commit but keep your changes, run git reset --soft HEAD~1. To discard the commit and its changes, run git reset --hard HEAD~1 (careful). To undo a commit you've already pushed, run git revert followed by the commit hash, which adds a new reversing commit safely.
git reset --soft HEAD~1 (undo last commit, keep changes)Step-by-step tutorial
7 stepsDecide what 'undo' means for you
Pick the right method before touching your history.
Undoing a commit can mean four different things, and the safe command depends on which you want. Do you want to fix the last commit, uncommit but keep your changes, discard the commit and its changes, or undo a commit you've already pushed?
As a rule: use amend or reset for local, unshared commits, and revert for anything already pushed. Run git log --oneline first to see your recent commits and their hashes.
git log --onelineKnowing whether the commit was pushed is the single most important thing before you start.
Fix the most recent commit with amend
Correct the last commit's message or contents without adding a new commit.
If you just need to fix the most recent commit, for example a typo in the message or a file you forgot, use git commit --amend. To change only the message, run git commit --amend and edit it. To add a forgotten file, stage it first with git add, then run git commit --amend.
Amend replaces the last commit with a new one, so it gets a new hash. Only amend commits you haven't pushed.
git add forgotten-file.txt
git commit --amend
# Change only the message without an editor:
# git commit --amend -m "New message"Use git commit --amend --no-edit to keep the message while adding staged changes.
Uncommit but keep your changes
Remove the last commit while keeping its changes in your files.
If you want to undo the commit itself but keep the work, use git reset --soft HEAD~1. This moves your branch back one commit and leaves the changes staged, ready to recommit. To keep the changes but unstage them, use git reset HEAD~1 (the default mixed mode).
Neither of these deletes your work. They just remove the commit wrapper so you can redo it, split it, or adjust it.
git reset --soft HEAD~1
# Keep changes but unstage them:
# git reset HEAD~1HEAD~1 means one commit before the current one. Use HEAD~2 to go back two commits, and so on.
Uncommit and discard the changes
Remove the last commit and throw away its changes.
If you want the commit and its changes gone entirely, use git reset --hard HEAD~1. This moves your branch back one commit and resets your files to match, discarding the changes.
This is the destructive option. Any uncommitted work is also lost. Only use it on local commits you're sure you don't need. If in doubt, prefer the soft reset above so you keep the work.
git reset --hard HEAD~1If you run this by mistake, don't panic yet: git reflog can often bring the commit back (see below).
Undo a commit you've already pushed
Reverse a shared commit safely with a new commit.
If the commit is already pushed or shared, don't rewrite history. Instead, run git revert followed by the commit hash, for example git revert 1a2b3c4. This creates a new commit that undoes the changes of that commit, leaving the history intact.
Because revert adds a commit rather than removing one, it's safe for branches other people use. After reverting, push as normal.
git revert 1a2b3c4
git pushTo undo a range of commits, you can revert several hashes; Git creates one reversing commit per commit.
Recover if you undid too much
Bring back a commit you removed by accident.
If a reset removed a commit you actually needed, git reflog usually saves you. It lists where HEAD has been, including the commit you just left. Find the hash of the state you want, then run git reset --hard <hash> to return to it.
The reflog keeps entries for a while (typically 90 days by default), so recovery works as long as Git hasn't cleaned up the unreachable commit.
git reflog
git reset --hard <hash-from-reflog>reflog is local to your machine, so recover on the same clone where the reset happened.
Verify the result
Confirm the history now looks the way you intended.
Check the outcome with git log --oneline to see the current commits, and git status to see the state of your working directory and staging area.
Make sure the commit you meant to undo is handled the way you expected: fixed, uncommitted, discarded, or reversed by a new revert commit.
git log --oneline
git statusIf you kept your changes, git status shows them staged or unstaged, ready for your next commit.
Confirm the commit was undone the way you wanted
The right result depends on the method you chose. After git commit --amend, git log --oneline shows the same number of commits, but the top one is your corrected version with a new hash. After git reset --soft or the default reset, the commit is gone from the log while your changes remain in git status. After git reset --hard, both the commit and its changes are gone. After git revert, you'll see an extra commit that undoes the target.
Whatever you did, git log --oneline and git status together tell you the real state. If a reset removed more than you meant, git reflog is your safety net for getting it back.
- git log and git status match the undo you intended: the commit is fixed, uncommitted, discarded, or reversed, and your changes are kept or removed accordingly.
- Your changes are missing after a soft reset (they shouldn't be), or a pushed branch now diverges from the remote because you reset shared history instead of reverting.
- git reset --soft HEAD~1 leaves your changes staged so you can commit them again, corrected.
- git revert 1a2b3c4 adds a new commit that reverses the change, safe for branches others use.
Troubleshooting
You ran git reset --hard and lost work
Cause: A hard reset discarded the commit and any uncommitted changes.
Run git reflog to list recent HEAD positions and find the hash of the state before the reset. Then run git reset --hard <hash> to restore it. This works as long as Git hasn't garbage-collected the unreachable commit, which usually gives you weeks.
You already pushed the commit you want to undo
Cause: Resetting or amending rewrites history and diverges from the remote.
Use git revert <commit> instead, which adds a new commit that undoes the change without rewriting history. Avoid resetting and force-pushing a shared branch unless everyone agrees, because it disrupts their clones.
After git reset HEAD~1 the changes are still in my files
Cause: That's expected: a soft or mixed reset keeps your changes and only removes the commit.
This is correct behavior. The commit is undone but the work is preserved so you can redo it. If you wanted the changes gone too, use git reset --hard HEAD~1, or stash them with git stash to set them aside.
fatal: ambiguous argument 'HEAD~1': unknown revision
Cause: There's no earlier commit to move to, usually because this is the only commit.
If it's the very first commit in the repository, there's no HEAD~1 to reset to. To undo the initial commit and start over, you can run git update-ref -d HEAD, which removes the branch pointer while keeping your files. Check git log first to confirm.
Frequently asked questions
How do I undo the last commit in Git?
It depends on what you want. Use git commit --amend to fix it, git reset --soft HEAD~1 to uncommit but keep your changes, git reset --hard HEAD~1 to discard it, or git revert if the commit is already pushed.
How do I undo a commit but keep my changes?
Run git reset --soft HEAD~1 to remove the commit and keep the changes staged, or git reset HEAD~1 to keep them unstaged. Neither deletes your work; they just remove the commit.
What's the difference between git reset and git revert?
git reset moves your branch pointer back and rewrites history, so it's for local, unshared commits. git revert creates a new commit that undoes an earlier one, which is safe for commits you've already pushed.
How do I undo a commit I already pushed?
Use git revert followed by the commit hash. It adds a new commit that reverses the change, keeping history consistent for everyone. Avoid resetting and force-pushing a shared branch.
What's the difference between --soft, --mixed, and --hard reset?
Soft keeps your changes staged, mixed (the default) keeps them unstaged, and hard discards them entirely. Soft and mixed preserve your work; hard does not.
Can I recover a commit after git reset --hard?
Usually yes. Run git reflog to find the commit's hash from before the reset, then git reset --hard <hash> to restore it. This works until Git garbage-collects the unreachable commit, which normally takes weeks.





