How to Use Jujutsu: The Beginner's Guide

CodexFuse Team · 2026-11-01T19:40:52.810Z · 18 min read min read

How to use Jujutsu (jj): the beginner's guide to the Git-compatible version-control system — install, config, colocate, describe, new, log, revsets, rebase, undo, and push to GitHub.

Learning how to use Jujutsu is the fastest way to escape git's staging-area grind. This jujutsu tutorial — a complete jj tutorial for git users switching over — is about Jujutsu the version-control system and jj its command-line tool — jj is the CLI, Jujutsu is the project, and saying that once makes everything else click. A quick disambiguation first: this is not Jujutsu Kaisen the anime, and it is not jujitsu the martial art — both crowd the search results for the exact keyword, so this guide is strictly for developers. Jujutsu is a free, open-source version-control system created by Martin von Zweigbergk that sits on top of your git repos as the local version-control layer, while GitHub stays the forge where code is hosted — two layers, no rivalry, and if you are new to the forge side, our GitHub beginner guide covers that layer. Jujutsu records your working copy as a commit automatically, gives every change a stable change ID that survives rewrites, rebases descendants for you, and lets you undo any operation — all verified in this guide against the current release, v0.46.0.

What Is Jujutsu, Exactly?

Jujutsu (jj) is a free, open-source version-control system that treats your working copy as the commit: every file edit is recorded automatically, so you never run git add again. Built by Martin von Zweigbergk on a git storage backend, it replaces git's staging area with a simpler model — change IDs that stay stable while you rewrite, automatic rebasing of descendant commits, first-class conflict handling, and an operation log that undoes any mistake with jj undo. It is licensed under Apache License 2.0, costs nothing, and has collected more than 32,000 stars on GitHub. It is still pre-1.0, so expect the occasional flag to move between monthly releases — but the core workflow has been stable for a long time.

How Is Jujutsu Different From Git?

The biggest difference is that Jujutsu treats your working copy as the commit: every edit is auto-recorded, so there is no staging area and no git add. Once you internalize that one idea, the rest of the tool reads naturally. A second difference is how commits are identified. Git gives you one identifier — the SHA hash — which changes every time you amend or rebase. Jujutsu gives you two: a change ID that stays stable while the change evolves, and a commit ID (the git SHA) underneath that changes with every rewrite. Always reference change IDs, because they survive amends, rebases, and splits. A third difference: Jujutsu has no "current branch" concept — its bookmarks do not advance automatically like git branches do, and a colocated repo leaves git's HEAD detached. Finally, rebasing and conflicts behave differently: descendants rebase automatically whenever you modify a commit, and conflicts never block an operation — they are recorded as first-class states you can walk away from and fix later. One related project worth naming once: Sapling is the other modern VCS in this lane — it is Meta's project, while Jujutsu keeps the git backend, so your existing git repos carry straight over.

Git habitJujutsu equivalentWhat changes
git add + git commitjj describeNo staging; the working copy is already the commit
git checkout -b featurejj newA new empty change on top, no branch to create
git commit --amendjj squashWorking-copy edits fold into the parent change
git rebase -ijj rebase -sDescendants rebase automatically; conflicts never block
git logjj logShows change IDs and commit IDs side by side
git branchjj bookmarkBookmarks never auto-advance; move them yourself
git reset --hard / reflog surgeryjj undo / jj op restoreUndoes operations, not commits; repeats walk further back
git pushjj git push --changeBare push only pushes bookmarks — tag the change first

What Do You Need Before Installing Jujutsu?

You need git version 2.42.0 or newer, because Jujutsu uses a git repo as its storage backend — jj will not run against an ancient git. Beyond that, you need a terminal and a code editor; jj opens your configured editor for descriptions, defaulting to nano on Linux/macOS and Notepad on Windows. If your git fundamentals are rusty, our Git beginner guide is the right companion read, since Jujutsu's whole design is a response to git's pain points.

How Do You Install Jujutsu?

Install Jujutsu with your platform's package manager — it is one command on every major operating system, and every command in this guide was verified against the current release, v0.46.0 (released 2026-10-07).

# macOS
brew install jj

# Windows
winget install jj-vcs.jj
# or: scoop install main/jj

# Arch Linux
sudo pacman -S jujutsu

# NixOS (released version)
nix run nixpkgs#jujutsu

# Debian/Ubuntu — no official apt repo; use the prebuilt musl binary,
# Homebrew, or cargo binstall:
cargo binstall --strategies crate-meta-data jj-cli

# Fedora — unofficial COPR repo (not listed in the official docs)
sudo dnf copr enable aldantanneo/jj-vcs
sudo dnf install jj-cli

Confirm the install with jj --version — you should see v0.46.0 or newer. The project ships monthly releases and is still pre-1.0, so if a flag below ever disagrees with your installed version, the official CLI reference at docs.jj-vcs.dev is the source of truth.

How Do You Set Up Jujutsu for the First Time?

Tell Jujutsu who you are, exactly like the first five minutes of git — your name and email go into every change you describe.

jj config set --user user.name "Your Name"
jj config set --user user.email "[email protected]"

Configuration is TOML. Your user config lives at ~/.config/jj/config.toml on Linux and macOS (respecting $XDG_CONFIG_HOME), and at %APPDATA%\jj\config.toml on Windows. The commands above write a [user] block with name and email keys. Two more keys worth setting early: ui.editor for the editor jj describe opens (overridable with the $JJ_EDITOR environment variable, falling back to $VISUAL then $EDITOR), and ui.pager for how long output is paged.

What Is the Safest Way to Try Jujutsu?

The safest way to try Jujutsu is jj git init --colocate inside an existing git repo — the zero-risk trial: your colleagues keep using git while you use jj, on the same files. Colocation means .jj/ and .git/ coexist in one working copy; jj auto-imports and auto-exports git state on every command, so git tools see a plain git repo and your teammates notice nothing. (In fact, colocation is now the default for both jj git init and jj git clone; pass --no-colocate if you want the git repo hidden inside .jj/ instead.) One caution for colocated repos, said once: jj leaves git's HEAD detached, so prefer read-only git commands and run git switch to a branch before any mutating git command — and know that an IDE's background git fetch can create divergent change IDs, which jj will show rather than hide. To start a brand-new repo instead, plain jj git init creates both .jj/ and .git/ from scratch, and you can toggle the arrangement later with jj git colocation enable or disable.

How Does the No-Staging Workflow Actually Work?

The no-staging workflow works like this: you edit files, and the change is already recorded — you never stage anything, you only describe what the change means. Here is the whole loop on a real file.

# Edit any file, then look at the working copy:
jj st
# Working copy: yourname@mpqrykyp "no description set"
# M src/app.js

# Give the change a message:
jj describe -m "Add retry logic to the payment form"

jj st (short for jj status) shows the working-copy change, its parent, a file summary, and any conflicts. jj describe attaches the message to the working-copy change — add -m to skip the editor. Notice what you did not do: no git add, no separate commit step. Your working copy is the commit, and describing it is the only ceremony left.

What Is jj new and Why Should You Use It for Every Task?

jj new starts a fresh, empty change on top of your current one — it is the jj replacement for git checkout -b, and the habit to build is one change per task. Run it after describing your last change, and you get a clean slate with the previous change as its parent. Because edits auto-record, "committing early and often" costs nothing: describe at logical stopping points, run jj new, and keep going. Need to go back and touch up an earlier change? jj edit <change-id> makes it the working copy again, and your later edits amend it directly — with descendants rebased for you automatically.

How Do You Read jj log and Change IDs?

jj log draws a graph where @ marks your working copy, and every entry shows a stable change ID next to its git commit ID — learn to read both columns and you can navigate any jj repo. The change ID is the concept that unlocks everything, so here it is plainly: a change ID is a randomly generated 16-byte identifier, shown as 12 lowercase letters in the k–z range (reverse hex), that stays the same while the change evolves through amends, rebases, and splits. The commit ID is the familiar git SHA, which changes with every rewrite. Prefer change IDs for every reference — jj edit mpqrykyp keeps working after rewrites that would invalidate a SHA.

Change IDCommit ID
What it isStable identity of a change as it evolvesGit SHA of one exact snapshot
Format12 letters, k–z range (e.g. mpqrykyp...)Hex hash (e.g. aef4df99...)
Survives amend/rebase?Yes — that is its entire purposeNo — any rewrite produces a new one
Use it forEveryday references: edit, rebase, describeInterop with git tools and forges
DivergenceShows as xyz?? when a change has divergent versionsN/A

In the default log template, immutable commits show as ◆, regular ones as ○, and your working copy as @ — so a glance tells you which commits you can still rewrite and which are history.

What Are Revsets and Which Ones Should You Learn First?

Jujutsu revsets are the query language for selecting commits — learn five expressions and you can point any command at exactly the commits you mean. If you have used git revision ranges, the syntax will feel familiar; the difference is that revsets are a full expression language with functions, not just A..B.

ExpressionSelectsBeginner use
@The working-copy commit"What am I on?"
@-Parent(s) of the working copy"What did I just finish?"
::@Ancestors of the working copy, including it"Everything leading here"
main..@Commits reachable from @ but not from main"What would I push?"
bookmarks()All bookmarked commits"Where are my named pointers?"
trunk()The configured mainline (e.g. main)Anchor for ranges
all() or ::Every visible commitFull-repo views in jj log -r

Use them anywhere a revision is expected: jj log -r 'main..@', jj rebase -s @-- -d main, jj abandon 'bookmarks()'. Quoting the expression protects it from your shell.

How Does jj rebase Handle Conflicts?

jj rebase moves your change and all of its descendants onto a new destination in one step — and conflicts never stop the rebase, they simply become first-class (conflict) commits you can walk away from and fix later. Say that once, because it inverts the git instinct that a conflict is an emergency. The command mirrors the intent: jj rebase -s <change> -d main rebases a change and its descendants (-s) onto main (-d), and the tutorial's own example reports "Rebased 2 commits" for a two-commit stack. When a rebase produces conflicts, jj st lists the unresolved paths and jj log marks the change (conflict); the working-copy files carry git-style conflict markers you can edit by hand, or run jj resolve for a merge tool. Finish with jj squash to fold the resolution into the change. And since modifying any commit auto-rebases its descendants, stacks of changes stay coherent while you edit the bottom of the pile.

How Does jj undo Work?

jj undo — the jujutsu undo command — reverses your last operation — not your last commit — and repeating it walks further back through everything you have done, which makes it the closest thing version control has to Ctrl+Z. This distinction matters, said once: if you run jj describe and then jj undo, the description is un-set, because the last operation was the describe. Every operation is recorded in the operation log — jj op log lists them, jj op restore <id> returns the repo to an earlier operation, and jj redo walks forward again. One guardrail: undo refuses to cross workspace boundaries by default (--allow-cross-workspace overrides it), so a shared working copy cannot silently roll back someone else's state.

How Do You Push Changes to GitHub?

Tag your change with a bookmark first, because a bare jj git push pushes only bookmarks and tags — run it with nothing to push and jj will report that nothing changed, which is the single most common beginner surprise. Bookmarks are jj's name for git branches, with one catch: they never auto-advance, so move them explicitly with jj bookmark move or jj bookmark set. The smoothest path for a single change skips bookmark management entirely: jj git push --change creates a push-<short-change-id> bookmark and pushes it, ready to become a pull request. For a named branch workflow, use jj git push -b feature-name. On the fetch side, jj git fetch records remote branches as remote-tracking bookmarks like main@origin — but new remote bookmarks are not imported locally by default (only the clone's default branch is), so track the ones you want with jj bookmark track main --remote=origin or set remotes.origin.auto-track-bookmarks = "*" in config. If your local and remote bookmarks disagree, jj log marks the bookmark main* until you reconcile. Pushes are force-with-lease style, checking the remote still matches the last-fetched position before updating it.

What If You Don't Want to Use GitHub at All?

You can push to any git remote, including a bare repository on your own server — Jujutsu does not care where the remote lives, because the remote protocol is plain git. A small VPS makes a fine private remote: create a bare repo with git init --bare, add it as a remote, and jj git push works exactly as it does against GitHub. If you have never rented a server before, our VPS hosting guide walks through what a VPS is and how to pick one.

What Mistakes Does Every Jujutsu Beginner Make?

Every git veteran trips on the same seven things when switching to jj — here they are, so you can skip the bruises.

MistakeWhy it happensDo this instead
Running git add out of habitMuscle memory from the staging areaThere is no staging — edit, then jj describe
Expecting a bookmark to follow youGit branches advance on commitBookmarks never auto-move — jj bookmark move explicitly
Bare jj git push, "nothing changed"Git pushes the current branchPush pushes bookmarks — use --change or -b
Panicking at a (conflict) commitGit stops the rebase and demands actionConflicts are first-class — walk away, jj resolve later
Mutating git commands in a colocated repoIt looks like a normal git repoPrefer read-only git commands; git switch before mutating
Describing after every micro-editTreating describe like commitEdits auto-record — describe once per logical change
Using jj undo like git resetExpecting commit-level undoUndo reverses the last operation — repeat to go further back

Where Do You Go From Here?

Practice the core loop until it is boring: jj new, edit, jj describe, jj git push --change. Then grow into revsets for navigation, jj split for carving clean changes out of messy ones, and jj op log whenever you want to see — or reverse — your own history. Keep one caveat in mind: Jujutsu is pre-1.0 and ships monthly, so flags occasionally move and the official docs at docs.jj-vcs.dev are the final word when your installed version disagrees with any guide, including this one.

Sources

  • Jujutsu official docs — Installation and setup (docs.jj-vcs.dev/latest/install-and-setup/) — per-OS install commands, config commands and file paths, git ≥ 2.42.0 requirement, Rust ≥ 1.97.1 for cargo install
  • Jujutsu official docs — Git compatibility (docs.jj-vcs.dev/latest/git-compatibility/) — colocated workspaces default, auto-import/export, detached HEAD, background-fetch divergence caution, conflict storage format
  • Jujutsu official docs — Bookmarks (docs.jj-vcs.dev/latest/bookmarks/) — bookmarks vs branches, no auto-advance, remote-tracking name@origin records, track and auto-track-bookmarks config, push semantics
  • Jujutsu official docs — Revsets (docs.jj-vcs.dev/latest/revsets/) — symbols and operators table (@, @-, ::, .., all(), bookmarks(), trunk(), change-ID offsets)
  • Jujutsu official docs — Operation log (docs.jj-vcs.dev/latest/operation-log/) — jj undo/redo, op log, op restore, op revert, cross-workspace default
  • Jujutsu official docs — Configuration (docs.jj-vcs.dev/latest/config/) — config file locations per OS, [user] TOML format, ui.editor/ui.pager, JJ_EDITOR/JJ_PAGER env overrides
  • Jujutsu official docs — Glossary (docs.jj-vcs.dev/latest/glossary/) — change ID definition (16 bytes, stable across rewrites, reverse-hex k–z)
  • Jujutsu official docs — Tutorial (docs.jj-vcs.dev/latest/tutorial/) — describe/new/log/edit/squash/abandon/conflicts walkthrough, "Rebased 2 commits" example
  • Jujutsu official docs — FAQ (docs.jj-vcs.dev/latest/faq/) — bare-push "nothing changed", bookmark-not-moving, change-ID references
  • Jujutsu official docs — CLI reference (docs.jj-vcs.dev/latest/cli-reference/) — jj st alias, describe -m, new, log template symbols (@, ◆, ○), split, undo, rebase -s/-r/-d
  • Jujutsu changelog (docs.jj-vcs.dev/latest/changelog/) — v0.46.0 released 2026-10-07, jj converge (0.45.0), undo cross-workspace default (0.46.0), git push multi-remote (0.46.0)
  • jj-vcs/jj GitHub repository (github.com/jj-vcs/jj) — Apache License 2.0, ~32,300 stars, automatic rebase and conflict-resolution design
  • FreshPorts — devel/jujutsu (freshports.org/devel/jujutsu) — 0.46.0_1 port update 2026-10-11, APACHE20 license
  • Christian Romney — Jujutsu usage gist (gist.github.com/christianromney/27fd1fca9e5f24ef24d9ed6c9eddda50) — Nov-2025-era install/config/colocate/working-copy walkthrough
  • Abhinav Sarkar — "How I use Jujutsu" (abhinavsarkar.net/posts/jj-usage/) — personal command list: colocate, new/describe/commit, rebase, revsets, op log
  • Alan West — "How jj fixes the Git workflow that's been wasting your time" (dev.to/alanwest/...) — git-pain-point workflow explainer: colocate, describe, new, fetch, push, team coexistence
  • DevelopersIO (Classmethod) — Jujutsu jj guide (dev.classmethod.jp/en/articles/jujutsu-jj-guide/) — Mar-2026 Homebrew install, config, colocate, Git-vs-jj comparison
  • Majid Jabrayilov — "Introducing Jujutsu VCS" (swiftwithmajid.com/2025/10/15/...) — Oct-2025 overview: init, working-copy model, squash, bookmarks, undo, abandon
  • Gyuri Horák — "Jujutsu VCS — short introduction" (horak.hu/posts/jj/) — design philosophy and backend separation (pre-0.10 era commands)
  • Andre Arko — "jj, part 1: what is it?" (andre.arko.net/2025/09/28/...) — fresh Nov-2026 multi-part series start, GitHub colocate workflow
  • Noor's Homelab — Jujutsu practical field guide (blog.noorshomelab.dev/guides/jujutsu-vcs-guide/) — May-2026 long-form guide: revsets, stacking, install notes

Frequently Asked Questions

Is Jujutsu a replacement for Git?

It replaces the git command-line workflow, not git itself — Jujutsu stores your history in a regular git repository as its backend, so forges, CI systems, and teammates on plain git all keep working. Think of it as a better interface to the same storage: you get the no-staging working-copy model, stable change IDs, and automatic rebases, while the repo underneath remains git. That is also why the jj vs git debate misses the point — you do not choose one storage or the other, you choose which CLI manages it.

What does "jj colocate" mean?

jj git init --colocate creates a workspace where Jujutsu's .jj/ directory and git's .git/ directory live side by side in the same working copy — this is the jujutsu colocate workflow. Jujutsu auto-imports and auto-exports git state on every command, so the git side always looks like a normal repo in detached HEAD — colleagues keep using git, IDEs keep working, and you get the full jj workflow. It is the recommended zero-risk way to trial Jujutsu on a real project, and it is now the default for both jj git init and jj git clone.

What is a change ID in Jujutsu?

A jujutsu change id is a randomly generated 16-byte identifier, displayed as 12 letters in the k–z range, that identifies a change as it evolves over time — through amends, rebases, and splits. It is the jj-native way to reference your work: unlike the git commit ID (the SHA), which changes with every rewrite, the change ID stays put, so jj edit <change-id> keeps working no matter how many times you have reworked the change. If a change ever diverges into two versions, jj marks it with ?? suffixes and the x/0, x/1 revset offsets let you address each version.

How do you undo a mistake in Jujutsu?

Run jj undo — it reverses your last operation, whatever it was, by restoring the repo to the operation's parent state. Repeat it to walk further back, and use jj redo to walk forward again. For anything older, jj op log lists every recorded operation and jj op restore <id> returns the repository to any of them. Remember that undo is operation-level: describing a change and then undoing will un-describe it, not delete the change.

Is Jujutsu ready for everyday use?

Yes, with one honest caveat: it is still pre-1.0 and experimental, shipping monthly releases, so flags and behaviors can move between versions — the project itself warns of work-in-progress features and workflow gaps (no annotated tag creation, no submodules, no Git LFS yet). That said, the core workflow is stable, the git backend means your data is never locked into an exotic format, and a growing community of developers uses it daily. Pin a version, skim the changelog on upgrade, and you will be fine.

Featured on Twelve Tools Launch Llama Tools Launch your MCP