Skip to content

Instantly share code, notes, and snippets.

@christianromney
Last active August 18, 2025 13:07
Show Gist options
  • Save christianromney/1d71097f0a2381336502a21719985fab to your computer and use it in GitHub Desktop.
Save christianromney/1d71097f0a2381336502a21719985fab to your computer and use it in GitHub Desktop.
🤖 Generated by Claude Code using Context7

A Short Guide to Jujutsu for Impatient Git Users

Motivation

Jujutsu (jj) is a next-generation version control system that addresses several pain points Git users face daily:

Problems jj Solves:

  • No staging area confusion - Work directly with commits, no git add complexity
  • Automatic conflict resolution workflow - No git rebase --continue dance
  • Safe history rewriting - Rebase/amend operations can't lose work
  • Lock-free concurrency - Multiple operations can run simultaneously
  • Unified mental model - One consistent way to handle all operations

Key Benefits:

  • Every operation is reversible via the operation log
  • Commits are automatically rebased when their parents change
  • Conflicts are stored as first-class objects in commits
  • Working copy changes are automatically committed

Conceptual Documentation

Core Abstractions

Commits (Revisions)

  • Immutable snapshots identified by change IDs (not hashes)
  • Change IDs stay constant through rewrites (unlike Git SHA-1s)
  • Every change has both a change ID and a commit ID

Bookmarks (Similar to Git branches)

  • Mutable pointers to commits that automatically move with rewrites
  • Replace Git's branch concept with better merge tracking
  • Can track remote Git branches seamlessly

Working Copy

  • Always corresponds to a commit (the "working-copy commit")
  • Changes are automatically committed when you switch revisions
  • No staging area - edit files and they're in the next commit

Operation Log

  • Records every command that modifies the repository
  • Enables undo/redo of any operation
  • Provides lock-free concurrency by storing operation history
graph TB
    subgraph "jj Repository"
        subgraph "Working Copy"
            WC[📁 Working Directory<br/>Always auto-committed]
            WCC[📝 Working-Copy Commit<br/>@ - Current commit]
        end
        
        subgraph "Commit Graph"
            C1[📦 Commit A<br/>Change ID: abc123<br/>Commit ID: def456]
            C2[📦 Commit B<br/>Change ID: ghi789<br/>Commit ID: jkl012]
            C3[📦 Commit C<br/>Change ID: mno345<br/>Commit ID: pqr678]
        end
        
        subgraph "Bookmarks"
            BM1[🏷️ main]
            BM2[🏷️ feature-branch]
            BM3[🏷️ remote/origin/main]
        end
        
        subgraph "Operation Log"
            OP1[⚡ Op: jj new main]
            OP2[⚡ Op: jj describe]
            OP3[⚡ Op: jj rebase]
            OP4[⚡ Op: Current @]
        end
    end
    
    %% Relationships
    WC --> WCC
    WCC --> C3
    C3 --> C2
    C2 --> C1
    
    BM1 --> C2
    BM2 --> C3
    BM3 --> C1
    
    OP1 --> OP2
    OP2 --> OP3
    OP3 --> OP4
    
    %% Styling
    classDef commitStyle fill:#e1f5fe,stroke:#01579b
    classDef bookmarkStyle fill:#f3e5f5,stroke:#4a148c
    classDef workingStyle fill:#e8f5e8,stroke:#1b5e20
    classDef opStyle fill:#fff3e0,stroke:#e65100
    
    class C1,C2,C3,WCC commitStyle
    class BM1,BM2,BM3 bookmarkStyle
    class WC workingStyle
    class OP1,OP2,OP3,OP4 opStyle
Loading

Primary Operations

  • jj new - Create new commit (replaces git checkout -b)
  • jj edit - Switch to editing a commit (replaces git checkout)
  • jj describe - Change commit message (replaces git commit --amend)
  • jj abandon - Delete commits (replaces git reset --hard)
  • jj rebase - Move commits (like git rebase but safer)

Using jj With and Without Git

With Git (Co-located Repository):

  • jj and Git repos share the same .git directory
  • Use jj git import/export to sync between jj and Git
  • Can use Git tools alongside jj commands
  • Push/pull through jj's Git integration

Without Git (Pure jj Repository):

  • Native jj storage format
  • All features available without Git compatibility layer
  • Can still push to Git remotes when needed

Check Your Understanding: Concepts

Question 1: What is the key difference between jj's change IDs and Git's commit hashes?

Click to reveal answer

Change IDs remain constant through rewrites (like amend, rebase), while Git commit hashes change with every modification. This means you can reliably refer to a logical change even after rewriting its history.

Question 2: In jj, what happens when you edit files in your working directory?

Click to reveal answer

Files are automatically staged and committed to the current working-copy commit (@). There's no staging area or need for git add - changes are immediately part of the commit.

Question 3: How do bookmarks differ from Git branches in terms of behavior during rewrites?

Click to reveal answer

Bookmarks automatically move to follow commits when they're rewritten (rebased, amended, etc.), whereas Git branches can become orphaned or point to old commit hashes after rewrites.

Question 4: What is the operation log and why is it important?

Click to reveal answer

The operation log records every command that modifies the repository, enabling undo/redo of any operation and providing lock-free concurrency. It makes every jj operation reversible.

Tutorial: Adding jj to an Existing Git Repository

1. Initialize jj in Git Repository

# In your existing Git repo
jj git init --colocate

# Import existing Git history
jj git import

2. Basic Workflow Examples

Create and Switch Between Commits:

# Create new commit based on main
jj new main
# Edit files - they're automatically in this commit

# Switch to different commit
jj new some-feature
# Your working copy changes were auto-committed to previous commit

Handle Conflicts:

# If rebase creates conflicts, jj stores them in the commit
jj rebase -d main
# Edit conflict markers in files, then:
jj describe -m "Resolved conflicts"

Manage History:

# View history
jj log

# Rewrite commit message
jj describe -r @- -m "Better message"

# Move commits around
jj rebase -r @ -d main

# Abandon unwanted commits
jj abandon badcommit

3. Git Integration

Sync with Git:

# Pull changes from Git remote
jj git fetch

# Push jj bookmarks to Git
jj git push

# Import new Git branches
jj git import

Complete Workflow Visualization:

sequenceDiagram
    participant Dev as Developer
    participant WC as Working Copy
    participant Repo as jj Repository
    participant OpLog as Operation Log
    
    Note over Dev,OpLog: Common jj Workflow: Feature Development
    
    Dev->>+Repo: jj new main
    Repo-->>WC: Switch to new commit @ based on main
    Repo->>OpLog: Record: "jj new main"
    Note right of WC: Working copy now at new commit
    
    Dev->>WC: Edit files (file1.js, file2.css)
    WC-->>WC: Files automatically staged
    Note right of WC: No 'git add' needed
    
    Dev->>+Repo: jj describe -m "Add user authentication"
    Repo-->>WC: Update commit message
    Repo->>OpLog: Record: "jj describe"
    
    Dev->>WC: Continue editing files
    WC-->>WC: Changes auto-committed to @
    
    Dev->>+Repo: jj bookmark create feature-auth
    Repo-->>Repo: Create bookmark pointing to @
    Repo->>OpLog: Record: "jj bookmark create"
    
    Dev->>+Repo: jj rebase -d main
    Repo-->>Repo: Move current commit to main
    Repo-->>WC: Update working copy
    Repo->>OpLog: Record: "jj rebase"
    Note right of Repo: Automatic conflict resolution if needed
    
    Dev->>+Repo: jj git push --bookmark feature-auth
    Repo-->>Repo: Export to Git remote
    Repo->>OpLog: Record: "jj git push"
    
    Note over Dev,OpLog: All operations are reversible via operation log!
Loading

Check Your Understanding: Tutorial

Question 1: After running jj git init --colocate in an existing Git repo, what additional step is needed to access Git's history in jj?

Click to reveal answer

Run jj git import to import the existing Git history as jj commits and bookmarks.

Question 2: When you run jj new main and then edit files, where are those changes stored?

Click to reveal answer

The changes are automatically committed to the new working-copy commit (@) that was created based on main. No explicit commit command is needed.

Question 3: If you run jj new some-feature after making changes, what happens to your uncommitted work?

Click to reveal answer

jj automatically commits your changes to the previous working-copy commit before switching to the new commit. You never lose work when switching commits.

Question 4: How does jj handle conflicts differently from Git during a rebase operation?

Click to reveal answer

jj stores conflicts as first-class objects within commits rather than blocking the operation. You can continue working and resolve conflicts later, or even commit conflicted states.

Question 5: What's the command equivalent to git push origin feature-branch in jj?

Click to reveal answer

jj git push --bookmark feature-branch (assuming you've created a bookmark named feature-branch pointing to your changes).

Reference: Essential Commands

Repository Operations

  • jj init --git - Create new jj repo with Git backend
  • jj git init --colocate - Add jj to existing Git repo
  • jj status - Show working copy status
  • jj log - View commit history

Commit Operations

  • jj new [REVISION] - Create new commit (default: current commit)
  • jj edit REVISION - Switch to editing specific commit
  • jj describe [-r REVISION] [-m MESSAGE] - Change commit description
  • jj abandon REVISION - Remove commits from history

History Manipulation

  • jj rebase -r REVISION -d DESTINATION - Move commits
  • jj squash - Merge current commit into parent
  • jj split - Split commit into multiple commits
  • jj duplicate REVISION - Create copy of commits

Bookmark Management

  • jj bookmark create NAME [REVISION] - Create new bookmark
  • jj bookmark set NAME REVISION - Move bookmark to commit
  • jj bookmark list - Show all bookmarks
  • jj bookmark delete NAME - Remove bookmark

Git Integration

  • jj git fetch [--remote REMOTE] - Fetch from Git remote
  • jj git push [--bookmark NAME] - Push to Git remote
  • jj git import - Import Git refs as bookmarks
  • jj git export - Export jj changes to underlying Git repo

Operation Log

  • jj operation log - View operation history
  • jj operation undo [OPERATION] - Undo operation
  • jj operation restore OPERATION - Restore to specific operation

Resources

Official Documentation

Written Tutorials

Video Tutorials

Note: Video URLs are current as of August 14, 2025, and may change over time.

For additional tutorials, search YouTube for "Jujutsu jj version control" or browse the official GitButler and GitHub channels.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment