# User's Guide
This guide walks you through using retcon to clean up a messy git branch.
## Prerequisites
- A git repository with a messy feature branch
- The branch has been pushed or you have a backup
- `retcon` installed and in your PATH
- An LLM agent available (retcon uses Claude Code by default)
## Quick Start
```bash
# 1. Generate guidance for creating a spec
retcon prompt > guidance.md
# 2. Give the guidance to your agent to create a spec
# e.g. in `my-spec.toml`
# 3. Run the reconstruction
retcon execute my-spec.toml
```
## Step 1: Create the Spec with Your Agent
The `retcon prompt` command outputs guidance you can give to your LLM agent. The agent will analyze your diffs and propose a series of commits.
```bash
# Get the guidance prompt
retcon prompt
```
Give this prompt to your agent along with context about your branch:
```bash
# Show the agent your changes
git diff origin/main...my-feature-branch
```
The agent will:
1. Analyze the diff to understand what changed
2. Identify logical groupings (refactors, features, tests, etc.)
3. Propose a commit sequence with messages and hints
**Iterate with your agent** until you're happy with the structure. Ask questions like:
- "Can we split commit 2 into two parts?"
- "Should the config changes be in their own commit?"
- "Reorder so refactors come before features"
Once you've agreed on the structure, have the agent write out the TOML file:
```
Write this plan as a retcon spec file to my-spec.toml
```
### Manual Spec Creation
You can also create the spec manually. First understand what changed:
```bash
# See the full diff against target
git diff origin/main...my-feature-branch
# See which files changed
git diff origin/main...my-feature-branch --stat
# See the messy commit history (for context)
git log origin/main..my-feature-branch --oneline
```
Focus on the **diff**, not the commits. The diff shows what actually changed; the commits show how you got there (which is what we're cleaning up).
Then create a TOML file describing the clean history you want:
```toml
# my-spec.toml
source = "my-feature-branch" # Your messy branch
remote = "origin/main" # Target for the PR
cleaned = "my-feature-branch-clean" # New clean branch
[[commit]]
message = "refactor: extract validation into dedicated module"
hints = """
Move validate_user() and validate_session() from lib.rs to validation.rs.
Include the ValidationError enum.
Pure reorganization - no behavior changes.
"""
[[commit]]
message = "feat: add OAuth provider support"
hints = """
New oauth.rs module with OAuthProvider trait.
Includes Google and GitHub implementations.
Token refresh logic in token.rs.
"""
[[commit]]
message = "test: add OAuth integration tests"
hints = """
New file tests/oauth_test.rs.
Mock provider for testing.
"""
```
### Tips for Good Specs
1. **Refactors first**: Put code reorganization before new features
2. **One concept per commit**: Each commit should do one thing
3. **Specific hints**: Name files and functions, not just concepts
4. **Note exclusions**: If a file has changes for multiple commits, say which parts belong where
## Step 2: Run Retcon
```bash
retcon execute my-spec.toml
```
Retcon will:
1. Create the `cleaned` branch from the merge-base
2. For each commit in order:
- Show the LLM the diff and your hints
- Apply the relevant changes
- Run `cargo check` (build verification)
- If it passes, mark complete and move on
- If it fails, try to fix it
- If stuck, stop and ask for help
### Watching Progress
Retcon prints progress as it works:
```
Resuming from commit 1/3: refactor: extract validation
Created commit
Building...
Build passed
✓ Commit complete
Commit 2/3: feat: add OAuth provider support
Created commit
Building...
Build failed, consulting LLM...
Created WIP commit
Building...
Build passed
✓ Commit complete
```
### The Spec File is State
Retcon updates your spec file as it works. After running, you'll see:
```toml
[[commit]]
message = "refactor: extract validation into dedicated module"
hints = "..."
history = [
{ commit_created = "a1b2c3d" },
"complete",
]
[[commit]]
message = "feat: add OAuth provider support"
hints = "..."
history = [
{ commit_created = "e4f5g6h" },
{ commit_created = "i7j8k9l" }, # WIP fix
"complete",
]
```
## Step 3: Handle Stuck States
Sometimes retcon can't proceed:
```
Commit 2/3: feat: add OAuth provider support
...
Build failed, consulting LLM...
LLM: "I'm stuck. OAuthProvider depends on SessionManager which
isn't in the diff yet - it's probably in commit 3."
✗ Stuck - stopping
```
Your spec now shows:
```toml
history = [
{ commit_created = "a1b2c3d" },
{ stuck = "OAuthProvider depends on SessionManager..." },
]
```
### To Continue
1. **Understand the problem**: Read the stuck message
2. **Fix it**: Edit hints, reorder commits, or manually adjust code
3. **Add a resolved entry**: Tell retcon what you changed
```toml
history = [
{ commit_created = "a1b2c3d" },
{ stuck = "OAuthProvider depends on SessionManager..." },
{ resolved = "Reordered commits 2 and 3 - SessionManager needs to come first" },
]
```
4. **Resume**:
```bash
retcon execute my-spec.toml
```
Retcon will retry with your resolution note as context.
### If You Don't Add Resolved
```bash
$ retcon execute my-spec.toml
Resuming from commit 2/3: feat: add OAuth provider support
✗ Previously stuck - add a `resolved` entry to continue
Edit the spec file and add after the `stuck` entry:
{ resolved = "description of what you changed" }
```
This ensures the LLM knows what changed before retrying.
## Step 4: Review the Result
When complete:
```bash
# Check out the clean branch
git checkout my-feature-branch-clean
# Review the history
git log --oneline
# Compare to original (should be identical content)
git diff my-feature-branch
# (should show nothing)
```
### Handling WIP Commits
If retcon created WIP commits during fixes, you can squash them:
```bash
git checkout my-feature-branch-clean
git rebase -i origin/main
# Mark WIP commits as "fixup" to fold them into their parent
```
Or keep them for transparency about the reconstruction process.
## Common Patterns
### Circular Dependencies
**Problem**: Commit A needs something from commit B, but B depends on A.
**Solution**: Combine them into one commit, or extract the shared piece into a third commit that comes first.
```toml
# Before (broken)
[[commit]]
message = "feat: add TokenStore"
# ...
[[commit]]
message = "feat: add SessionManager"
# SessionManager uses TokenStore, but TokenStore uses SessionManager!
# After (fixed)
[[commit]]
message = "feat: add TokenStore and SessionManager"
hints = "These have circular dependencies - must be in same commit"
```
### Interleaved Changes
**Problem**: One file has changes for multiple logical commits.
**Solution**: Use hints to specify which changes belong where.
```toml
[[commit]]
message = "refactor: rename foo to bar"
hints = """
In src/lib.rs: ONLY the foo→bar renames (lines 10-50 of the diff).
Do NOT include the new baz() function - that's commit 2.
"""
[[commit]]
message = "feat: add baz functionality"
hints = """
In src/lib.rs: the new baz() function.
Builds on the bar rename from commit 1.
"""
```
### Missing Dependencies
**Problem**: Build fails because something from a later commit is needed.
**Solution**: Either reorder commits, or pull the dependency into the current commit's hints.
```toml
[[commit]]
message = "feat: add OAuth flow"
hints = """
Include the OAuthConfig struct even though it's "supposed" to be
in the config commit - we need it here for the code to compile.
"""
```
## Troubleshooting
### "Failed to find merge-base"
Your source and remote branches don't share history. Make sure:
- `source` is your feature branch name
- `remote` is the target branch (e.g., `origin/main`)
- Both branches exist
### "No more changes to extract"
The diff between cleaned and source is empty. This means either:
- All changes have been extracted (success!)
- The branches are identical (nothing to do)
- Wrong branch names in the spec
### Build Keeps Failing
If the LLM keeps getting stuck:
1. Check if changes are correctly split - maybe they need to be combined
2. Add more specific hints about what to include
3. Manually make the fix and add a `resolved` entry
### Want to Start Over
```bash
# Delete the clean branch
git branch -D my-feature-branch-clean
# Remove history from spec (or delete and recreate)
# Edit my-spec.toml, remove all `history = [...]` fields
# Run again
retcon execute my-spec.toml
```