Undoing the last commit with git reset --soft
Question
How do you undo the last commit in Git while keeping the changes staged?
The correct answer is
-
git revert HEAD -
git reset HEAD~1 -
git reset --soft HEAD~Correct -
git undo HEAD~1
Explanation
TL;DR
git reset --soft HEAD~ moves the current branch back to the parent of the current commit and stops there. The index and working tree are untouched, so everything the undone commit contained is still staged, ready to be amended, split, or recommitted.
The two pieces
HEAD~ names the first parent of the current commit. It is shorthand for HEAD~1, and the notation generalizes: HEAD~2 is the grandparent, and so on.
git reset takes a target commit and moves the current branch (and HEAD with it) to that commit. The flag decides how far the reset propagates:
--soft moves HEAD only (index and working tree untouched)
--mixed moves HEAD, resets index (working tree untouched; the default)
--hard moves HEAD, index, tree (uncommitted changes are lost)
With --soft, the snapshot that was committed is still in the index, and the index no longer matches the branch tip, which is exactly the definition of "staged changes". Running git status right after shows every file from the undone commit under "Changes to be committed".
Why the other options fail
git reset HEAD~1 uses the default --mixed mode: the commit is undone, but the index is reset to the parent commit too, so the changes survive only as unstaged modifications in the working tree. You would need to git add them again.
git revert HEAD does not remove the commit. It creates a new commit that applies the inverse of HEAD, which is the right tool for undoing a commit that is already pushed to a shared branch, but it is not "undo and keep staged".
git undo is not a Git command.
One habit worth keeping
A reset rewrites the branch pointer, so reserve git reset variants for commits that have not been pushed. For anything already shared, prefer git revert. And if a reset goes wrong, git reflog still holds the previous tip, so a git reset --hard back to the reflog entry can bring the commit back.
Share this quiz
Comments
No comments yet. Be the first.