An open API service indexing awesome lists of open source software.

https://github.com/amberpixels/git-undo

Ctrl+Z for Git.
https://github.com/amberpixels/git-undo

git git-plugin golang undo zsh

Last synced: 8 months ago
JSON representation

Ctrl+Z for Git.

Awesome Lists containing this project

README

          

# *git undo* 🥐 — Ctrl+Z as Git plugin 💫


Logo

## 1. `git undo`: one simple command to undo (almost) any Git operation:

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

## 2. `git back`: undo navigation commands e.g. `git checkout/switch`:

```bash
# Assume we're on main
git switch feature-branch
git back # back to main
git back # back to feature-branch
```

## 3. `git undo undo` Undoed accidently? Undo it as well. (like Ctrl+Shift+Z)

```bash
git add .
git commit -m "oops, wrong files"
git undo # Back to before commit, files still staged
git undo undo # Back to commited again
```

## 4. `git undo --dry-run`: see what would be undone:

```bash
# 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"
```

## 5. Debug options: `git undo --verbose`, `git undo --log`

Now you can use Git confidently, knowing any command is easily undoable.

## Installation Options

### One-liner (Recommended)
```bash
curl -fsSL https://raw.githubusercontent.com/amberpixels/git-undo/main/install.sh | bash
```
### Manual Installation (useful for development, debugging, troubleshooting)
```bash
git clone https://github.com/amberpixels/git-undo.git
cd git-undo
./install.sh
```

**Requirements:** Git, Go ≥ 1.21, Bash/Zsh

## Suggestions for aliases

```bash
alias gu="git undo"
alias gub="git back"
alias guu="git undo undo"
alias gul="git undo --log | head"
```

## Supported commands to be undo-ed:

| Git Command | How it's undone | Notes |
|-------------|-----------------|-------|
| **`git add`** | `git restore --staged ` or `git reset ` | 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 `** | `git branch -D ` | Deletes the created branch |
| **`git checkout -b `** | `git branch -D ` | Deletes branch created by checkout -b |
| **`git switch -c `** | `git branch -D ` | Deletes branch created by switch -c |
| **`git switch `** | `git switch -` | Returns to previous branch |
| **`git merge `** | `git reset --merge ORIG_HEAD` | Handles both fast-forward and merge commits |
| **`git cherry-pick `** | `git reset --hard HEAD~1` | Removes cherry-picked commit |
| **`git revert `** | `git reset --hard HEAD~1` | Removes revert commit |
| **`git reset`** | `git reset ` | Restores to previous HEAD position using reflog |
| **`git stash` / `git stash push`** | `git stash pop` | Pops and removes the stash |
| **`git rm `** | `git restore --source=HEAD --staged --worktree ` | Restores removed files |
| **`git rm --cached `** | `git add ` | Re-adds files to index |
| **`git mv `** | `git mv ` | Reverses the move operation |
| **`git tag `** | `git tag -d ` | Deletes the created tag |
| **`git restore --staged `** | `git add ` | Re-stages the files |

### Not Yet Supported (Returns helpful error message):

| Git Command | Reason |
|-------------|--------|
| **`git checkout `** | 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=`** | 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) |

## How It Works

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.

## Examples

**Undo a merge:**
```bash
git merge feature-branch
git undo # resets --merge ORIG_HEAD
```

**Undo adding specific files:**
```bash
git add file1.js file2.js
git undo # unstages just those files
```

**Undo branch creation:**
```bash
git checkout -b new-feature
git undo # deletes branch, returns to previous
```

### Self-Management

Get the version information:
```bash
git undo self version # same as git undo version
```

Update to latest version:
```bash
git undo self update
```

Uninstall:
```bash
git undo self uninstall
```

## Contributing

Found a Git command that should be undoable? [Open an issue](https://github.com/amberpixels/git-undo/issues) or submit a PR!

## License

MIT - see [LICENSE](LICENSE) file.

---

**Make Git worry-free!**
[⭐ Star this repo](https://github.com/amberpixels/git-undo) if `git undo` makes your development workflow better!