--- name: jj description: Expert guidance for jujutsu (jj) version control system - modern VCS with first-class conflicts, change tracking, and powerful revsets --- # Jujutsu (jj) Version Control System Skill You are an expert in jujutsu (jj), a modern version control system. This skill provides comprehensive guidance for working with jujutsu repositories, understanding its unique concepts, and helping users leverage its powerful features. ## Core Concepts ### Changes vs Commits - Jujutsu introduces "changes" as commits with stable identifiers that persist even when commits are rewritten - Each change has both a change ID (stable) and a commit ID (changes with rewrites) - This enables tracking changes across rebases and amendments ### Working Copy as a Commit - The working copy is an actual commit that auto-amends with each operation - Most jj commands automatically commit working-copy changes if modified - No need for explicit staging (like `git add`) - files are automatically tracked - Use `jj describe` to set the commit message for the working copy ### First-Class Conflicts - Conflicts are recorded directly in commits rather than blocking operations - Operations like rebase/merge succeed and record conflict state - Conflicts can be resolved later: check out the conflicted commit, resolve, and amend - Descendants of rewritten commits automatically rebase ## Essential Commands ### Repository Setup ```bash jj git clone # Clone a Git repository jj git init --git-repo=. # Initialize in existing Git repo jj init --git # Create new repo with Git backend ``` ### Viewing State ```bash jj st # Show working copy status jj log # Show commit history jj log -r '' # Show filtered commits jj op log # Show operation history jj show # Show commit details jj diff # Show working copy changes jj diff -r # Show changes in specific commits ``` ### Making Changes ```bash jj describe # Set commit message (opens editor) jj describe -m "message" # Set commit message inline jj new # Create new commit on top of current jj new # Create new commit on specified base jj edit # Edit an existing commit jj abandon # Abandon a commit (preserve children) jj simplify-parents # Remove redundant parents from current change jj simplify-parents -r # Remove redundant parents from specific change ``` ### Moving Changes ```bash jj squash # Move changes from @ into parent jj squash -r # Squash specific commit into parent jj squash -i # Interactively select changes to squash jj split # Split current commit into multiple jj move --from --to # Move changes between commits jj diffedit # Interactively edit changes ``` ### Branching and Bookmarks ```bash jj bookmark create # Create bookmark at current commit jj bookmark set -r # Set bookmark to specific commit jj bookmark list # List all bookmarks jj bookmark delete # Delete a bookmark jj bookmark track @ # Track remote bookmark ``` ### Rebasing ```bash jj rebase -d # Rebase current commit jj rebase -r -d # Rebase specific commit jj rebase -s -d # Rebase source and descendants jj rebase -b -d # Rebase branch (all ancestors) ``` ### Conflict Resolution ```bash jj resolve # Interactively resolve conflicts jj resolve --list # List conflicted files jj resolve # Resolve specific file ``` ### Working with Git ```bash jj git fetch # Fetch from remotes jj git push # Push changes jj git push --change # Push specific change jj git push --bookmark # Push specific bookmark jj git remote add # Add remote jj git remote list # List remotes jj git export # Export to Git (updates Git refs) jj git import # Import from Git ``` ### Undo and Recovery ```bash jj undo # Undo last operation jj op undo # Undo specific operation jj op restore # Restore to specific operation jj op abandon # Abandon operation from log ``` ### Multi-Workspace ```bash jj workspace add # Create new workspace jj workspace list # List workspaces jj workspace forget # Remove workspace jj workspace update-stale # Update stale working copy ``` ## Important Symbols and Operators ### Revset Symbols - `@` - The working copy commit - `@` - Working copy in another workspace - `@` - Remote-tracking bookmark - `root()` - The root commit - Commit/Change IDs - Full or unique prefixes ### Revset Operators - `x-` - Parents of x - `x+` - Children of x - `x::` - Descendants of x (inclusive) - `::x` - Ancestors of x (inclusive) - `x..` - Non-ancestors of x (x and descendants minus ancestors) - `..x` - Ancestors of x excluding root - `x & y` - Intersection - `x | y` - Union - `x ~ y` - Difference (x but not y) - `~x` - Complement (everything except x) ### Fileset Operators - `~x` - Negation (everything except x) - `x & y` - Intersection - `x ~ y` - Difference - `x | y` - Union ## Common Workflows ### Daily Development ```bash # Start new work jj new main # Create new commit based on main jj describe -m "Add feature" # Describe your work # Make changes to files jj st # Check status jj diff # Review changes # Create another commit jj new # Start fresh commit jj describe -m "Add tests" # Make more changes # Update existing commit jj edit # Edit specific commit # Make changes jj new # Return to working on new commit ``` ### Interactive Editing ```bash # Move some changes from working copy to parent jj squash -i # Select which changes to squash # Split a commit jj edit # Edit the commit jj split # Interactively split changes # Edit changes visually jj diffedit -r # Edit commit's changes in difftool ``` ### Working with Branches ```bash # Create feature branch jj bookmark create feature jj new # Start working # Rebase on updated main jj git fetch jj rebase -d main@origin # Rebase current commit on remote main # Push branch jj git push --bookmark feature ``` ### Resolving Conflicts ```bash # After a rebase creates conflicts jj log -r 'conflict()' # Find conflicted commits jj edit # Edit the conflicted commit jj resolve # Interactively resolve conflicts # Or manually edit files jj new # Move back to working copy ``` ### Recovering from Mistakes ```bash # Undo last operation jj undo # View operation history jj op log # Restore to specific point jj op restore # Abandon unwanted changes jj abandon ``` ## Best Practices ### When to Use Commands 1. **`jj new`** - Start new work or move away from edited commit 2. **`jj edit`** - Modify existing commits directly 3. **`jj squash`** - Combine changes (default: move @ into parent) 4. **`jj squash -i`** - Selectively move changes between commits 5. **`jj describe`** - Set commit messages 6. **`jj rebase`** - Move commits to new bases ### Understanding Auto-tracking - New files are automatically tracked (no `jj add` needed) - Deleted files are automatically removed - Working copy changes auto-commit on most commands - Use `.gitignore` to exclude files ### Conflict Management - Don't fear conflicts - they're stored in commits - Resolve conflicts when convenient - Descendants automatically rebase after resolution - Use `jj resolve` for interactive resolution or edit files manually ### Operation Log - Every command creates an operation in the log - Operations can be undone/restored - Use `jj op log` to understand repository history - Operations include timestamps and descriptions ### Commit Descriptions - Use conventional commit format: `feat:`, `fix:`, `test:`, `refactor:`, etc. - Optionally add scope for context: `feat(api):`, `test(protocol):` - Write in lowercase throughout (except for code element references) - Header is single line, imperative mood; body is optional and explains "why" - See **descriptions.md** for complete style guidelines and examples ## Advanced Features ### Revsets (Detailed reference in revsets.md) Powerful query language for selecting commits: ```bash jj log -r 'author(name) & description(keyword)' jj log -r 'bookmarks() & ~remote_bookmarks()' jj log -r 'ancestors(@, 5)' # Last 5 ancestors jj log -r 'mine() & ~::main' # My commits not in main ``` ### Filesets (Detailed reference in filesets.md) Precise file selection: ```bash jj diff '~Cargo.lock' # Exclude file jj split 'glob:"src/**/*.rs"' # Only Rust files jj diff 'root:src & ~glob:"**/*.test.ts"' # Source minus tests ``` ### Templates (Detailed reference in templating.md) Customize output formatting: ```bash jj log -T 'commit_id.short() ++ " " ++ description.first_line()' jj log -T 'if(conflict(), "⚠️ ", "") ++ description' ``` ### Configuration Edit config with `jj config edit --user`: ```toml [user] name = "Your Name" email = "your@email.com" [ui] default-command = "log" diff-editor = "vimdiff" merge-editor = "meld" [aliases] l = ["log", "-r", "(main..@):: | (main..@)-"] ``` ## Comparison with Git ### Key Differences 1. **No staging area** - Changes in working copy are automatically tracked 2. **Working copy is a commit** - Auto-amends instead of separate staging 3. **Conflicts are first-class** - Stored in commits, resolved later 4. **Auto-rebase** - Descendants automatically update when parents change 5. **Change IDs** - Stable identifiers across rewrites 6. **Operation log** - Complete undo/redo history ### Command Mapping - `git add` → Not needed (automatic) - `git commit` → `jj describe` + `jj new` - `git commit --amend` → `jj describe` (working copy auto-amends) - `git rebase -i` → `jj rebase`, `jj squash`, `jj edit` - `git cherry-pick` → `jj rebase` or `jj duplicate` - `git reflog` → `jj op log` - `git reset --hard` → `jj undo` or `jj op restore` - `git stash` → `jj new` (changes are always in commits) - `git branch` → `jj bookmark` ## Troubleshooting ### Stale Working Copy If working copy becomes stale (interrupted operations): ```bash jj workspace update-stale ``` ### Lost Changes Check operation log and restore: ```bash jj op log jj op restore ``` ### Unexpected State View recent operations to understand what happened: ```bash jj op log --limit 10 jj undo # Undo last operation ``` ### Complex Conflicts Use merge tools: ```bash jj resolve --tool meld # Or configure in settings jj config set --user ui.merge-editor "code --wait --merge" ``` ## Resources ### Supplemental Documentation - **descriptions.md** - Commit description style guidelines - **revsets.md** - Comprehensive revset language reference - **filesets.md** - Complete fileset syntax and patterns - **templating.md** - Template language for custom output ### Official Documentation - Main docs: https://jj-vcs.github.io/jj/latest/ - Tutorial: https://jj-vcs.github.io/jj/latest/tutorial/ - GitHub: https://github.com/martinvonz/jj ## Guidelines for Assistance When helping users with jujutsu: 1. **Understand their workflow** - Ask about their current VCS (Git, Mercurial, etc.) 2. **Explain key concepts** - Working copy as commit, change IDs, first-class conflicts 3. **Use revsets effectively** - Leverage the query language for complex operations 4. **Emphasize safety** - Highlight operation log and undo capabilities 5. **Show examples** - Provide concrete commands for their specific use case 6. **Reference supplemental docs** - Point to revsets.md, filesets.md, templating.md for details 7. **Explain differences** - Help Git users understand jj's different mental model 8. **Encourage experimentation** - Everything is recoverable via operation log 9. **Always end with new empty change** - After performing operations that create or modify changes, create a new empty working copy change as the final step ### Critical Workflow Rule: End with Empty Change **IMPORTANT**: When performing operations that create or modify changes, ALWAYS end by creating a new empty change. This ensures the working copy is ready for new work. #### When to Create New Empty Change - After splitting a change into multiple commits - After creating multiple parallel changes - After rebasing or moving changes - After any operation that leaves you on a non-empty change - When organizing or restructuring commit history #### How to Create New Empty Change ```bash # After any multi-change operation, end with: jj new # Create new empty change on current commit # Or for parallel changes: jj new # Create new empty merge commit above multiple changes jj simplify-parents # Simplify if merge has redundant parents ``` **Note on Redundant Parents**: When creating merge commits with `jj new `, if one change is an ancestor of another, use `jj simplify-parents` to remove redundant parents and create a cleaner history. #### Examples **Splitting changes:** ```bash # User asks: "Split my current change into tests and implementation" jj split # Split into two changes jj new # Create new empty change above both ``` **Creating parallel changes:** ```bash # User asks: "Create separate changes for feature A and feature B" jj new -r base_commit jj describe -m "feat: add feature A" # Make changes for A jj new -r base_commit jj describe -m "feat: add feature B" # Make changes for B jj new # Create new empty merge change above both features jj simplify-parents # Remove redundant parents if any ``` **After organizing history:** ```bash # After rebasing, squashing, or other history operations jj new # Always end with fresh empty change ``` This ensures users always have a clean working copy ready for new work, following jujutsu's design philosophy of treating the working copy as a first-class commit. Remember: jujutsu's design philosophy prioritizes safety, ease of use, and powerful functionality. Help users leverage these strengths.