Why Jujutsu (jj) Is Perfect for AI-Generated Code
If you're using AI to write code, you need better version control. Git wasn't designed for the iterative, experimental nature of AI-assisted development. Jujutsu is.
The Problem: Git Fights AI Workflows
When AI writes your code, your development process changes fundamentally. Instead of carefully crafted commits, you're dealing with:
- Rapid iteration cycles: AI generates, you test, refine the prompt, regenerate
- Experimental branches: Multiple attempts at the same problem with different approaches
- Frequent rewrites: AI rarely matches your actual architecture on the first try
- History chaos: Your commit log becomes a graveyard of "fix AI-generated bug" commits
Traditional Git workflows crumble under this pressure. You end up with messy histories, complex rebases, and the constant fear of losing work during cleanup. It's like trying to write a novel with a typewriter (technically possible, but you're fighting your tools).
Enter Jujutsu: Version Control for the AI Age
Jujutsu (jj) reimagines version control around "changes" instead of "commits." This subtle shift unlocks workflows that are perfect for AI-assisted development.
Changes vs. Commits: The Time Machine Effect
In Git, once you commit, you're committed (pun intended). Want to fix something three commits back? Welcome to rebase hell.
In jj, every change is mutable. You can edit any change at any time, and jj automatically rebases everything downstream. It's like having a time machine for your code (or more accurately, it's like having a word processor instead of a typewriter).
Real scenario: Your AI generates a new API endpoint, but after testing, you realize the interface needs adjustment. In Git, you'd either:
- Add a "fix interface" commit (messy history)
- Interactive rebase (risk breaking things)
In jj, you just edit the original change. Everything depending on it updates automatically. No git surgery required.
Perfect for AI Experimentation
AI development is inherently experimental. You'll often have multiple AI-generated solutions to compare. Jj's branching model makes this trivial:
# Create three different AI attempts at the same feature
jj new -m "AI attempt 1: REST API approach"
# ... let AI generate solution 1
jj new -m "AI attempt 2: GraphQL approach"
# ... let AI generate solution 2
jj new -m "AI attempt 3: RPC approach"
# ... let AI generate solution 3
# Check your current status
jj st
Your history stays clean, and you can easily compare approaches without complex Git gymnastics. It's like having multiple drafts of the same essay, but they all know about each other's existence.
Stacked Changes for Iterative Development
AI rarely gets complex features right on the first try. You'll typically iterate:
- AI generates basic structure
- AI adds error handling
- AI adds tests
- AI optimizes performance
In jj, these become a natural stack of changes:
@ Add performance optimizations
◉ Add comprehensive tests
◉ Add error handling
◉ Basic feature implementation
◉ main
When the AI needs to fix something in the basic implementation, you edit that change, and all the dependent changes automatically rebase. It's like editing the foundation of a house and having all the floors automatically adjust (no manual reconstruction required).
Bookmarks: Git Branches That Actually Make Sense
Here's where jj really shines for GitHub workflows. Instead of Git's branch model (which feels like naming your children before they're born), jj uses "bookmarks."
In Git, you have to decide on a branch name before you know what you're building:
git checkout -b feature/maybe-user-auth-or-something
In jj, you build first, name later:
# Work on several changes
jj new -m "Add user model"
jj new -m "Add authentication"
jj new -m "Add middleware"
# Later, when you know what you built:
jj bookmark create user-auth-system
Bookmarks are just pointers to changes. Multiple bookmarks can point to the same change, and they move automatically as you rebase. When you're ready for a PR:
jj git push --bookmark user-auth-system
This pushes your bookmark as a Git branch to GitHub. Your PR workflow remains unchanged, but your local development becomes infinitely more flexible.
The AI Development Workflow
Here's how jj transforms AI-assisted development:
1. Start with Architecture (Install jj first: GitHub releases)
# In your existing Git repo
jj init --git-repo .
jj new -m "Define API interface"
# You design the interface, AI fills implementation
2. Iterative Implementation
jj new -m "Implement user service"
# Let AI implement based on your interface
jj new -m "Add validation"
# AI adds validation layer
jj st # Check your current status
jj new -m "Add error handling"
# AI improves error handling
3. Discover Issues and Fix Retroactively
# Oh no, the interface needs adjustment
jj edit "Define API interface"
# Make changes, everything downstream updates automatically
4. Ship When Ready
jj bookmark create feature-user-service
jj git push --bookmark feature-user-service
Your final history tells the story of what was built, not how many times the AI hallucinated.
Handling AI's Favorite Mistake: The Everything Sandwich
AI loves to mix concerns. It'll add logging, error handling, database migrations, and new features all in one glorious mess. With jj, you can easily split these apart after the fact:
# AI generated everything in one messy change
jj split
# Interactively split into logical pieces
This is nearly impossible in Git without performing open-heart surgery on your repository.
The Refactoring Advantage
Mitchell Hashimoto (creator of Vagrant, Terraform) notes that AI agents excel at refactoring: "Anytime I ask it to do that, it's always perfect."
Jj makes AI refactoring risk-free. Since any change is editable, you can let AI aggressively refactor, knowing you can always edit or revert specific changes without losing other work. It's like having an undo button that actually understands context.
Why This Matters for AI-Generated Code
AI is changing how we write software. The traditional Git model (linear commits, careful history curation) was designed for human development patterns.
AI generates code differently:
- More experimental (they don't have egos to protect)
- Rapid iteration (they don't get tired)
- Frequent architectural changes (they don't fall in love with their first solution)
- Multiple attempts at solutions (they're happy to start over)
Jj was built for exactly this kind of workflow. It's not just better at handling AI-generated code; it transforms how you think about version control entirely. Git feels like accounting software after using jj (technically correct but unnecessarily painful).
The Learning Curve: Hours, Not Weeks
Basic jj concepts map to Git:
git add
→jj new
(creates a change)git commit
→ automatic (changes are always "committed")git log
→jj log
git status
→jj st
git push
→jj git push --bookmark <name>
git branch
→jj bookmark create <name>
The difference is that jj's model is simpler and more forgiving. It's version control designed for the AI era.
Takeaways
- Mutable Changes: Edit any change anytime, automatic downstream rebasing
- Experiment Freely: Easy comparison of multiple AI solutions
- Stack Naturally: Iterative development cycles become manageable
- Risk-Free Refactoring: Let AI aggressively refactor with easy rollback
- Bookmarks > Branches: Name things when you understand them, not before
- Zero Migration Cost: Works with existing Git repos and GitHub workflows
- Simple Mental Model: Changes instead of commits reduces cognitive overhead