Claude
Skills
Sign in
Back

jj

Included with Lifetime
$97 forever

Jujutsu (jj) version control system - a Git-compatible VCS with novel features. Use when working with jj repositories, managing stacked/dependent commits, needing automatic rebasing with first-class conflict handling, using revsets to select commits, or wanting enhanced Git workflows. Triggers on mentions of 'jj', 'jujutsu', change IDs, operation log, or jj-specific commands.

General

What this skill does


# Jujutsu (jj) Version Control System

## Overview

Jujutsu is a powerful Git-compatible version control system that combines ideas from Git, Mercurial, Darcs, and adds novel features. It uses Git repositories as a storage backend, making it fully interoperable with existing Git tooling.

**Key differentiators from Git:**
- Working copy is automatically committed (no staging area)
- Conflicts can be committed and resolved later
- Automatic rebasing of descendants when commits change
- Operation log enables easy undo of any operation
- Revsets provide powerful commit selection
- Change IDs stay stable across rewrites (unlike commit hashes)

## When to Use This Skill

- User mentions "jj", "jujutsu", or "jujutsu vcs"
- Working with stacked/dependent commits
- Questions about change IDs vs commit IDs
- Revset queries for selecting commits
- Conflict resolution workflows in jj
- Git interoperability with jj
- Operation log, undo, or redo operations
- History rewriting (squash, split, rebase, diffedit)
- Bookmark management (jj's equivalent of branches)

## Key Concepts

### Working Copy as a Commit

In jj, the working copy is always a commit. Changes are automatically snapshotted:

```bash
# No need for 'git add' - changes are tracked automatically
jj status        # Shows working copy state
jj diff          # Shows changes in working copy commit
```

### When Snapshots Are Triggered

The working copy is snapshotted into `@` when running most jj commands (`new`, `status`, `diff`, `log`, `describe`). Force a snapshot with `jj util snapshot` or just run any jj command.

### Change ID vs Commit ID

- **Change ID**: Stable identifier that persists across rewrites (e.g., `kntqzsqt`)
- **Commit ID**: Hash that changes when commit is rewritten (e.g., `5d39e19d`)

Always prefer change IDs when referring to commits in commands.

**Versioned access (0.37+):** Use `xyz/n` suffix to access hidden/divergent versions:
- `xyz/0` - latest version of change xyz
- `xyz/1` - previous version (useful for `jj restore --from xyz/1 --to xyz`)
- Shown automatically in `jj log` for divergent changes

### No Staging Area

Instead of staging, use these patterns:
- `jj split` - Split working copy into multiple commits
- `jj squash -i` - Interactively move changes to parent
- Direct editing with `jj diffedit`

### First-Class Conflicts

Conflicts are recorded in commits, not blocking operations:

```bash
jj rebase -s X -d Y     # Succeeds even with conflicts
jj log                   # Shows conflicted commits with ×
jj new <conflicted>      # Work on top of conflict
# Edit files to resolve, then:
jj squash                # Move resolution into parent
```

### Operation Log

Every operation is recorded and can be undone:

```bash
jj op log                # View operation history
jj undo                  # Undo last operation
jj redo                  # Redo undone operation
jj op revert <op-id>     # Revert specific operation
jj op restore <op-id>    # Restore to specific operation
```

## Essential Commands

| Command | Description | Git Equivalent |
|---------|-------------|----------------|
| `jj git clone <url>` | Clone a Git repository | `git clone` |
| `jj git init` | Initialize new repo | `git init` |
| `jj status` / `jj st` | Show working copy status | `git status` |
| `jj log` | Show commit history | `git log --graph` |
| `jj diff` | Show changes | `git diff` |
| `jj new` | Create new empty commit | - |
| `jj describe` / `jj desc` | Edit commit message | `git commit --amend` (msg only) |
| `jj edit <rev>` | Edit existing commit | `git checkout` + amend |
| `jj squash` | Move changes to parent | `git commit --amend` |
| `jj split` | Split commit in two | `git add -p` + multiple commits |
| `jj rebase` | Move commits | `git rebase` |
| `jj bookmark` / `jj b` | Manage bookmarks | `git branch` |
| `jj git fetch` | Fetch from remote | `git fetch` |
| `jj git push` | Push to remote | `git push` |
| `jj undo` | Undo last operation | `git reflog` + reset |
| `jj file annotate` | Show line origins | `git blame` |
| `jj file search` | Search file contents | `git grep` |
| `jj commit` | Finalize WC commit + start new | `git commit` |
| `jj absorb` | Auto-squash into right commits | `git commit --fixup` + autosquash |
| `jj evolog` | History of a single change | `git reflog` (per-commit) |
| `jj next` / `jj prev` | Navigate commit graph | `git checkout HEAD~` |
| `jj interdiff` | Compare diffs of two changes | - |
| `jj fix` | Run formatters on commits | - |
| `jj arrange` | TUI to reorder/abandon commits | `git rebase -i` (reorder) |
| `jj bookmark advance` | Move bookmark forward | fast-forward branch |

## Common Workflows

### Starting a New Change

```bash
# Working copy changes are auto-committed
# When ready to start fresh work:
jj new                    # Create new commit on top
jj describe -m "message"  # Set description
# Or combine:
jj new -m "Start feature X"
```

### Editing a Previous Commit

```bash
# Option 1: Edit in place
jj edit <change-id>       # Make working copy edit that commit
# Make changes, they're auto-committed
jj new                    # Return to working on new changes

# Option 2: Squash changes into parent
jj squash                 # Move all changes to parent
jj squash -i              # Interactively select changes

# Option 3: Auto-squash into correct commits in stack
jj absorb                 # Each hunk goes to commit that last changed those lines
```

### Rebasing Commits

```bash
# Rebase current branch onto main
jj rebase -d main

# Rebase specific revision and descendants
jj rebase -s <rev> -d <destination>

# Rebase only specific revisions (not descendants)
jj rebase -r <rev> -d <destination>

# Insert commit between others
jj rebase -r X -A Y       # Insert X after Y
jj rebase -r X -B Y       # Insert X before Y

# Simplify redundant parents during rebase
jj rebase -s <rev> -d <dest> --simplify-parents
```

### Reordering Commits with `jj arrange`

```bash
jj arrange <revset>       # Open TUI to reorder/abandon commits
```

The TUI shows selected commits with their immediate parents/children. Use swap up/down to reorder along graph edges.

### Working with Bookmarks (Branches)

```bash
jj bookmark list          # List bookmarks
jj bookmark create <name> # Create at current commit
jj bookmark set <name>    # Move bookmark to current commit
jj bookmark delete <name> # Delete bookmark
jj bookmark track <name> --remote <remote>  # Track remote bookmark
jj bookmark advance       # Move bookmark forward to @ (like "jj tug")
```

**Gotchas:** Use `--allow-backwards` to move a bookmark to an ancestor. The `*` suffix in log means diverged from remote (push to sync). Use `bookmark set` (not `create`) if the bookmark may already exist on a remote.

### Searching File Contents

```bash
jj file search <pattern>                  # Search with regex (default)
jj file search --pattern "glob:*.rs"      # Use glob pattern
jj file search --pattern "substring:foo"  # Substring match
jj file search -r <rev> <pattern>         # Search at specific revision
```

### Pushing Changes

```bash
# Push specific bookmark
jj git push --bookmark <name>

# Push change by creating auto-named bookmark
jj git push --change <change-id>

# Push all bookmarks (skips ineligible: private/conflicted)
jj git push --all

# Pass push options to remote server
jj git push --bookmark <name> --option key=value
```

**Reorder a pushed/stacked branch:** `jj rebase --ignore-immutable -s <change> -d <dest>` (descendants auto-rebase), then `jj git push --bookmark <name>` — `jj git push` is force-with-lease-safe by default (no flag). See [references/github-workflow.md](references/github-workflow.md).

### Resolving Conflicts

```bash
# After a rebase creates conflicts:
jj log                    # Find conflicted commit (marked with ×)
jj new <conflicted>       # Create commit on top
# Edit files to resolve conflicts
jj squash                 # Move resolution into conflicted commit

# Or use ext
Files: 10
Size: 117.6 KB
Complexity: 55/100
Category: General

Related in General