Are you a developer who’s ever felt bogged down by the complexities of Git? Do you wish for a version control system that makes iterative development, refactoring, and collaboration feel more natural and less error-prone? You’re in the right place!

Welcome to Jujutsu, often abbreviated as jj, a modern, Git-compatible version control system designed to streamline your development workflow. In this guide, we’ll embark on a journey to master jj, starting with its fundamental concepts and practical applications. This first chapter introduces you to the core philosophy of Jujutsu, guides you through its installation, and helps you take your very first steps.

By the end of this chapter, you’ll understand jj’s unique approach to version control, have it installed on your system, and be ready to create and manage your first commits. We assume you’re already familiar with basic version control concepts like commits, branches, and merging, ideally from experience with Git or Mercurial.

Understanding Jujutsu’s Core Philosophy

Jujutsu (jj) is a new generation of version control system that aims to combine the best aspects of Git and Mercurial while introducing powerful new concepts. It’s built to be Git-compatible, meaning you can use jj on existing Git repositories and interact seamlessly with Git remotes like GitHub or GitLab. However, jj isn’t just a Git wrapper; it fundamentally rethinks how you interact with your code history.

Why Jujutsu? Solving Common VCS Pain Points

jj was created to address several common frustrations developers face with traditional VCS, especially Git. Understanding these pain points helps clarify why jj’s design choices are so impactful.

  • Complex Staging Area: Git’s staging area (index) can be powerful but often adds an extra mental burden, especially for beginners or when making quick changes. It requires an explicit git add step before committing.
  • Immutable History Mindset: Git’s strong emphasis on immutable history, while good for integrity, can make refactoring and cleaning up your local commits cumbersome. Operations like rebase -i are powerful but require careful manual intervention and understanding of detached HEAD states.
  • Branch Management Overload: Traditional branches in Git can become unwieldy, leading to “branch spaghetti” and confusion about which branch is tracking what. This often hinders linear, iterative development.
  • Lack of Robust Undo: While Git has reflog, it’s not a general-purpose, easy-to-use undo mechanism for most operations. Recovery often involves digging through the reflog manually.

jj tackles these issues head-on, offering a fresh perspective that prioritizes simplicity, power, and safety.

The Jujutsu Paradigm Shift: Core Concepts

To truly appreciate jj, it’s crucial to understand its core differentiating concepts. These aren’t just new features; they represent a fundamental shift in how you think about version control, moving from a rigid, “snapshot-based” model to a more fluid, “change-based” one.

The Working Copy as a Commit

In Git, your working directory, the staging area, and your commits are distinct entities. You modify files, git add them to the staging area, and then git commit to create a new snapshot. This multi-step process can sometimes feel disconnected from the actual work.

jj simplifies this by treating your entire working copy as a commit itself. What does this mean in practice?

  • There’s no separate staging area. Any change in your working directory is implicitly part of the “working copy commit.”
  • When you run jj commit, jj creates a new commit that contains all changes from your current working directory. Then, it automatically moves the “working copy commit” to be a child of this new, just-created commit.

This model often feels more intuitive, as your working directory is always in a committable state, embodying the current “in-progress” commit. You don’t need to explicitly stage changes; just save your files, and jj sees them as part of your active work.

Mutable History by Design

One of jj’s most powerful features is its embrace of mutable history. Unlike Git, where changing past commits is seen as an advanced operation (and potentially dangerous if not handled carefully, especially when interacting with shared history), jj makes it a central, safe, and easy part of your local workflow.

Why is this important? It empowers you to refine your work and maintain a clean, logical history before sharing it with others. This means you can effortlessly:

  • Edit previous commits: Fix a typo, add a missing file, or refine a commit message.
  • Reorder commits: Arrange your changes in a more logical sequence.
  • Split a single commit into multiple: Break down a large commit into smaller, more reviewable chunks.
  • Combine multiple commits into one: Squash several related commits into a single, cohesive change.

jj encourages you to iterate and refine your local history before sharing it, leading to cleaner, more logical commit graphs. This flexibility is a game-changer for iterative development and code review preparation.

The Operation Log: Your Safety Net

With great power comes great responsibility, but jj provides a crucial safety net: the operation log. Every single action you perform with jj – every commit, rebase, undo, or update – is recorded in this log. This is a fundamental difference from Git’s reflog, which primarily tracks where your branch pointers have been. The jj operation log tracks every command executed.

This log gives you unparalleled confidence to experiment freely with jj’s mutable history features, knowing you can always revert to a previous state of your repository.

  • Undo any operation: Made a mistake? Just jj undo. This command effectively reverses the last jj operation, restoring your repository to its state before that operation.
  • Redo an undone operation: Changed your mind after an undo? jj redo will reapply the undone operation.
  • Explore your command history: The jj op log command allows you to see what you did and when, providing a transparent audit trail of your actions.

📌 Key Idea: The operation log is Jujutsu’s powerful safety net, allowing you to undo and redo any operation, making mutable history fearless. This significantly reduces the cognitive load of complex refactoring.

Installing Jujutsu (as of 2026-05-19)

Let’s get jj up and running on your system! Jujutsu is actively developed, and its latest stable version often includes significant improvements. As of May 19, 2026, we’ll aim for a recent stable release. For consistency and stability, let’s target Jujutsu version 0.20.0 or later, which reflects current stable releases. Always check the official GitHub releases page for the absolute latest version and release notes.

You can install jj in several ways depending on your operating system.

macOS Installation

The recommended way to install jj on macOS is using Homebrew, a popular package manager.

brew install jujutsu

Linux Installation

For Linux, you can often find pre-built binaries or install via cargo. Using cargo is generally recommended for the latest versions or if pre-built packages aren’t readily available for your distribution.

First, ensure you have Rust and Cargo installed. If not, follow the official installation instructions at rust-lang.org.

Then, install jj using cargo:

cargo install jj

Pre-built Binaries (Alternative)

You can also download pre-built binaries from the official Jujutsu GitHub releases page. Look for the .tar.gz archive for your architecture (e.g., jj-v0.20.0-x86_64-unknown-linux-gnu.tar.gz), extract it, and place the jj executable in a directory that’s included in your system’s PATH.

Windows Installation

For Windows, pre-built binaries are typically the easiest route.

Download the appropriate .zip file (e.g., jj-v0.20.0-x86_64-pc-windows-msvc.zip) from the official Jujutsu GitHub releases page. Extract the jj.exe executable and place it in a directory that’s included in your system’s PATH environment variable.

Verify Your jj Installation

After installation, open a new terminal or command prompt and run the following command to check if jj is correctly installed and accessible:

jj --version

You should see output similar to this (the exact version number might differ if you installed a newer release):

jj 0.20.0

If you see the version number, congratulations! jj is ready to go. If not, double-check your installation steps, especially ensuring the jj executable is in your system’s PATH.

Getting Hands-On with Jujutsu: Your First Repository and Commit

Now that jj is installed, let’s dive in and experience its unique workflow by creating a new project and making our first commits. This section will walk you through the essential commands for daily use.

Step 1: Initialize Your First Jujutsu Repository

We’ll start by creating a new directory for our project and initializing a jj repository within it.

  1. Create a Project Directory: Open your terminal or command prompt and create a new directory for your project.

    mkdir my_jj_project
    cd my_jj_project
    
  2. Initialize the Jujutsu Repository: Inside your new project directory, run the jj init command.

    jj init
    

    You’ll see output confirming the initialization:

    Initialized empty Jujutsu repository in my_jj_project/.jj
    

    This command creates a .jj directory inside your project, similar to Git’s .git directory, where jj stores its internal data.

  3. Check the Status: Let’s see the current state of our newly initialized repository using jj status.

    jj status
    

    You should see something like this:

    Current working copy: 000000000000
    There is no Diff in the working copy
    

    000000000000 is jj’s special identifier for the “null” or “empty” commit. It represents the state before any actual changes have been committed. At this point, your working copy is empty and has no changes.

Step 2: Making Your First Change and Commit

It’s time to create some content and make our first jj commit! Remember, with jj, there’s no staging area. Your working directory is your current working copy commit.

  1. Create a File: Let’s create a simple README.md file using echo.

    echo "# My First Jujutsu Project" > README.md
    echo "This is a test project to learn Jujutsu." >> README.md
    
  2. Check Status Again: Now that we’ve made changes, let’s see what jj status reports.

    jj status
    

    Output:

    Current working copy: 000000000000
    Working copy has changes:
      A README.md
    

    Notice how jj immediately recognizes the new file and indicates that the “working copy has changes.” There’s no jj add command because your working copy is a commit; any changes are automatically part of that implicit working copy commit.

  3. View the Diff: You can see the changes in your working copy using jj diff. This is analogous to git diff.

    jj diff
    

    Output:

    diff --git a/README.md b/README.md
    new file mode 100644
    --- /dev/null
    +++ b/README.md
    @@ -0,0 +1,2 @@
    +# My First Jujutsu Project
    +This is a test project to learn Jujutsu.
    

    This diff output is very similar to what you’d see in Git, showing the new lines added.

  4. Commit Your Changes: Now, let’s create our first actual commit. In jj, the commit command takes all changes in your working directory and creates a new commit that is a child of your current working copy’s parent.

    jj commit -m "Initial project setup"
    

    Output:

    Created 6d5e1f706e22 (empty) (no description set)
    Replaced 000000000000 with 6d5e1f706e22 (empty) (no description set)
    Working copy now at 6d5e1f706e22 (empty) (no description set)
    

    What just happened?

    • jj created a new commit with a unique ID (e.g., 6d5e1f706e22). This is your actual commit, containing the README.md file.
    • The “working copy commit” then moved to become this new commit. This is the “working copy as a commit” in action.
    • The (empty) and (no description set) parts are internal details jj shows briefly because it creates the commit then applies the message and content. Don’t worry about them.
  5. Check Status After Commit: Let’s confirm the state of our repository after the commit.

    jj status
    

    Output:

    Current working copy: 6d5e1f706e22 Initial project setup
    There is no Diff in the working copy
    

    Now, jj status shows your working copy is associated with your new commit 6d5e1f706e22, and there are no further changes in your working directory. Perfect!

Step 3: Exploring Your History

Let’s see the history we’ve created and how jj presents it.

  1. View the Commit Log: The jj log command displays your repository’s history, similar to git log but with jj’s unique perspective.

    jj log
    

    Output (commit IDs will vary):

    @ 6d5e1f706e22 Initial project setup
    o 000000000000 (empty) (no description set)
    

    Here’s what you’re seeing:

    • @ 6d5e1f706e22 Initial project setup: This is your Initial project setup commit. The @ symbol is crucial – it indicates that this is the commit your working copy is currently on.
    • o 000000000000 (empty) (no description set): This is the “null” commit, the conceptual parent of your very first commit.

    Notice the linear, clean history. jj aims for this by default, simplifying the visual representation of your changes.

  2. Make Another Change and Commit: Let’s add another line to our README.md and commit it, observing how the history evolves.

    echo "This is the second line of the README." >> README.md
    jj commit -m "Add second line to README"
    

    Now, run jj log again:

    jj log
    

    Output (again, IDs will vary):

    @ 7a1b2c3d4e5f Add second line to README
    o 6d5e1f706e22 Initial project setup
    o 000000000000 (empty) (no description set)
    

    You can clearly see your two commits stacked on top of each other, with the working copy (@) pointing to the latest one. This “stacking” of commits is a core concept in jj that we’ll explore much more deeply in future chapters.

  3. Show a Specific Commit: You can view the contents of any specific commit using jj show <commit_id>. Let’s look at the Initial project setup commit. You can use a short prefix of the commit ID.

    jj show 6d5e1f706e22
    

    This command will display the files and their content as they were in that specific commit, allowing you to inspect past states of your project.

Mini-Challenge: Build a Small Feature Iteratively

Let’s put your new knowledge to the test and practice the jj workflow.

Challenge:

  1. Create a new file called features.txt with the content “Feature A: Initial idea”.
  2. Commit this change with a message like “feat: Add initial feature A idea”.
  3. Modify features.txt to add “Feature A: Refined details”.
  4. Commit this modification with a message like “feat: Refine feature A details”.
  5. Use jj log to observe your commit history, paying attention to the order and the working copy pointer.
  6. Use jj show on your first feature commit (the one adding “Initial idea”) to see its content without the refined details.

Hint: Remember, there’s no jj add. Just make your changes in the working directory and then jj commit.

What to observe/learn:

  • How jj automatically tracks all changes in your working copy, eliminating the staging area.
  • The linear progression and stacking of commits in jj log as you build a feature iteratively.
  • How jj show lets you easily inspect the exact content of any past commit.

Common Pitfalls & Troubleshooting for New jj Users

As you transition from Git to jj, you might encounter a few initial hiccups due to the fundamental differences in their models. Recognizing these common pitfalls can help you quickly adapt.

  1. Expecting a Staging Area (The jj add Reflex): The most common mistake for Git users is instinctively looking for an add command.
    • Pitfall: Trying to run jj add <file> or similar.
    • Why it happens: In Git, git add is essential to stage changes.
    • Solution: Remember, jj doesn’t have a separate staging area. All changes in your working directory are implicitly part of the current working copy commit. Just modify files and then jj commit. If you only want to commit some changes from your working directory, jj has powerful commands like jj split or jj amend -i (interactive) which we’ll cover in detail later.
  2. Misinterpreting jj commit’s Behavior: The commit command in jj behaves differently than in Git.
    • Pitfall: Thinking jj commit just moves a branch pointer.
    • Why it happens: In Git, git commit creates a commit and then moves the current branch pointer.
    • Solution: In jj, jj commit creates a new commit that is a child of your current working copy commit, and then it moves your working copy to point to this new commit. Think of jj commit as “capture my current working state as a new commit, and then continue working on top of it.” This subtle difference is key to jj’s mutable history model.
  3. Ignoring jj log’s Visual Cues: Especially when coming from Git, it’s easy to just skim jj log and miss its unique indicators.
    • Pitfall: Not understanding the @ symbol or the linear presentation.
    • Why it happens: Git’s log often shows complex branch graphs.
    • Solution: Make jj log your friend. Use it frequently to understand where your working copy (@) is positioned and how your commits are stacked. The linear, cleaner history is a feature, not a lack of information.

🧠 Important: jj’s philosophy is “commit early, commit often.” Because history is mutable and undo is easy with the operation log, you’re encouraged to save your work frequently without worrying about creating “messy” commits. You can always clean them up and refine them later before sharing. This encourages smaller, more focused changes.

Summary and What’s Next

In this first chapter, you’ve taken your initial steps into the world of Jujutsu, a powerful and intuitive version control system. You’ve installed jj and experienced its fundamental workflow.

Here’s a quick recap of the key takeaways:

  • Jujutsu’s Purpose: A modern, Git-compatible VCS designed to simplify development workflows and overcome common Git frustrations with its unique model.
  • Core Concepts:
    • The working copy as a commit, eliminating the need for a separate staging area.
    • Mutable history by design, making it easy and safe to refine your local commits.
    • The operation log, providing a robust undo/redo mechanism for every action, ensuring safety.
  • Installation: You successfully installed jj (targeting version 0.20.0 or later as of 2026-05-19) on your system.
  • First Steps: You initialized a jj repository, made changes, committed them, and explored your repository’s history using jj status, jj diff, jj commit, and jj log.
  • Common Pitfalls: We discussed the key mindset shifts required when moving from Git, particularly regarding the absence of a staging area and the unique behavior of jj commit.

You’re now equipped with the foundational knowledge to interact with jj and appreciate its core philosophy. In the next chapter, we’ll dive deeper into jj’s mutable history features, learning how to modify, reorder, and refine your commits with unparalleled ease. Get ready to experience true flexibility in your version control!

References


This page is AI-assisted and reviewed. It references official documentation and recognized resources where relevant.