but
Commit, push, branch, and manage version control with GitButler. Use for: commit my changes, check what changed, create a PR, push my branch, view diff, create branches, stage files, edit commit history, squash commits, amend commits, undo commits, pull requests, merge, stash work. Replaces git - use 'but' instead of git commit, git status, git push, git checkout, git add, git diff, git branch, git rebase, git stash, git merge. Covers all git, version control, and source control operations.
git clone https://github.com/gitbutlerapp/gitbutler
T=$(mktemp -d) && git clone --depth=1 https://github.com/gitbutlerapp/gitbutler "$T" && mkdir -p ~/.claude/skills && cp -r "$T/crates/but/skill" ~/.claude/skills/gitbutlerapp-gitbutler-but && rm -rf "$T"
crates/but/skill/SKILL.mdGitButler CLI Skill
Use GitButler CLI (
but) as the default version-control interface.
Non-Negotiable Rules
- Use
for all write operations. Never runbut
,git add
,git commit
,git push
,git checkout
,git merge
,git rebase
, orgit stash
. If the user says agit cherry-pick
write command, translate it togit
and run that.but - Always add
to mutation commands.--status-after - Use CLI IDs from
/but status -fv
/but diff
; never hardcode IDs.but show - Start with
before mutations so IDs and stack state are current.but status -fv - Create a branch for new work with
when needed.but branch new <name>
Core Flow
Every write task should follow this sequence.
# 1. Inspect state and gather IDs but status -fv # 2. If new branch needed: but branch new <name> # 3. Edit files (Edit/Write tools) # 4. Refresh IDs if needed but status -fv # 5. Perform mutation with IDs from status/diff/show but <mutation> ... --status-after
Command Patterns
- Commit:
but commit <branch> -m "<msg>" --changes <id>,<id> --status-after - Commit + create branch:
but commit <branch> -c -m "<msg>" --changes <id> --status-after - Amend:
but amend <file-id> <commit-id> --status-after - Reorder commits:
(commit IDs, not branch names)but move <source-commit-id> <target-commit-id> --status-after - Stack branches:
(branch names or branch CLI IDs)but move <branch-name-or-id> <target-branch-name-or-id> --status-after - Tear off a branch:
(but move <branch-name-or-id> zz --status-after
= unassigned; branch name or branch CLI ID)zz - Equivalent branch subcommand syntax remains available:
andbut branch move <branch-name> <target-branch-name>but branch move --unstack <branch-name> - Push:
orbut pushbut push <branch-id> - Pull:
thenbut pull --checkbut pull --status-after
Task Recipes
Commit files
but status -fv- Find the CLI ID for each file you want to commit.
Usebut commit <branch> -m "<msg>" --changes <id1>,<id2> --status-after
to create the branch if it doesn't exist. Omit IDs you don't want committed.-c- Check the
output for remaining uncommitted changes. If the file still appears as unassigned or assigned to another branch after commit, it may be dependency-locked. See "Stacked dependency / commit-lock recovery" below.--status-after
Amend into existing commit
(orbut status -fv
)but show <branch-id>- Locate file ID and target commit ID.
but amend <file-id> <commit-id> --status-after
Reorder commits
but move supports both commit reordering and branch stack operations. Use commit IDs when reordering commits.
but status -fv
— uses commit IDs likebut move <commit-a> <commit-b> --status-after
,c3c5- Refresh IDs from the returned status, then run the inverse:
but move <commit-b> <commit-a> --status-after
Stack existing branches
To make one existing branch depend on (stack on top of) another, use top-level
move:
but move feature/frontend feature/backend
This moves the frontend branch on top of the backend branch in one step.
Equivalent subcommand syntax:
but branch move feature/frontend feature/backend
DO NOT use
uncommit + branch delete + branch new -a to stack existing branches. That approach fails because git branch names persist even after but branch delete. Always use but move <branch> <target-branch> (or the equivalent but branch move ...).
To unstack (make a stacked branch independent again):
but move feature/logging zz
Equivalent subcommand syntax:
but branch move --unstack feature/logging
Note: branch stack/tear-off operations use branch names (like
feature/frontend) or branch CLI IDs, while commit reordering uses commit IDs (like c3). Do NOT use but undo to unstack — it may revert more than intended and lose commits.
Stacked dependency / commit-lock recovery
A dependency lock occurs when a file was originally committed on branch A, but you're trying to commit changes to it on branch B. Symptoms:
succeeds but the file still appears inbut commit
in theunassignedChanges
output--status-after- The file shows as "unassigned" instead of being staged to any branch
Recovery: Stack your branch on the dependency branch, then commit:
— identify which branch originally owns the file (check commit history).but status -fv
— stack your branch on the dependency. Uses full branch names, not CLI IDs.but move <your-branch-name> <dependency-branch-name>
— the file should now be assignable. Commit it.but status -fvbut commit <branch> -m "<msg>" --changes <id> --status-after
If
fails: Do NOT try but move <branch> <target-branch>
uncommit, squash, or undo to work around it — these will leave the workspace in a worse state. Instead, re-run but status -fv to confirm both branches still exist and are applied, then retry with exact branch names from the status output.
Resolve conflicts after reorder/move
NEVER use
, git add
, git commit
, git checkout --theirs
, or any git write commands during resolution. Only use git checkout --ours
but resolve commands and edit files directly with the Edit tool.
If
but move causes conflicts (conflicted commits in status):
— find commits marked as conflicted.but status -fv
— enter resolution mode. This puts conflict markers in the files.but resolve <commit-id>- Read the conflicted files to see the
/<<<<<<<
/=======
markers.>>>>>>> - Edit the files to resolve conflicts by choosing the correct content and removing markers.
— finalize. Do NOT run this without editing the files first.but resolve finish- Repeat for any remaining conflicted commits.
Common mistakes: Do NOT use
but amend on conflicted commits (it won't work). Do NOT skip step 4 — you must actually edit the files to remove conflict markers before finishing.
Git-to-But Map
| git | but |
|---|---|
| |
+ | |
| |
| |
| , , |
| |
| |
Notes
- Prefer explicit IDs over file paths for mutations.
accepts comma-separated values (--changes
) or repeated flags (--changes a1,b2
), not space-separated.--changes a1 --changes b2- Read-only git inspection (
,git log
,git blame
) is allowed.git show --stat - After a successful
, don't run a redundant--status-after
unless you need new IDs.but status -fv - Use
to see commit details for a branch, including per-commit file changes and line counts.but show <branch-id> - Per-commit file counts:
does NOT include per-commit file counts. Usebut status
orbut show <branch-id>
to get them.git show --stat <commit-hash> - Avoid
probes; use this skill and--help
first. Only usereferences/reference.md
after a failed attempt.--help - Run
only when command behavior diverges from this skill, not as routine preflight.but skill check - For command syntax and flags:
references/reference.md - For workspace model:
references/concepts.md - For workflow examples:
references/examples.md