GitButler CLI Guide
GitButler (but) is a modern Git client that makes history manipulation safe and reversible.
[IMPORTANT] Detect GitButler Workspace
Before running any git commands, check if GitButler is active:
git branch --show-current
If the result is gitbutler/workspace:
- •[PREFER]
butcommands when equivalent exists (commit, squash, undo, amend) - •[OK] Native git for operations
butdoesn't cover (cherry-pick, stash, tag, revert, blame) - •[CAUTION] Some git commands can corrupt virtual branch state (see below)
Git Command Guidelines:
Prefer but | Use git freely | Use git with caution |
|---|---|---|
but commit over git commit | git cherry-pick | git reset --hard |
but rub over git rebase -i | git stash | git push --force |
but undo over git reset | git tag | git rebase |
but absorb for amending | git revert | git clean |
but reword for messages | git blame, git bisect | git checkout <file> |
Why prefer but when available? GitButler manages virtual branches through its workspace:
- •
butcommands maintain virtual branch tracking - •
but undoand oplog provide safer recovery - •Some raw git commands can corrupt the virtual branch state
Quick detection pattern:
# At start of git-related tasks, check:
if [[ $(git branch --show-current) == "gitbutler/workspace" ]]; then
# Use 'but' commands instead of 'git'
fi
Key Advantages Over Git
| Feature | Git | GitButler |
|---|---|---|
| Undo operations | Complex reflog | but undo |
| Time travel | Risky reset | but restore <sha> |
| Squash commits | rebase -i + editor | but rub <src> <target> |
| Fix old commit | stash → rebase → amend | but absorb |
| Multiple features | Switch branches constantly | Virtual branches (simultaneous) |
Essential Commands
Inspection (Always Start Here!)
but status # View workspace state (branches, commits, changes) but oplog # View operation history (time-travel checkpoints)
Status output explained:
╭┄00 [Unassigned Changes] ┊ g0 M calculator.py [LOCKED] 8ebedce ← File ID, status, dependency ┊ ┊╭┄al [calculator-feature] ← Branch ID ┊● abc1234 Commit message ← Commit ├╯ ┊ ┴ 6e7da9e (common base) [origin/main]
- •
g0,h0: File/change IDs (use withbut rub) - •
al,ut: Branch IDs - •
[LOCKED] <sha>: GitButler detected this change belongs to that commit - •
M,A,D: Modified, Added, Deleted
The rub Multi-Tool
The rub command performs different operations based on source/target types:
| Source | Target | Operation | Example |
|---|---|---|---|
| File | Branch | Assign | but rub g0 al |
| File | Commit | Amend | but rub g0 abc123 |
| Commit | Commit | Squash | but rub abc123 def456 |
| Commit | Branch | Move | but rub abc123 ut |
Squash workflow:
but status # Get current SHAs but rub <source-sha> <target-sha> # Squash source INTO target but reword <new-sha> -m "Combined message" # Update message
Smart Amending with absorb
When you modify code, GitButler detects which commit introduced those lines:
# Edit a file, then check status but status # Shows: g0 M file.py [LOCKED] abc123 ← Detected dependency! # Auto-amend to the correct commit but absorb
GitButler automatically:
- •Analyzes which lines changed
- •Finds the commit that introduced them
- •Amends the change into that commit
- •Rebases all dependent commits
Commit Editing
but reword <sha> -m "new message" # Edit commit message (auto-rebases) but absorb # Auto-amend changes to correct commits but absorb <file-id> # Absorb specific file only
Undo & Recovery (Time Travel)
but undo # Undo last operation (one step back) but oplog snapshot -m "checkpoint" # Create named checkpoint but restore <sha> --force # Restore to any oplog snapshot
The oplog is your time machine:
but oplog # See all operations # Output: # 7f8e652 [SQUASH] SquashCommit # abc1234 [CREATE] CreateCommit # def5678 [MOVE_HUNK] MoveHunk but restore 7f8e652 --force # Go back to that point
Even undos are tracked! You can undo an undo.
Virtual Branches (Work on Multiple Features)
Create and manage branches:
but branch new <name> # Create virtual branch but branch list # List all branches but branch unapply <id> # Hide branch temporarily but branch apply <id> # Show branch again
Work on multiple features simultaneously:
# Edit files for different features vim feature-a.py vim feature-b.py # Check status - assign to different branches but status # g0 M feature-a.py # h0 M feature-b.py but rub g0 al # Assign to branch 'al' but rub h0 ut # Assign to branch 'ut' # Commit to each branch but commit al -m "Feature A" --only but commit ut -m "Feature B" --only
No context switching! Both branches are active simultaneously.
Committing
but commit <branch> -m "message" # Commit ALL uncommitted changes but commit <branch> -m "message" --only # Commit ONLY assigned changes but commit -c -m "message" # Create new branch and commit
[CAUTION] Important: Without --only, but commit includes ALL uncommitted changes!
Quick Reference: Git → But
| Git Command | But Command |
|---|---|
git status | but status |
git reflog | but oplog |
git checkout -b | but branch new |
git add | but rub <file> <branch> |
git commit | but commit <branch> -m |
git commit --amend | but rub <file> <commit> or but absorb |
git rebase -i (squash) | but rub <commit> <commit> |
git rebase -i (reword) | but reword <sha> -m |
git reset --hard | but restore <sha> --force |
| N/A | but undo |
| N/A | but oplog snapshot |
| N/A | but absorb |
Common Workflows
Fix typo in old commit message
but status # Find the commit SHA but reword <sha> -m "Fixed message"
Squash multiple commits
but status # Get SHAs but rub <source> <target> # Squash but reword <new-sha> -m "Combined" # Update message
Amend change to old commit
# Edit the file, then: but status # Check for [LOCKED] dependency but absorb # Auto-amend
Recover from mistake
but undo # Quick: undo last operation # OR but oplog # Find the right snapshot but restore <sha> --force # Go back in time
Error Handling
Common Errors and Recovery
| Error | Cause | Recovery |
|---|---|---|
but status fails | GitButler not initialized | Run but to initialize, or check .git/gitbutler directory |
| "Branch not found" | Virtual branch deleted/renamed | Run but status to list available branches |
| "Conflict detected" | Merge conflict during operation | Resolve conflicts in files, then but commit |
| "Uncommitted changes" | Operation blocked by dirty state | Commit or stash changes first |
| Command hangs | Large repo or network issue | Wait, or Ctrl+C and retry |
Recovery Commands
but undo # Undo last operation (safe, always works) but oplog # View all operations for recovery points but restore <sha> --force # Restore to any previous state but oplog snapshot list # List named checkpoints
When to Use undo vs restore
- •
but undo: Quick single-step rollback. Use when the last operation went wrong. - •
but restore: Time-travel to any point. Use when you need to go back multiple operations or to a named checkpoint.
[INFO] The oplog tracks everything, including undos. You can always recover!
Claude Code Hooks Integration
GitButler integrates with Claude Code through hooks (but claude pre-tool, but claude post-tool, but claude stop) that automatically manage commits during AI-assisted development sessions.
Key benefits:
- •Auto-assigns changes to appropriate branches
- •Generates commit messages from user prompts
- •Eliminates manual
but commitduring sessions
For detailed configuration and setup instructions, see references/hooks.md.
Reference Files
For detailed documentation, see:
- •
references/cheatsheet.md- Quick command reference with git → but mappings - •
references/tutorial.md- Comprehensive step-by-step workflows - •
references/hooks.md- Claude Code hooks setup guide