How to undo anything in Git
January 18, 2025 ยท View on GitHub
Posting this as a reference for my future self, so I don't have to search every time.
Update: Wrote ugit to undo you last git command
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 git commit
# undo last commit (unstage everything)
$ git reset HEAD~
# undo last commit (don't unstage everything)
$ git reset --soft HEAD^
Undo most recent commit message
$ git commit --amend
# or
$ git commit --amend -m "Fixes bug #42"
git commit --amend will 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.
Undo git merge
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 1 option 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
Undo git push
$ git revert HEAD~
Undo git add
$ git restore --staged index.html
Undo most recent git checkout
$ git checkout -
Undo git pull
- Get SHA1 of state before pull using
git reflog - Reset state using
# WARNING: Uncommited changes will be lost git reset --hard <SHA1>
Optionally you can go back in time using git reset --hard master@{"5 minutes ago"}
Undo accidental git branch -D delete
- Use
git reflogto get the commit SHA before you deleted the branchgit reflog - Now if the change isn't pushed to remote, run
Otherwise recreate the branchgit checkout -b branch_name <SHA1>git branch <branchName> <SHA1>
Stop a file from being tracked
When you committed the file previously but now realise it shouldn't have been
git rm --cached application.log
Most recent git reset
- Get last good state using
git reflog - Use
git resetto reset :)git reset <COMMIT_HASH>
Most recent git stash pop/drop/clear
- Find the lost stash,
git fsck --no-progress --unreachable | grep commit | cut -d ' ' -f3 | xargs git log --oneline --merges --no-walk - Update the stash refs:
git update-ref refs/stash "$LOST_STASH_COMMIT" --create-reflog -m "my recovered stash"
Most recent git stash apply
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
Undo accidental git tag delete
Only works for annotated tags, tags created using
git tag -a
- Use
git fsckto check for dangling/unreachable commits.git fsck --unreachable | grep tag - Verify that its the correct tag:
git cat-file -p "COMMIT_HASH" - Update tag refs:
git update-ref refs/tags/"TAG_NAME" --create-reflog "COMMIT_HASH" - Tag is now restored, run
git tag -lto verify
Undo/Restore a file to a previous version
-
Get the commit you want to restore the file to
git log --oneline <FILE> -
Use
git restoreto restore the file :)git restore --source=<COMMIT> <FILE>
Undo accidental file delete
When you have not committed the changes yet
git checkout HEAD <file-path>
When committed the file delete
- Choose commit that deleted the file
git log --diff-filter=D --oneline - Checkout the file
git checkout <COMMIT>~1 -- <FILE>
Undo a git merge ๐๏ธ
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
Reference ORIG_HEAD points to the original commit before the merge. So we are just resetting that
When you pushed the merge commit
- Switch to your main/default branch
git checkout main - Get the merge commit from git log
git log --oneline - Revert that merge commit
git revert -m 1 <COMMIT>
Also must read: How to revert a faulty merge
Undo all current uncommitted changes
Storing everything in stash
# -a is for adding untracked changes
git stash save -au "custom message"