DevOps & Workflow5 min read

    How to undo a git commit

    Share

    "Undoing" a commit in git can mean very different things depending on whether the commit has been pushed, whether you want to keep the changes, and whether anyone else has pulled from your branch. Picking the wrong tool is how people accidentally lose work or rewrite history other people are already building on.

    This guide walks through each case and the safe answer for it.


    First, decide which case you're in

    Ask three questions:

    1. Has the commit been pushed? If yes, anything that rewrites history (reset, commit --amend, force-push) will affect collaborators. Prefer git revert.
    2. Do you want to keep the changes in your working tree? That decides between --soft, --mixed, and --hard resets.
    3. How many commits back do you need to undo? One, several, or "back to a known good commit".

    The right command falls out of the answers.


    Undo the last commit, keep the changes

    The most common case: you committed too early, want to rework the changes, and nothing has been pushed.

    git reset --soft HEAD~1
    

    The commit is gone, but every file change is still staged. Edit, re-stage, re-commit.

    If you want the changes unstaged but kept in your working tree:

    git reset --mixed HEAD~1     # --mixed is the default
    

    Undo the last commit, throw the changes away

    git reset --hard HEAD~1
    

    This deletes the commit and the changes. Use only when you're sure you don't want them — and remember that a hard reset can usually still be recovered with git reflog for a couple of weeks.


    Fix the last commit instead of removing it

    If the previous commit is fine but you want to:

    • adjust the message, or
    • include one more file change,

    then --amend is what you want, not a reset.

    # fix the message only
    git commit --amend -m "better message"
    
    # add more changes to the same commit
    git add path/to/file
    git commit --amend --no-edit
    

    --amend rewrites the commit. Don't amend a commit that has already been pushed and pulled by others.


    Undo a commit that has already been pushed

    The safe answer is git revert. It creates a new commit that undoes the changes of an earlier commit, leaving history intact.

    git revert <sha>
    git push
    

    Revert the most recent commit:

    git revert HEAD
    

    Revert a merge commit (you must tell git which parent to keep — usually 1, the branch you merged into):

    git revert -m 1 <merge-sha>
    

    If you really must rewrite pushed history (e.g., you accidentally pushed secrets), see "Force-pushing safely" below — but revert is the default answer.


    Undo several commits at once

    Reset back to a specific commit

    git log --oneline       # find the SHA you want to land on
    git reset --soft <sha>  # or --mixed, or --hard
    

    Everything after that commit becomes uncommitted (or vanishes, with --hard).

    Revert a range of pushed commits

    git revert --no-commit <oldest>^..<newest>
    git commit -m "Revert feature X"
    

    --no-commit collapses the reverts into the index so you produce one revert commit instead of one per commit.


    Undo just one file from a commit

    If you committed too much and only want to back one file out:

    git checkout HEAD~1 -- path/to/file
    git commit -m "Revert path/to/file"
    

    Or, equivalently, with git restore:

    git restore --source=HEAD~1 -- path/to/file
    git commit -am "Revert path/to/file"
    

    Force-pushing safely

    After a reset or --amend on a branch you've already pushed, your local and remote diverge. git push will be rejected. You then have a choice:

    • git push --force — overwrites the remote with your local. Dangerous: if a teammate pushed in the meantime, their work is gone.
    • git push --force-with-lease — refuses the push if the remote has commits you haven't seen. Use this. Always.
    git push --force-with-lease
    

    Even with --force-with-lease, do not force-push to shared branches like main or master without coordinating with the team.


    Recover a commit you "accidentally" undid

    git reset --hard and similar destructive operations don't actually delete the commit immediately — git's reflog remembers where every branch and HEAD pointed for a while.

    git reflog
    # find the SHA from before your reset
    git reset --hard <sha>
    

    This works for at least 30 days by default (controlled by gc.reflogExpire). If the reflog has rotated out, git fsck --lost-found may still surface the dangling commit.


    Quick reference

    Situation Command
    Last commit, keep staged changes git reset --soft HEAD~1
    Last commit, keep unstaged changes git reset HEAD~1
    Last commit, discard everything git reset --hard HEAD~1
    Tweak last commit's message git commit --amend
    Add files to last commit git add . && git commit --amend --no-edit
    Undo a pushed commit git revert <sha>
    Undo a pushed merge git revert -m 1 <merge-sha>
    Undo a range of pushed commits git revert --no-commit A^..B then commit
    Recover after a destructive command git reflog then git reset --hard <sha>

    Summary

    • Local commit → reset (soft / mixed / hard depending on what you want to keep).
    • Pushed commit → revert is almost always the safe answer.
    • Want to fix the last commit, not remove it → --amend.
    • After rewriting history, always push with --force-with-lease, never plain --force.
    • If you do destroy something, git reflog is your friend for the next 30 days.