Every time I accidentally git commit --amend
instead of a normal git commit I have to google git reset --soft HEAD@{1}
to save the day.
Imagine you have a file called foo.txt
and your Git history looked like this:
A -> B -> C (HEAD)
Let's see each commit we made:
A == foo
B == FOO
C == Foo
The following examples explain the different reset flags:
git reset --soft B == move HEAD to B but keep C's changes staged (i.e. added to the index)
git reset --mixed B == move HEAD to B but keep C's changes unstaged (--mixed is the DEFAULT)
git reset --hard B == move HEAD to B but completely delete C (you've lost those changes forever)
NOTE: If you accidentally
git commit --amend
theHEAD
, then you can undo that usinggit reset --soft HEAD@{1}
. The--soft
means the changes you made are kept staged (ready for an actualgit commit
) while theHEAD@{1}
means setHEAD
to what it was before the accidental--amend
. This meansHEAD@{1}
is NOT the same thing asHEAD~1
, which gives you the commit that is the parent node of the commit thatHEAD
is currently pointing to. The referenceHEAD@{1}
is actually able to get back what we want because what it references is actually sourced fromgit reflog
, which if you rungit reflog
you'll see the output shows an index for each recorded change.
If you want to clean up a PRs commits, then run:
git reset origin/main
Then your changes will still exist, but will just be unstaged (as --mixed is the default behaviour). You can now git add --patch
cleanly.