Emmanuel Corels
← Blog
Cloud & DevOps

Undo a Git commit without losing the work

Reset, amend or revert? Choose from the commit’s publication state and decide explicitly what should happen to the index and working tree.

By Emmanuel Corels

An accidental commit creates two separate questions: should the branch stop pointing at that commit, and should the file changes remain available? Git can answer those independently. Most data loss happens when someone reaches for --hard before deciding what should survive.

First establish whether the commit is private or shared

git status
git branch --show-current
git log --oneline --decorate -5
git show --stat --summary HEAD

If the commit exists only in your local branch, rewriting that local history is normally reasonable. If it has been pushed to a branch other people consume, prefer a new revert commit. This is the central distinction in Git’s own documentation: reset moves a branch tip and changes history; revert records a new commit that applies the inverse change.

Keep the changes staged: soft reset

Use this when the snapshot is correct but the commit boundary or message is wrong:

git branch rescue/before-undo
git reset --soft HEAD~1
git status

HEAD~1 means the first parent of the current commit. A soft reset moves the branch back one commit while leaving both the index and working tree intact. The changes remain staged, ready to split, amend or recommit.

git restore --staged path/to/file
git commit -m "Focused change with corrected scope"

Keep the files but unstage them: mixed reset

The accepted Stack Overflow solution uses the default mixed mode:

git branch rescue/before-undo
git reset HEAD~1
git status

The branch moves back and the index is reset, but the working-tree files remain. This is useful when you want to review every hunk before rebuilding the commit:

git add -p
git diff --cached
git commit -c ORIG_HEAD

ORIG_HEAD records the previous tip for this operation; -c opens the old message for editing. Check it rather than assuming it contains what you expect after several history-changing commands.

Correct the latest private commit in place

If the commit should remain one commit, amend it:

# edit files
git add -p
git diff --cached
git commit --amend

Amending creates a new commit object. Its hash changes even if only the message changes, so do not treat amend as harmless after publication.

Undo a commit that has already been shared

git pull --ff-only
git revert <commit-id>
git show --stat HEAD
git push

Revert preserves the existing history and appends an explicit reversal. That makes the correction visible to collaborators and automation. If later commits touch the same lines, Git may stop for conflicts; resolve the files, stage them and continue with git revert --continue. For a merge commit, identify the mainline parent deliberately with -m; do not guess.

Why reset --hard is not the default answer

A hard reset updates the branch, index and working tree together. Uncommitted tracked changes can disappear. If destroying the local files is genuinely intended, inspect first and create a recovery pointer:

git status --short
git diff
git diff --cached
git branch rescue/before-hard-reset
git reset --hard HEAD~1

Untracked files are a separate concern and are not removed by reset. Avoid adding git clean to a recovery recipe unless its preview, git clean -nd, has been reviewed.

Recovery when you reset the wrong commit

git reflog --date=local -10
git show <old-head-from-reflog>
git branch rescue/recovered <old-head-from-reflog>

The reflog often retains the former local branch tip, but it is a recovery mechanism with expiry—not a backup. Create a branch as soon as you identify the correct object.

A decision table worth keeping

SituationOperationFiles afterward
Private commit; keep changes stagedgit reset --soft HEAD~1Staged
Private commit; review and restagegit reset HEAD~1Modified, unstaged
Private latest commit; correct itgit commit --amendIncluded in replacement commit
Published commitgit revert <id>Inverse recorded in a new commit

Before moving a branch, create a name that still points to where you are. A rescue branch costs almost nothing and turns panic into a reversible operation.

Sources: the solved Stack Overflow question (question by Hamza Yerlikaya; accepted answer by Esko Luontola, CC BY-SA), the git-reset documentation, and Git’s Fixing mistakes guide.

Primary source: Review the official reference ↗