git add . git commit -m "oops, wrong files" git undo # Back to before commit, files still staged git undo # Back to before add, clean working directory# Assume we're on main git switch feature-branch git back # back to main git back # back to feature-branchgit add . git commit -m "oops, wrong files" git undo # Back to before commit, files still staged git undo undo # Back to commited again# Make some changes git add file.txt git undo --dry-run # shows hint to run "git restore --staged ." git commit -m "test commit" git undo --dry-run # shows hint to run "git reset --soft HEAD~1"Now you can use Git confidently, knowing any command is easily undoable.
curl -fsSL https://raw.githubusercontent.com/amberpixels/git-undo/main/install.sh | bashgit clone https://github.com/amberpixels/git-undo.git cd git-undo ./install.shRequirements: Git, Go ≥ 1.21, Bash/Zsh
alias gu="git undo"alias gub="git back"alias guu="git undo undo"alias gul="git undo --log | head"| Git Command | How it's undone | Notes |
|---|---|---|
git add | git restore --staged <files> or git reset <files> | Unstages files. Uses git reset if no HEAD exists |
git commit | git reset --soft HEAD~1 | Keeps changes staged. Handles merge commits and tagged commits |
git branch <name> | git branch -D <name> | Deletes the created branch |
git checkout -b <name> | git branch -D <name> | Deletes branch created by checkout -b |
git switch -c <name> | git branch -D <name> | Deletes branch created by switch -c |
git switch <branch> | git switch - | Returns to previous branch |
git merge <branch> | git reset --merge ORIG_HEAD | Handles both fast-forward and merge commits |
git cherry-pick <commit> | git reset --hard HEAD~1 | Removes cherry-picked commit |
git revert <commit> | git reset --hard HEAD~1 | Removes revert commit |
git reset | git reset <previous-head> | Restores to previous HEAD position using reflog |
git stash / git stash push | git stash pop | Pops and removes the stash |
git rm <files> | git restore --source=HEAD --staged --worktree <files> | Restores removed files |
git rm --cached <files> | git add <files> | Re-adds files to index |
git mv <old> <new> | git mv <new> <old> | Reverses the move operation |
git tag <name> | git tag -d <name> | Deletes the created tag |
git restore --staged <files> | git add <files> | Re-stages the files |
| Git Command | Reason |
|---|---|
git checkout <branch> | Only checkout -b is supported (regular checkout navigation not undoable) |
git clean | Cannot recover deleted untracked files (would need pre-operation backup) |
git restore --worktree | Previous working tree state unknown |
git restore --source=<ref> | Previous state from specific reference unknown |
git stash pop/apply | Would need to re-stash, which is complex |
| Branch/tag deletion | Cannot restore deleted branches/tags (would need backup) |
After installation both shell hooks and git hooks are installed, that track any git command and send them to git-undo (a git plugin) binary. There git commands are categorized and stored in a tiny log file (.git/git-undo/commands). Later, when calling git undo it reads the log and decide if it's possible (and how) to undo previous command.
Undo a merge:
git merge feature-branch git undo # resets --merge ORIG_HEADUndo adding specific files:
git add file1.js file2.js git undo # unstages just those filesUndo branch creation:
git checkout -b new-feature git undo # deletes branch, returns to previousGet the version information:
git undo self version # same as git undo versionUpdate to latest version:
git undo self updateUninstall:
git undo self uninstallFound a Git command that should be undoable? Open an issue or submit a PR!
MIT - see LICENSE file.
Make Git worry-free!⭐ Star this repo if git undo makes your development workflow better!