gitbutler
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 trackingbut 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 commitM,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 mappingsreferences/tutorial.md- Comprehensive step-by-step workflowsreferences/hooks.md- Claude Code hooks setup guide