A last Git commit can be wrong in different ways: bad message, missing file, local-only commit, or shared remote history. To undo the last Git commit safely, decide whether to rewrite local history with git commit --amend or git reset, or preserve shared history with git revert.
Git has no built-in git undo command for every commit mistake. git commit --amend replaces the latest commit, git reset moves the branch pointer while choosing what stays staged or unstaged, and git revert adds a normal undo commit. For a one-commit repository, git update-ref -d HEAD removes the first branch tip while keeping files staged.
Understand Which Git Undo Command Fits the Last Commit
Pick the command by what you need to preserve. Use git commit --amend for a last-commit correction, git reset --soft HEAD~1 to remove the commit while keeping changes staged, git reset HEAD~1 to keep changes unstaged, and git reset --hard HEAD~1 only when tracked changes can be discarded. Use git revert HEAD after a shared push, or git update-ref -d HEAD when the last commit is also the initial commit.
Quick Reference for Git Undo Tasks
| Situation | Best Command | What Happens | Shared Branch Safe? |
|---|---|---|---|
| Fix the last commit message or add a forgotten file | git commit --amend | Replaces the last commit with a corrected commit | No |
| Undo the last local commit but keep changes staged | git reset --soft HEAD~1 | Removes the commit and keeps the same index | No |
| Undo the last local commit but keep changes unstaged | git reset HEAD~1 | Removes the commit and leaves changes in the working tree | No |
| Redo the commit after a reset with the old message | git commit -C ORIG_HEAD | Creates a replacement commit with the previous message | No |
| Delete the last local commit and discard tracked changes | git reset --hard HEAD~1 | Moves the branch back and resets tracked files | No |
| Undo the only commit in a new repository | git update-ref -d HEAD | Returns the repository to a no-commit state with files staged | No |
| Undo the last pushed commit on a shared branch | git revert HEAD --no-edit | Creates a new commit that reverses the last commit | Yes |
| Remove the last pushed commit from a private branch | git push --force-with-lease | Rewrites the remote branch only if the lease still matches | Private only |
The most important decision is whether the commit is already pushed. If other people may have pulled it, do not rewrite shared history with git reset unless you have explicit agreement to force-push. On shared branches, git revert is the safer choice because it preserves the visible history.
Inspect the Last Git Commit Before You Undo It
Before changing history, confirm which commit is at HEAD, whether the branch is ahead of its upstream, and whether your working tree is already dirty. That avoids undoing the wrong commit or mixing unrelated changes into the recovery.
git status -sb
git log --oneline --decorate -n 3
## main...origin/main [ahead 1] 4f8f51b (HEAD -> main) Add dashboard feature 980e8e0 (origin/main) Initial commit
In these examples, HEAD is the current commit, HEAD~1 is the parent of that commit, and HEAD~2 moves back two commits. The [ahead 1] marker means the last commit exists locally but has not reached origin/main yet, which makes reset or amend options safer than they would be after a shared push.
Verify the Git Command Is Available
If the inspection command fails because Git is not installed, check the command first:
git --version
A working Git install prints a version line. Many desktop and developer-focused Linux installations already include Git, while minimal systems may not. If git --version returns command not found, use the matching distro guide: Install Git on Ubuntu, Install Git on Debian, Install Git on Fedora, Install Git on Linux Mint, Install Git on Arch Linux, Install Git on CentOS Stream, or Install Git on Rocky Linux.
Undo the Last Git Commit with Git Commands
Change Only the Last Git Commit Message
If the code is fine and only the message is wrong, amend the last commit with a corrected message:
git commit --amend -m "Corrected commit message"
[main 9d63724] Corrected commit message Date: Sat Feb 28 07:45:13 2026 +0000 1 file changed, 1 insertion(+) create mode 100644 notes.txt
Git writes a new commit object with the updated message, so the commit hash changes. Use this only before you push the commit to a shared remote.
Add a Forgotten File to the Last Git Commit
If you forgot to stage one file, add it and amend the commit without changing the message:
git add forgotten-file.txt
git commit --amend --no-edit
[main 896ad1a] Add dashboard feature Date: Sat Feb 28 07:45:13 2026 +0000 2 files changed, 2 insertions(+) create mode 100644 draft.txt create mode 100644 forgotten-file.txt
The --no-edit flag keeps the existing commit message. This is one of the fastest ways to undo a last commit mistake without losing work.
Amend rewrites history by replacing the old commit with a new one. If the commit is already pushed to a shared branch, use
git revertinstead ofgit commit --amend.
Undo the Last Unpushed Git Commit but Keep Changes Staged
Use reset methods only for commits you have not pushed yet. Start with a soft reset when you want to remove the commit but keep everything staged for the next commit.
git reset --soft HEAD~1
git status
On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: draft.txt modified: notes.txt
Your files stay exactly as they were in the last commit, and the changes remain staged. This is useful when you want to split the commit, add another file, or rewrite the message before committing again.
Undo the Last Unpushed Git Commit but Keep Changes Unstaged
The default git reset mode is mixed reset. It removes the last commit and leaves the changes in your working tree so you can review them before staging again.
git reset HEAD~1
Unstaged changes after reset: M notes.txt
git status
On branch main Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: notes.txt Untracked files: (use "git add <file>..." to include in what will be committed) draft.txt no changes added to commit (use "git add" and/or "git commit -a")
This gives you a clean review point before you decide what to stage again. It is also identical to git reset --mixed HEAD~1.
Redo the Last Git Commit with the Original Message
After a reset moves HEAD, Git usually records the previous branch tip in ORIG_HEAD. Use it when you reset to edit files but want the replacement commit to keep the old message.
git reset HEAD~1
# Edit or stage the files you want in the replacement commit
git add notes.txt draft.txt
Create the replacement commit with the old message after the corrected files are staged:
git commit -C ORIG_HEAD
[main 4f8f51b] Add dashboard feature Date: Sat Feb 28 07:45:13 2026 +0000 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 draft.txt
The -C ORIG_HEAD option reuses the old message exactly. Use -c ORIG_HEAD instead when you want Git to open the previous message for editing before it creates the new commit.
Undo the Last Unpushed Git Commit and Discard Tracked Changes
git reset --hardpermanently discards tracked changes in the commit and your working tree. If you are not completely sure, stop atgit reset --softorgit resetinstead.
Use a hard reset only when you want the branch and tracked files to return to the previous commit exactly:
git reset --hard HEAD~1
git status
HEAD is now at 980e8e0 Initial commit On branch main nothing to commit, working tree clean
Use this only when the commit is local and you truly want it gone. Ordinary untracked files usually remain after git reset --hard, but an untracked path that blocks Git from writing a tracked path can still be removed. Review git status before treating the reset as risk-free.
If untracked files remain after the hard reset, preview them before deleting anything:
git clean -fdn
Would remove scratch.log Would remove temp.txt
Run the destructive clean only when every listed file can be deleted:
git clean -fd
Removing scratch.log Removing temp.txt
Undo the Initial Git Commit
HEAD~1 cannot exist when the repository has only one commit. If the first commit should be removed while keeping its files staged, delete the current HEAD reference instead:
git update-ref -d HEAD
git status
On branch main No commits yet Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: first.txt
The repository returns to a no-commit state, but the files from the former initial commit remain staged. Commit again with a corrected first commit, or unstage files with git rm --cached <file> when they should not be part of the new initial commit.
Do not use
git update-ref -d HEADafter publishing the initial commit to a shared remote. It removes the local branch tip, so shared repositories need a coordinated history rewrite or a follow-up revert-style correction instead.
Undo the Last Pushed Git Commit Safely
If the commit is already on a shared branch, revert it instead of resetting history. This creates a new commit that applies the inverse change and keeps the remote history intact.
git revert HEAD --no-edit
[main 2b64e75] Revert "Add new feature" Date: Sat Feb 28 07:45:13 2026 +0000 1 file changed, 1 insertion(+), 1 deletion(-)
Push the new revert commit after it is created:
git push origin main
After the push, teammates can pull normally without dealing with rewritten history. On shared branches, this is the safest way to undo the last pushed commit.
git revert HEAD also works before pushing, but it creates a second commit instead of removing the mistaken one. Use that only when the visible undo commit is useful, such as when a local branch is being reviewed exactly as a history record. For normal unpushed mistakes, git reset keeps the branch cleaner.
If you want to inspect the reverse changes before Git creates the revert commit, use git revert --no-commit HEAD. That applies the undo to your index and working tree first so you can review or combine it with other fixes.
Handle Advanced Git Undo Cases
Undo the Last Two Git Commits but Keep the Changes
When the last two commits need to be rewritten together, move HEAD back two commits with a soft reset:
git reset --soft HEAD~2
git status
On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: app.txt new file: notes.txt
This is the cleanest way to undo the last two commits without losing the work. If you prefer the changes unstaged instead, use git reset HEAD~2.
Split the Last Git Commit into Smaller Commits
When the last commit mixed unrelated work, reset it back into the working tree first:
git reset HEAD~1
git status -sb
## main M draft.txt M notes.txt
Stage and commit each logical piece separately:
git add notes.txt
git commit -m "Update dashboard notes"
git add draft.txt
git commit -m "Update dashboard draft"
git log --oneline -n 3
ab7bcc1 Update dashboard draft aae3259 Update dashboard notes 60a67ff Initial commit
If one file contains multiple unrelated hunks, use git add -p instead of staging the whole file. That lets you choose the hunks for the first replacement commit, then repeat the process for the remaining changes.
Move the Last Git Commit to a New Branch
If the last commit belongs on a new branch and has not been pushed, create that branch at the current commit before resetting the original branch:
git switch -c feature/login-fix
git switch main
git reset --hard HEAD~1
git switch feature/login-fix
The new branch keeps the commit, while main moves back one commit. If the wrong-branch commit has already been pushed, coordinate with the team before rewriting the remote branch, or open a corrective pull request from the branch that should own the work. For more branch movement examples, use switch Git branches.
Undo an Amended Git Commit
If you used git commit --amend and want the pre-amend commit back, Git’s reflog is the fastest recovery tool. It records where HEAD pointed before and after the amend.
git reflog -n 4
0211f35 HEAD@{0}: commit (amend): Add feature
4d9f79b HEAD@{1}: commit: Add feature
3638e85 HEAD@{2}: commit (initial): Initial commit
The entry at HEAD@{1} is the commit before the amend. A soft reset restores that commit while keeping the extra amended changes staged:
git reset --soft HEAD@{1}
git status
On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: notes.txt
This is a safer recovery than a hard reset because the pre-amend commit is back, but the amended difference is still available for review.
Revert the Last Git Commit Without Creating the Commit Yet
Sometimes you want the safety of git revert but still want to inspect the reverse patch before writing a new commit. That is what --no-commit is for.
git revert --no-commit HEAD
git status
On branch main You are currently reverting commit 1e12748. (all conflicts fixed: run "git revert --continue") (use "git revert --skip" to skip this patch) (use "git revert --abort" to cancel the revert operation) Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: app.txt
The reverse change is now staged, but Git has not created the revert commit yet. Finish with git commit -m "Revert ..." when the result looks right, or cancel the whole operation with git revert --abort.
Undo a Last Merge Commit
A merge commit has more than one parent, so git revert HEAD cannot guess which side should be treated as the mainline. Inspect the merge before reverting it:
git log -1 --pretty="%h %p %s"
9ab14dd 6b9c9f4 5b1d769 Merge feature/report
For a normal merge into main, parent 1 is usually the branch you were on when you ran git merge. Revert the merge while keeping that mainline parent:
git revert -m 1 HEAD --no-edit
[main 92bbe59] Revert "Merge feature/report" Date: Sat Feb 28 07:45:13 2026 +0000 1 file changed, 1 deletion(-) delete mode 100644 report.txt
If the merge commit has not been pushed and you simply want to remove it, git reset --hard HEAD~1 is the local-history option. On shared branches, prefer the git revert -m path so everyone can pull a normal new commit.
Remove the Last Pushed Git Commit from a Private Branch
Only rewrite remote history on a private branch or after your team agrees to it. For shared or protected branches, use
git revertinstead.
If the branch is private and you need the last pushed commit removed from the remote history completely, fetch first and confirm the local branch still matches the remote branch you plan to rewrite:
git fetch origin
git status -sb
## main...origin/main
Continue only when the status shows the expected private branch state. If it shows behind, ahead, or diverged unexpectedly, inspect the remote changes before rewriting anything. Capture the current remote tip, reset locally, and push with an explicit lease:
expected_remote="$(git rev-parse origin/main)"
git reset --hard HEAD~1
git push --force-with-lease=main:"$expected_remote" origin main
--force-with-lease=main:"$expected_remote" is safer than plain --force because Git checks the remote branch against the value you captured before overwriting it. Use this only for private history that must disappear, such as accidental secret commits or broken generated artifacts. If a credential was pushed, rotate or revoke it before relying on history cleanup. If the commit only tracked files that should be ignored in future commits, clear Git cache before recommitting the cleaned state.
Undo All Unpushed Git Commits on a Private Branch
If more than one local commit sits ahead of the remote branch, fetch first and inspect the exact range before resetting. This keeps a broader Git reset workflow from deleting work you meant to keep.
git fetch origin
git log origin/main..HEAD --oneline
6ca1e2c Add local note ef5c05c Add local change
git reset --hard origin/mainremoves every local commit shown in that range and discards tracked working-tree changes. Use it only when the branch is private and every listed commit should disappear.
When the listed commits are all disposable, reset the local branch back to the remote tracking branch:
git reset --hard origin/main
git status
HEAD is now at 40a3100 Initial commit On branch main Your branch is up to date with 'origin/main'. nothing to commit, working tree clean
Troubleshoot Common Git Undo Errors
Most failed repairs come from a dirty working tree or a missing recovery point. Start by proving the state, then choose the smallest fix that keeps the work you still need.
Fix Git Revert When Local Changes Would Be Overwritten
If the same file has uncommitted edits, Git protects those edits and stops before starting the revert:
git revert HEAD --no-edit
error: Your local changes to the following files would be overwritten by merge: app.txt Please commit your changes or stash them before you merge. Aborting fatal: revert failed
Check the dirty file before choosing a fix:
git status --short
M app.txt
Commit the local edit if it is ready, or stash it before rerunning the revert. Reapply the stash only if you still need those local edits after the revert succeeds, and expect to resolve conflicts if the saved edit touches the reverted lines.
git stash push -m "work before revert"
git revert HEAD --no-edit
# Reapply the stash only if you still need those local edits; resolve conflicts if prompted
git stash pop
Verify the fix with git log --oneline -n 3. A successful revert adds a new revert commit, and your saved local edit remains available through the stash until you pop or drop it.
Recover a Git Commit After a Hard Reset
If you reset too far with git reset --hard, the reflog usually gives you a recovery path:
git reflog -n 3
980e8e0 HEAD@{0}: reset: moving to HEAD~1
4f8f51b HEAD@{1}: commit: Add dashboard feature
980e8e0 HEAD@{2}: commit (initial): Initial commit
The lost commit is still visible at HEAD@{1}. Reset back to that entry:
git reset --hard HEAD@{1}
HEAD is now at 4f8f51b Add dashboard feature
Run git log --oneline -n 3 afterward and confirm the recovered commit is back at HEAD. Reflog entries expire over time, so recover as soon as you notice the mistake.
For the full option sets behind these workflows, Git’s official manuals for git-commit, git-reset, git-revert, git-reflog, git-update-ref, git-push, and git-clean document the underlying flags in detail.
Conclusion: Choose the Right Git Undo Command
A bad last Git commit is recoverable when the command matches the branch state. Use amend for small local corrections, reset for unpushed commits, revert for shared history, and reflog when a destructive reset went too far. Keep git status -sb and git log --oneline in the loop before pushing the repaired branch.


Formatting tips for your comment
You can use basic HTML to format your comment. Useful tags currently allowed in published comments:
<code>command</code>command<strong>bold</strong><em>italic</em><blockquote>quote</blockquote>