Back to skills
SkillHub ClubShip Full StackFull Stack

complete-branch

This skill should be used when completing branches, merging to main, creating PRs with GitButler, or when `--complete-branch` flag is mentioned.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
25
Hot score
88
Updated
March 20, 2026
Overall rating
C2.8
Composite score
2.8
Best-practice grade
N/A

Install command

npx @skill-hub/cli install outfitter-dev-agents-complete-branch
gitversion-controlbranchingworkflowautomation

Repository

outfitter-dev/agents

Skill path: gitbutler/skills/complete-branch

This skill should be used when completing branches, merging to main, creating PRs with GitButler, or when `--complete-branch` flag is mentioned.

Open repository

Best for

Primary workflow: Ship Full Stack.

Technical facets: Full Stack.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: outfitter-dev.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install complete-branch into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/outfitter-dev/agents before adding complete-branch to shared team environments
  • Use complete-branch for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: complete-branch
version: 2.0.0
description: This skill should be used when completing branches, merging to main, creating PRs with GitButler, or when `--complete-branch` flag is mentioned.
---

# Complete GitButler Virtual Branch

Virtual branch ready → snapshot → merge to main → cleanup → return.

<when_to_use>

- Virtual branch work is complete and ready to ship
- Tests pass and code is reviewed (if required)
- Ready to merge changes into main branch
- Need to clean up completed branches

NOT for: ongoing work, branches needing more development, stacks (complete bottom-to-top)

</when_to_use>

<prerequisites>

**Before completing any branch:**
- [ ] GitButler initialized (`but --version` succeeds)
- [ ] Virtual branch exists with committed changes
- [ ] Main branch tracked as base
- [ ] No uncommitted changes (or changes assigned to branches)
- [ ] Tests passing

</prerequisites>

<quick_start>

## Quick Start (7 Steps)

```bash
# 1. Verify branch state
but status
but log

# 2. Create safety snapshot
but snapshot --message "Before integrating feature-auth"

# 3. Switch to main
git checkout main

# 4. Update main from remote
git pull origin main

# 5. Merge virtual branch
git merge --no-ff refs/gitbutler/feature-auth -m "feat: add user authentication"

# 6. Push to remote
git push origin main

# 7. Clean up and return
but branch rm feature-auth
git checkout gitbutler/workspace
```

</quick_start>

<pre_flight>

## Pre-Integration Checklist

```bash
# All work committed?
but status  # Your branch should show committed changes

# Tests passing?
bun test  # or npm test, cargo test, etc.

# Branch up to date with main?
but base update

# No uncommitted changes?
but status  # Should show no unassigned files
git status  # Should be clean or show only .gitbutler/ changes

# Safety snapshot created?
but snapshot --message "Before integrating feature-auth"
```

</pre_flight>

<workflows>

## Integration Workflows

### A. Direct Merge to Main

```bash
# 1. Verify branch state
but status
but log

# 2. Create snapshot
but snapshot --message "Before integrating feature-auth"

# 3. Switch to main
git checkout main

# 4. Update main
git pull origin main

# 5. Merge with --no-ff (preserves history)
git merge --no-ff refs/gitbutler/feature-auth -m "feat: add user authentication"

# 6. Push
git push origin main

# 7. Clean up
but branch rm feature-auth
git checkout gitbutler/workspace
```

### B. Pull Request Workflow

```bash
# 1. Push branch to remote
git push origin refs/gitbutler/feature-auth:refs/heads/feature-auth

# 2. Create PR
gh pr create --base main --head feature-auth \
  --title "feat: add user authentication" \
  --body "Description..."

# 3. Wait for review and approval

# 4. Merge PR (via GitHub UI or CLI)
gh pr merge feature-auth --squash

# 5. Update main and clean up
git checkout main
git pull origin main
but branch rm feature-auth
git checkout gitbutler/workspace
```

### C. Stacked Branches (Bottom-Up)

```bash
# Must merge in order: base → dependent → final

# 1. Merge base branch first
git checkout main && git pull
git merge --no-ff refs/gitbutler/feature-base -m "feat: base feature"
git push origin main
but branch rm feature-base
git checkout gitbutler/workspace

# 2. Update remaining branches
but base update

# 3. Merge next level
git checkout main && git pull
git merge --no-ff refs/gitbutler/feature-api -m "feat: API feature"
git push origin main
but branch rm feature-api
git checkout gitbutler/workspace

# 4. Repeat for remaining stack levels
```

</workflows>

<recovery>

## Error Recovery

### Merge Conflicts

```bash
# View conflicted files
git status

# Resolve conflicts manually

# Stage resolved files
git add src/auth.ts

# Complete merge
git commit

# Verify and push
git push origin main

# Clean up
but branch rm feature-auth
git checkout gitbutler/workspace
```

### Push Rejected (Main Moved Ahead)

```bash
git pull origin main
# Resolve any conflicts if main diverged
git push origin main
```

### Undo Integration (Not Pushed Yet)

```bash
git reset --hard HEAD~1
git checkout gitbutler/workspace
```

### Undo Integration (Already Pushed)

```bash
git revert -m 1 HEAD
git push origin main
```

</recovery>

<cleanup>

## Post-Integration Cleanup

```bash
# Delete integrated virtual branch
but branch rm feature-auth

# Clean up remote branch (if created for PR)
git push origin --delete feature-auth

# Verify workspace is clean
but status  # Should show remaining active branches only
but log     # Branch should be gone
```

</cleanup>

<rules>

ALWAYS:
- Create snapshot before integration: `but snapshot --message "..."`
- Use `--no-ff` flag to preserve branch history
- Return to workspace after git operations: `git checkout gitbutler/workspace`
- Run tests before integrating
- Complete stacked branches bottom-to-top

NEVER:
- Merge without snapshot backup
- Skip updating main first (`git pull`)
- Forget to return to `gitbutler/workspace`
- Merge middle of stack before base
- Force push to main without explicit confirmation

</rules>

<troubleshooting>

## Common Issues

| Symptom | Cause | Solution |
|---------|-------|----------|
| Merge conflicts | Diverged from main | Resolve conflicts, stage, commit |
| Push rejected | Main moved ahead | `git pull`, resolve, push |
| Branch not found | Wrong ref path | Use `refs/gitbutler/<name>` |
| Can't return to workspace | Integration branch issue | `git checkout gitbutler/workspace` |

## Emergency Recovery

```bash
# If integration went wrong
but oplog
but undo  # Restores pre-integration state

# If stuck after git operations
git checkout gitbutler/workspace
```

</troubleshooting>

<best_practices>

## Best Practices

**Keep branches small:**
- Small branches = easier merges
- Aim for single responsibility per branch

**Update base regularly:**

```bash
but base update
```

**Test before integrating:**
- Always run full test suite before merging

**Meaningful merge commits:**

```bash
# Good: Describes what and why
git merge --no-ff feature-auth -m "feat: add JWT-based user authentication"

# Bad: Generic message
git merge --no-ff feature-auth -m "Merge branch"
```

</best_practices>

<references>

- [version-control skill](../version-control/SKILL.md) — core GitButler workflows
- [stack-workflows skill](../stack-workflows/SKILL.md) — stacked branches
- [REFERENCE.md](../version-control/REFERENCE.md) — CLI reference and troubleshooting

</references>


---

## Referenced Files

> The following files are referenced in this skill and included for context.

### ../version-control/SKILL.md

```markdown
---
name: version-control
version: 2.0.0
description: This skill should be used when working with GitButler, virtual branches, `but` commands, or when `--gitbutler` or `--but` flags are mentioned.
---

# GitButler Version Control

Virtual branches → parallel development → post-hoc organization.

<when_to_use>

- Multiple unrelated features in same workspace simultaneously
- Multi-agent concurrent development (agents in same repo)
- Exploratory coding where organization comes after writing
- Post-hoc commit reorganization needed
- Visual organization preferred (GUI + CLI)

NOT for: projects using Graphite (incompatible models), simple linear workflows (use plain git), when PR submission automation required end-to-end (use Graphite instead)

</when_to_use>

<core_concepts>

| Concept | Description |
|---------|-------------|
| Virtual branches | Multiple branches applied simultaneously to working directory |
| Integration branch | `gitbutler/workspace` tracks virtual branch state — never touch directly |
| Target branch | Base branch (e.g., `origin/main`) all work diverges from |
| File assignment | Assign file hunks to branches with `but rub` |
| Stacks | Dependent branches via `--anchor` flag |
| Oplog | Operations log for undo/restore — your safety net |

**Key difference from Git**: All branches visible at once. Organize files to branches after editing. No checkout.

</core_concepts>

<workflow>

## Quick Start

```bash
# Initialize (one time)
but init

# Create branch
but branch new feature-auth

# Make changes, check status for file IDs
but status
# ╭┄00 [Unassigned Changes]
# │   m6 A src/auth.ts

# Assign file to branch using ID
but rub m6 feature-auth

# Commit
but commit feature-auth -m "feat: add authentication"
```

## Core Loop

1. **Create**: `but branch new <name>`
2. **Edit**: Make changes in working directory
3. **Check**: `but status` to see file IDs
4. **Assign**: `but rub <file-id> <branch-name>`
5. **Commit**: `but commit <branch> -m "message"`
6. **Repeat**: Continue with other features in parallel

## The Power of `but rub`

Swiss Army knife — combines entities to perform operations:

| Source | Target | Operation |
|--------|--------|-----------|
| File ID | Branch | Assign file to branch |
| File ID | Commit | Amend commit with file |
| Commit SHA | Branch | Move commit between branches |
| Commit SHA | Commit SHA | Squash (newer into older) |

</workflow>

<parallel_development>

## Parallel Feature Development

```bash
# Create two independent features
but branch new feature-a
but branch new feature-b

# Edit files for both (same workspace!)
echo "Feature A" > feature-a.ts
echo "Feature B" > feature-b.ts

# Assign to respective branches
but rub <id-a> feature-a
but rub <id-b> feature-b

# Commit independently
but commit feature-a -m "feat: implement feature A"
but commit feature-b -m "feat: implement feature B"

# Both branches exist, zero conflicts, same directory
```

## Multi-Agent Workflows

Multiple AI agents working concurrently in same repo:

```bash
# Agent 1
but branch new agent-1-feature
# ... make changes ...
but commit agent-1-feature -m "feat: add feature X"

# Agent 2 (simultaneously, same workspace)
but branch new agent-2-bugfix
# ... make changes ...
but commit agent-2-bugfix -m "fix: resolve issue Y"
```

**See [multi-agent skill](../multi-agent/SKILL.md) for advanced patterns**

</parallel_development>

<completion>

## Completing Work

**CRITICAL**: GitButler CLI lacks native commands for merging to main or creating PRs. Use git for integration.

```bash
# 1. Snapshot for safety
but snapshot --message "Before integrating feature-auth"

# 2. Switch to main
git checkout main

# 3. Update main
git pull origin main

# 4. Merge virtual branch
git merge --no-ff refs/gitbutler/feature-auth -m "feat: add auth"

# 5. Push
git push origin main

# 6. Clean up and return
but branch rm feature-auth
git checkout gitbutler/workspace
```

**See [complete-branch skill](../complete-branch/SKILL.md) for full guided workflow**

</completion>

<commands>

## Essential Commands

| Command | Purpose |
|---------|---------|
| `but init` | Initialize GitButler in repository |
| `but status` | View changes and file IDs |
| `but log` | View commits on active branches |
| `but branch new <name>` | Create virtual branch |
| `but branch new <name> --anchor <parent>` | Create stacked branch |
| `but rub <source> <target>` | Assign/move/squash/amend |
| `but commit <branch> -m "msg"` | Commit to branch |
| `but commit <branch> -o -m "msg"` | Commit only assigned files |
| `but publish` | Publish branches to forge (GitHub) |
| `but forge auth` | Authenticate with GitHub |
| `but absorb` | Amend uncommitted changes |
| `but oplog` | Show operation history |
| `but undo` | Undo last operation |
| `but snapshot --message "msg"` | Create manual snapshot |
| `but base update` | Update workspace with latest base |
| `but .` | Open GitButler GUI for current repo |

**Global flags come first**: `but --json status` ✓ | `but status --json` ✗

</commands>

<ai_integration>

## AI Agent Integration

Three integration methods:

**1. Agents Tab** (Claude Code, recommended)
- GUI-based launcher tied to branches
- Automatic commit management per session
- Parallel agent execution with branch isolation

**2. Lifecycle Hooks**

```json
{
  "hooks": {
    "PreToolUse": [{"matcher": "Edit|MultiEdit|Write", "hooks": [{"type": "command", "command": "but claude pre-tool"}]}],
    "PostToolUse": [{"matcher": "Edit|MultiEdit|Write", "hooks": [{"type": "command", "command": "but claude post-tool"}]}],
    "Stop": [{"matcher": "", "hooks": [{"type": "command", "command": "but claude stop"}]}]
  }
}
```

**3. MCP Server**

```bash
but mcp  # Start MCP server for agent integration
```

</ai_integration>

<rules>

ALWAYS:
- Use `but` for all work within virtual branches
- Use `git` only for integrating completed work into main
- Return to `gitbutler/workspace` after git operations: `git checkout gitbutler/workspace`
- Snapshot before risky operations: `but snapshot --message "..."`
- Assign files immediately after creating: `but rub <id> <branch>`
- Check file IDs with `but status` before using `but rub`

NEVER:
- Use `git commit` on virtual branches — breaks GitButler state
- Use `git add` — GitButler manages index
- Use `git checkout` on virtual branches — no checkout needed
- Push `gitbutler/integration` to remote — it's local-only
- Mix Graphite and GitButler in same repo — incompatible models
- Pipe `but status` directly — causes panic; capture output first:

  ```bash
  status_output=$(but status)
  echo "$status_output" | head -5
  ```

</rules>

<troubleshooting>

## Quick Troubleshooting

| Symptom | Cause | Solution |
|---------|-------|----------|
| Branch not showing in `but log` | Not tracked | `but track --parent <parent>` |
| Files not committing | Not assigned | `but rub <file-id> <branch>` |
| Conflicts in workspace | All branches applied | Resolve in files or reassign hunks |
| Mixed git/but broke state | Used git commands | `but base update` or reinit |
| Broken pipe panic | Output consumed partially | Capture output to variable first |
| Filename with dash fails | Interpreted as range | Use file ID from `but status` |
| Lost work | Need recovery | Use `but oplog` and `but undo` |

## Recovery Pattern

```bash
# View recent operations
but oplog

# Undo last operation
but undo

# Or restore to specific snapshot
but restore <snapshot-id>

# If workspace corrupted
but base update
# Last resort: but init
```

**See [references/reference.md](references/reference.md#troubleshooting-guide) for comprehensive troubleshooting**

</troubleshooting>

<comparison>

## GitButler vs Graphite

| Aspect | Graphite | GitButler |
|--------|----------|-----------|
| Model | Linear stacks of physical branches | Virtual branches, optional stacking |
| Branch switching | Required (`gt up`/`gt down`) | Never needed (all applied) |
| PR submission | ✓ `gt submit --stack` | ✗ CLI only (use `gh` or GUI) |
| Multi-agent | Serial (checkout required) | Parallel (virtual branches) |
| Post-hoc organization | Difficult | `but rub` trivial |
| CLI completeness | Full automation | Partial (missing PR/push) |

**Choose GitButler for**: Exploratory work, multi-agent, post-hoc organization
**Choose Graphite for**: Production automation, PR submission, terminal-first

</comparison>

<references>

- [references/reference.md](references/reference.md) — complete CLI reference and troubleshooting
- [references/examples.md](references/examples.md) — real-world workflow patterns
- [multi-agent skill](../multi-agent/SKILL.md) — multi-agent coordination
- [stack-workflows skill](../stack-workflows/SKILL.md) — stacked branches
- [complete-branch skill](../complete-branch/SKILL.md) — merging to main
- [GitButler Docs](https://docs.gitbutler.com/) — official documentation

</references>

```

### ../stack-workflows/SKILL.md

```markdown
---
name: stack-workflows
version: 2.0.0
description: This skill should be used when creating stacked branches, dependent features, reviewable PR breakdown, or when stack, stacked branches, or `--anchor` are mentioned.
---

# GitButler Stack Workflows

Dependent branches → anchor-based stacking → reviewable chunks.

<when_to_use>

- Sequential dependencies (e.g., refactor → API → frontend)
- Large features broken into reviewable chunks
- Granular code review (approve/merge early phases independently)
- Post-hoc stack organization after exploratory coding

NOT for: independent parallel features (use virtual branches), projects using Graphite stacking

</when_to_use>

<stack_vs_virtual>

## Stacked vs Virtual Branches

| Type | Use Case | Dependencies |
|------|----------|--------------|
| **Virtual** | Independent, unrelated work | None — parallel |
| **Stacked** | Sequential dependencies | Each builds on parent |

Stacked branches = virtual branches split into dependent sequence.
Default: Virtual branches are stacks of one.

</stack_vs_virtual>

<create>

## Creating Stacks

```bash
# Base branch (no anchor)
but branch new base-feature

# Stacked branch (--anchor specifies parent)
but branch new child-feature --anchor base-feature

# Third level
but branch new grandchild-feature --anchor child-feature
```

**Result:** `base-feature` ← `child-feature` ← `grandchild-feature`

**Short form:** `-a` instead of `--anchor`

```bash
but branch new child -a parent
```

</create>

<patterns>

## Stack Patterns

### Feature Dependency Stack

```bash
# Auth foundation
but branch new auth-core
but commit auth-core -m "feat: add authentication core"

# OAuth layer depends on auth core
but branch new auth-oauth --anchor auth-core
but commit auth-oauth -m "feat: add OAuth integration"

# Social login depends on OAuth
but branch new auth-social --anchor auth-oauth
but commit auth-social -m "feat: add social login"
```

### Refactoring Stack

```bash
# Extract utilities
but branch new refactor-extract-utils
but commit refactor-extract-utils -m "refactor: extract common utilities"

# Update consumers
but branch new refactor-use-utils --anchor refactor-extract-utils
but commit refactor-use-utils -m "refactor: use extracted utilities"

# Clean up
but branch new refactor-cleanup --anchor refactor-use-utils
but commit refactor-cleanup -m "refactor: remove deprecated code"
```

### Deep Stack (5 levels)

```bash
but branch new db-schema
but branch new data-access --anchor db-schema
but branch new business-logic --anchor data-access
but branch new api-endpoints --anchor business-logic
but branch new frontend-integration --anchor api-endpoints
```

</patterns>

<post_hoc>

## Post-Hoc Stack Organization

**Problem:** Created branches independently, now want to stack them.

**Solution:** Recreate with correct anchors:

```bash
# Current: three independent branches
# feature-a, feature-b, feature-c

# Stack feature-b on feature-a
but branch new feature-b-stacked --anchor feature-a
commit_sha=$(but log | grep "feature-b:" | head -1 | awk '{print $1}')
but rub $commit_sha feature-b-stacked
but branch delete feature-b --force

# Stack feature-c on feature-b-stacked
but branch new feature-c-stacked --anchor feature-b-stacked
commit_sha=$(but log | grep "feature-c:" | head -1 | awk '{print $1}')
but rub $commit_sha feature-c-stacked
but branch delete feature-c --force
```

</post_hoc>

<pr_workflow>

## PR Preparation for Stacks

**GitButler CLI lacks native PR submission.** Use GitHub CLI:

```bash
# Push branches
git push -u origin base-feature
git push -u origin dependent-feature

# Create PRs with correct base branches
gh pr create --base main --head base-feature \
  --title "feat: base feature" \
  --body "First in stack"

gh pr create --base base-feature --head dependent-feature \
  --title "feat: dependent feature" \
  --body "Depends on base-feature PR"
```

**GitHub Settings:**
- Enable automatic branch deletion after merge
- Use **Merge** strategy (recommended) — no force pushes needed
- Merge bottom-to-top (sequential order)

</pr_workflow>

<reorganize>

## Stack Reorganization

### Squashing Within Stack

```bash
newer_commit=$(but log | grep "newer" | awk '{print $1}')
older_commit=$(but log | grep "older" | awk '{print $1}')
but rub $newer_commit $older_commit
```

### Moving Commits Between Stack Levels

```bash
commit_sha=$(but log | grep "specific commit" | awk '{print $1}')
but rub $commit_sha correct-branch
```

### Splitting a Branch

```bash
# Original has multiple features
but branch new second-feature --anchor original-branch
commit_sha=$(but log | grep "second feature commit" | awk '{print $1}')
but rub $commit_sha second-feature
```

</reorganize>

<navigation>

## Stack Navigation

**Note:** Virtual branches don't need checkout — all branches active simultaneously.

```bash
# View full stack structure
but log

# Work on any branch directly (no checkout needed)
but commit base-feature -m "update base"
but commit dependent-feature -m "update dependent"

# JSON for programmatic analysis
but --json log | jq '.[] | .branchDetails[] | {name, baseCommit}'
```

</navigation>

<rules>

ALWAYS:
- Create stacks with `--anchor` from the start
- Merge stacks bottom-to-top (base first, dependents after)
- Snapshot before reorganizing: `but snapshot --message "Before stack reorganization"`
- Keep each level small (100-250 LOC) for reviewability
- Delete empty branches after reorganization

NEVER:
- Skip stack levels when merging
- Stack independent, unrelated features (use virtual branches)
- Create deep stacks (5+ levels) without good reason
- Forget anchor when creating dependent branches

</rules>

<troubleshooting>

## Common Issues

| Symptom | Cause | Solution |
|---------|-------|----------|
| Stack not showing in `but log` | Missing `--anchor` | Recreate with correct anchor |
| Commits in wrong stack level | Wrong branch targeted | `but rub <sha> correct-branch` |
| Can't merge middle of stack | Wrong order | Merge bottom-to-top only |

## Recovery

```bash
# Recreate branch with correct anchor
but branch new child-stacked --anchor parent
commit_sha=$(but log | grep "child:" | head -1 | awk '{print $1}')
but rub $commit_sha child-stacked
but branch delete child --force
```

</troubleshooting>

<best_practices>

## Best Practices

### Planning

- Start simple: 2-3 levels max initially
- Single responsibility per level
- Only stack when there's a real dependency

### Maintenance

- Run `but log` regularly to verify structure
- Commit to correct branches immediately
- Clean up empty branches

### Communication

- Clear commit messages explaining why stack level exists
- Descriptive names indicating stack relationship
- Share `but status` when coordinating

</best_practices>

<references>

- [version-control skill](../version-control/SKILL.md) — core GitButler workflows
- [complete-branch skill](../complete-branch/SKILL.md) — merging to main
- [multi-agent skill](../multi-agent/SKILL.md) — multi-agent coordination
- [GitButler Stacks Docs](https://docs.gitbutler.com/features/branch-management/stacked-branches)

</references>

```

complete-branch | SkillHub