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 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

  1. 1.
    Get SHA1 of state before pull using git reflog
  2. 2.
    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

  1. 1.
    Use git reflog to get the commit SHA before you deleted the branch
    git reflog
  2. 2.
    Now if the change isn't pushed to remote, run
    git checkout -b branch_name <SHA1>
    Otherwise recreate the branch
    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

  1. 1.
    Get last good state using git reflog
  2. 2.
    Use git reset to reset :)
    git reset <COMMIT_HASH>

Most recent git stash pop/drop/clear

  1. 1.
    Find the lost stash,
    git fsck --no-progress --unreachable | grep commit | cut -d ' ' -f3 | xargs git log --oneline --merges --no-walk
  2. 2.
    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 .gitconfig otherwise 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
  1. 1.
    Use git fsck to check for dangling/unreachable commits.
    git fsck --unreachable | grep tag
  2. 2.
    Verify that its the correct tag:
    git cat-file -p "COMMIT_HASH"
  3. 3.
    Update tag refs:
    git update-ref refs/tags/"TAG_NAME" --create-reflog "COMMIT_HASH"
  4. 4.
    Tag is now restored, run git tag -l to verify

Undo/Restore a file to a previous version

  1. 1.
    Get the commit you want to restore the file to
    git log --oneline <FILE>
  2. 2.
    Use git restore to 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
  1. 1.
    Choose commit that deleted the file
    git log --diff-filter=D --oneline
  2. 2.
    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
  1. 1.
    Switch to your main/default branch
    git checkout main
  2. 2.
    Get the merge commit from git log
    git log --oneline
  3. 3.
    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"