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-branch
git 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 | bash
git clone https://github.com/amberpixels/git-undo.git
cd git-undo
./install.sh
Requirements: 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_HEAD
Undo adding specific files:
git add file1.js file2.js
git undo # unstages just those files
Undo branch creation:
git checkout -b new-feature
git undo # deletes branch, returns to previous
Get the version information:
git undo self version # same as git undo version
Update to latest version:
git undo self update
Uninstall:
git undo self uninstall
Found 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!