How to undo anything in Git
Posted on 03 Apr, 2021
Posting this as a reference for my future self, so I don't have to search every time.
If the reader has a better way to undo something, please edit the page and send a PR. More than happy to correct myself.
# undo last commit (unstage everything)
$ git reset HEAD~
# undo last commit (don't unstage everything)
$ git reset --soft HEAD^
$ git commit --amend
$ git commit --amend -m "Fixes bug #42"
git commit --amendwill update and replace the most recent commit with a new commit that combines any staged changes with the contents of the previous commit. With nothing currently staged, this just rewrites the previous commit message.
Not yet pushed to remote
$ git reset --hard <commit-before-merge>
# assuming the merge was your most recent commit
$ git reset HEAD~
When you have already PUSHed the merge to remote
git revert -m 1 <merge-commit-hash>
git revert will make sure that a new commit is created to revert the effects of that unwanted merge. The
-m 1option tells Git that we want to keep the parent side of the merge (which is the branch we had merged into). Finally, also make sure to provide the correct commit hash: when using git revert, we have to specify the actual merge commit's hash.
Now, when you have fixed changes in your branch you would have to revert the revert before merging again. Read How to revert a faulty merge
$ git checkout feature
# commits to fix the bug.
$ git checkout master
$ git revert e443799
$ git merge feature
# Fix any merge conflicts introduced by the bug fix
$ git commit # commit the merge
$ git push
$ git revert HEAD~
$ git restore --staged index.html
$ git checkout -
- 1.Get SHA1 of state before pull using
- 2.Reset state using# WARNING: Uncommited changes will be lostgit reset --hard <SHA1>
git reflogto get the commit SHA before you deleted the branchgit reflog
- 2.Now if the change isn't pushed to remote, rungit checkout -b branch_name <SHA1>Otherwise recreate the branchgit branch <branchName> <SHA1>
When you committed the file previously but now realise it shouldn't have been
git rm --cached application.log
- 1.Get last good state using
git resetto reset :)git reset <COMMIT_HASH>
- 1.Find the lost stash,git fsck --no-progress --unreachable | grep commit | cut -d ' ' -f3 | xargs git log --oneline --merges --no-walk
- 2.Update the stash refs:git update-ref refs/stash "$LOST_STASH_COMMIT" --create-reflog -m "my recovered stash"
Make sure that diff coloring is set to auto in your
.gitconfigotherwise the command will fail with unrecognised input.
git stash show -p | git apply --reverse
Only works for annotated tags, tags created using
git tag -a
git fsckto check for dangling/unreachable commits.git fsck --unreachable | grep tag
- 2.Verify that its the correct tag:git cat-file -p "COMMIT_HASH"
- 3.Update tag refs:git update-ref refs/tags/"TAG_NAME" --create-reflog "COMMIT_HASH"
- 4.Tag is now restored, run
git tag -lto verify
- 1.Get the commit you want to restore the file togit log --oneline <FILE>
git restoreto restore the file :)git restore --source=<COMMIT> <FILE>
When you have not committed the changes yet
git checkout HEAD <file-path>
When committed the file delete
- 1.Choose commit that deleted the filegit log --diff-filter=D --oneline
- 2.Checkout the filegit checkout <COMMIT>~1 -- <FILE>
Undoing a git merge is a risky business. Please proceed with caution
When the merge has conflicts, and you want to give up
git merge --abort
When the merge is unpushed
git reset --merge ORIG_HEAD
ORIG_HEADpoints to the original commit before the merge. So we are just resetting that
When you pushed the merge commit
- 1.Switch to your main/default branchgit checkout main
- 2.Get the merge commit from git loggit log --oneline
- 3.Revert that merge commitgit revert -m 1 <COMMIT>
Storing everything in stash
# -a is for adding untracked changes
git stash save -au "custom message"