cd /news/ai-tools/jujutsu-cheatsheet-for-llm-s-and-git… · home topics ai-tools article
[ARTICLE · art-20433] src=gist.github.com pub= topic=ai-tools verified=true sentiment=· neutral

Jujutsu "Cheatsheet" for LLM's and Git users

Jujutsu (jj) version 0.41+ defaults to "colocated" mode, which maintains a real `.git/` directory alongside `.jj/` for seamless interoperability with existing Git tools. Users must configure `.gitignore` before running `jj git init --colocate` to prevent build artifacts, secrets, and OS junk from being swept into the initial commit. The tool provides distinct commands for finalizing changes (`jj commit -m`) versus editing descriptions (`jj describe -m`), with the latter only renaming the current change rather than creating a new commit.

read9 min publishedJun 2, 2026

jj

can manage a brand-new repo or one that already has a .git

directory. The colocated mode is the most useful for interop — it keeps a real .git/

directory alongside .jj/

, so other tools (gh

, IDE git integrations, GitHub Actions checkout, pre-commit hooks) still work normally.

jj git init --colocate

jj git init --colocate

jj git clone --colocate <git-url> <dir>

jj git init --git-repo <path-to-git-repo> <name>

jj git colocation status
jj git colocation enable
jj git colocation disable

⚠️

Set up.gitignore

BEFORE runningjj git init --colocate

.jj

snapshots the working copy on every command, and anything not gitignored at init time gets swept into the initial change. Cleaning it up afterward is annoying — you have to abandon/squash and re-snapshot, and if you've already pushed, the bad blobs live in the remote history. Common offenders to ignore first: build output dirs (node_modules/

,target/

,build/

,dist/

), secrets (.env

, credentials files), OS junk (.DS_Store

,Thumbs.db

), editor swap/backup files, and large binary artifacts.If you've already done the init without ignoring something, see

Undo an Accidental Working-Copy Snapshotbelow — the recipe is.gitignore

the path first, thenjj file untrack

.

jj config set --user user.name "Your Name"
jj config set --user user.email you@example.com

jj config edit --user
jj config edit --repo
jj config edit --workspace
jj commit -m "Commit message"

jj describe -m "New commit message"

jj edit @

jj new

⚠️

Common pitfall: usingjj describe -m

between push cycles when you meantjj commit -m

.describe

only renames the current change — subsequent edits stack onto the same change, and successivedescribe

/push cycles sideways-overwrite the same commit on origin under different messages while accumulating diff. Looks like N separate commits in your terminal scrollback, but only one commit exists in git history. Usejj commit -m

whenever you want the current change to be done and a fresh empty change ready for the next feature.

jj status

jj log

jj log -n 5

jj diff

jj diff --from <rev1> --to <rev2>

jj diff -r <rev>
jj config set --repo snapshot.auto-track "none()"

jj file track <paths>
jj file untrack <paths>
jj bookmark list

jj bookmark create <name>

jj bookmark create <name> -r @

jj bookmark create <name> && jj edit <name>

jj bookmark set <name> <revision>

jj bookmark set <name> @
jj bookmark set <name> <revision> --allow-backwards

jj bookmark track <name> --remote=<remote>
jj bookmark list --remote <remote>
jj bookmark list --all-remotes                # show everything (local + every remote)

Bookmarks are jj's branch equivalent; there is no "current" bookmark. Bookmarks do not move when you create new commits, but they follow rewrites.

jj git fetch

jj git fetch --remote <name>

jj rebase -d <bookmark>@<remote>

jj git export

jj git push

jj git push -b <bookmark_name>

jj git push --change @

jj git push --named myfeature=@

jj git push -b <bookmark_name> --allow-empty-description

jj git push --remote <name> -b <bookmark_name>

jj git import

jj git remote list
jj git remote add <name> <url>

There is no jj git pull

; use jj git fetch

  • jj rebase -d <bookmark>@<remote>

(or merge).

Set default remotes in .jj/repo/config

so plain jj git fetch

or jj git push

pick the expected remote:

[git]
fetch = "origin"
push = "origin"
jj git remote list
jj git remote add origin <ssh-url>

git switch -c <branch>
jj git export

Notes:

  • In a colocated repo, jj git push

uses jj's remote list, not git's. Add the remote in jj or set[git] fetch/push

in.jj/repo/config

. - If you already have git remotes, copy the SSH URL from git remote -v

intojj git remote add

.

  • Run jj git fetch

to bring down the latest remote refs. - Use jj rebase -d <bookmark>@<remote>

(or merge) so your commits sit on the desired remote tip. - In colocated workspaces, jj auto-imports/exports on every command; in non-colocated workspaces, use jj git export

after jj changes andjj git import

after git changes. - Push with jj git push -b <bookmark>

— new bookmarks are auto-tracked on push in jj 0.41+; for one-shot WIP/PR,jj git push --change @

auto-creates apush-<changeid>

bookmark and pushes it. - If you moved refs in Git directly, mirror those moves back into jj with jj git import

.

@

  • Current working copy@-

  • Parent of current working copy@--

  • Grandparent of current working copy<bookmark>@<remote>

  • Remote-tracking bookmark (e.g.,main@origin

)<commit_id>

  • Specific commit by ID (prefix is enough to be unique)<change_id>

  • Change ID (shown at the start ofjj log

, stable across rewrites)<bookmark_name>

  • Points to commit with that bookmark
jj new
jj squash --from @ --into @-
jj bookmark create feature-branch

jj commit -m "Start work on feature"
jj squash --from <rev> --into <target>
jj rebase -s <start>..<end> -d <target>
jj status

jj resolve <file_path>

jj commit -m "Resolved conflicts"
jj op log

jj undo
jj redo

jj op revert <operation_id>
jj op restore <operation_id>

jj auto-snapshots all non-ignored working-copy files into @

on every command. Colocating a repo (jj git init --colocate

) or running any jj command while build caches / vendored deps / scratch files are still untracked will pull that junk into your change. Two ways to back it out:

echo 'some-build-dir/' >> .gitignore
jj file untrack some-build-dir scratch some-cache.bin

jj undo                      # revert the most recent op
jj op restore <operation_id> # rewind to a known-good op (see `jj op log`)

Caveat: jj undo

/ jj op restore

alone will not keep untracked files out — the next jj command re-snapshots them. For stray untracked files the durable fix is always gitignore + jj file untrack (or delete the files). Tested on jj 0.41.

jj restore --from <rev> --into @ <paths>

jj revert -r <rev> -o <dest>
  • jj automatically snapshots your working copy before operations
  • There is no staging area; most jj

commands snapshot the working copy automatically - Use jj op log

+jj undo

/jj redo

orjj op revert

/jj op restore

to recover - Use jj abandon

to abandon a revision (use--retain-bookmarks

if needed) - Use descriptive bookmark names for easier navigation jj git

subcommands provide interop with git repositoriesjj log

shows the change ID first, then the commit ID

Git Command Jujutsu Equivalent
git add
Automatic with jj (or jj file track )
git commit
jj commit -m "message"
git commit --amend
jj new + jj squash --into @-
git checkout branch
jj edit branch_name
git branch
jj bookmark list
git branch name
jj bookmark create name
git push
jj git push
git pull
jj git fetch + jj rebase -d <bookmark>@<remote>
git log
jj log
git diff
jj diff
git rebase
jj rebase
git reset --hard HEAD~1
jj abandon @
git stash
Not needed (auto-snapshots)
── more in #ai-tools 4 stories · sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/jujutsu-cheatsheet-f…] indexed:0 read:9min 2026-06-02 ·