{"slug": "jujutsu-cheatsheet-for-llm-s-and-git-users", "title": "Jujutsu \"Cheatsheet\" for LLM's and Git users", "summary": "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.", "body_md": "`jj`\n\ncan manage a brand-new repo or one that already has a `.git`\n\ndirectory. The **colocated** mode is the most useful for interop — it keeps a real `.git/`\n\ndirectory alongside `.jj/`\n\n, so other tools (`gh`\n\n, IDE git integrations, GitHub Actions checkout, pre-commit hooks) still work normally.\n\n```\n# Initialize a brand-new colocated repo in the current directory.\n# (--colocate is the default in jj 0.41+; the flag is harmless. Use --no-colocate to opt out.)\njj git init --colocate\n\n# Convert an existing git repo to be jj-managed (run inside the repo)\njj git init --colocate\n\n# Clone an existing remote as a colocated repo (colocation is the default;\n# use --no-colocate to disable)\njj git clone --colocate <git-url> <dir>\n\n# Create a jj repo backed by an existing Git repo at a different path\njj git init --git-repo <path-to-git-repo> <name>\n\n# Check or change colocation mode of an existing repo\njj git colocation status\njj git colocation enable\njj git colocation disable\n```\n\n⚠️\n\nSet up`.gitignore`\n\nBEFORE running`jj git init --colocate`\n\n.`jj`\n\nsnapshots 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/`\n\n,`target/`\n\n,`build/`\n\n,`dist/`\n\n), secrets (`.env`\n\n, credentials files), OS junk (`.DS_Store`\n\n,`Thumbs.db`\n\n), editor swap/backup files, and large binary artifacts.If you've already done the init without ignoring something, see\n\nUndo an Accidental Working-Copy Snapshotbelow — the recipe is`.gitignore`\n\nthe path first, then`jj file untrack`\n\n.\n\n```\n# Configure identity (jj uses --user instead of git's --global)\njj config set --user user.name \"Your Name\"\njj config set --user user.email you@example.com\n\n# Edit config by scope\njj config edit --user\njj config edit --repo\njj config edit --workspace\n# Finalize the current change AND open a new empty change on top.\n# This is the right tool for landing a sequence of separate commits.\njj commit -m \"Commit message\"\n\n# Edit JUST the description of the current change (no finalize, no new change).\n# After this, further edits keep modifying the same change.\njj describe -m \"New commit message\"\n\n# Set the working-copy revision (for amend-style edits,\n# prefer `jj new` + `jj squash`)\njj edit @\n\n# Create a new empty change on top of current commit (or a specified revision)\njj new\n```\n\n⚠️\n\nCommon pitfall: using`jj describe -m`\n\nbetween push cycles when you meant`jj commit -m`\n\n.`describe`\n\nonly renames the current change — subsequent edits stack onto the same change, and successive`describe`\n\n/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. Use`jj commit -m`\n\nwhenever you want the current change to be done and a fresh empty change ready for the next feature.\n\n```\n# Show repository status (similar to git status)\njj status\n\n# View detailed log\njj log\n\n# View last N commits\njj log -n 5\n\n# Show diff of current working copy\njj diff\n\n# Show diff between specific revisions\njj diff --from <rev1> --to <rev2>\n\n# Show diff between a revision and its parent(s)\njj diff -r <rev>\n# New files are auto-tracked by default (except ignored files)\n# Configure with snapshot.auto-track (example disables auto-track)\njj config set --repo snapshot.auto-track \"none()\"\n\n# Manually track or untrack paths\njj file track <paths>\njj file untrack <paths>\n# List all bookmarks (similar to git branches)\njj bookmark list\n\n# Create a bookmark (similar to git branch)\njj bookmark create <name>\n\n# Point a bookmark at your current work (mirrors git checkout -b <name>)\njj bookmark create <name> -r @\n\n# Create and switch to a bookmark (similar to git checkout -b)\njj bookmark create <name> && jj edit <name>\n\n# Update a bookmark to point to another revision (forward only by default)\njj bookmark set <name> <revision>\n\n# Move a bookmark (often used to update a bookmark to point to current working copy)\n# Use --allow-backwards to move a bookmark backwards or sideways:\njj bookmark set <name> @\njj bookmark set <name> <revision> --allow-backwards\n\n# Track or inspect remote bookmarks\njj bookmark track <name> --remote=<remote>\njj bookmark list --remote <remote>\njj bookmark list --all-remotes                # show everything (local + every remote)\n```\n\nBookmarks are jj's branch equivalent; there is no \"current\" bookmark. Bookmarks do not move when you create new commits, but they follow rewrites.\n\n``` python\n# Fetch remote refs/commits and import them into jj\njj git fetch\n\n# Target a specific remote (mirrors git fetch <name>)\njj git fetch --remote <name>\n\n# After fetch, rebase or merge onto the desired remote bookmark\njj rebase -d <bookmark>@<remote>\n\n# Export your current jj view into the underlying Git repo\njj git export\n\n# Push changes to GitHub (defaults to tracked bookmarks)\njj git push\n\n# Push a specific bookmark (mirrors git push origin <branch>).\n# In jj 0.41+, new bookmarks are auto-tracked on push — no --allow-new needed.\n# (--allow-new still works but is deprecated; tracking can also be auto-configured via\n# remotes.<name>.auto-track-bookmarks.)\njj git push -b <bookmark_name>\n\n# Push a commit by change-id — auto-creates a `push-<changeid>` bookmark.\n# Ideal for one-shot WIP / \"open a PR for this change\" workflows.\njj git push --change @\n\n# Push a new bookmark under an explicit name without creating it locally first\njj git push --named myfeature=@\n\n# Push a commit that has no description yet (otherwise rejected).\n# Default: jj refuses to push commits with empty descriptions.\njj git push -b <bookmark_name> --allow-empty-description\n\n# Push to a specific remote\njj git push --remote <name> -b <bookmark_name>\n\n# After using regular git commands, re-import to update jj's view\njj git import\n\n# Inspect or add remotes\njj git remote list\njj git remote add <name> <url>\n```\n\nThere is no `jj git pull`\n\n; use `jj git fetch`\n\n+ `jj rebase -d <bookmark>@<remote>`\n\n(or merge).\n\nSet default remotes in `.jj/repo/config`\n\nso plain `jj git fetch`\n\nor `jj git push`\n\npick the expected remote:\n\n```\n[git]\nfetch = \"origin\"\npush = \"origin\"\n# jj does NOT use git's remotes unless configured in jj:\njj git remote list\njj git remote add origin <ssh-url>\n\n# If git shows \"HEAD (no branch)\", reattach:\ngit switch -c <branch>\n# then export jj state into git (if needed)\njj git export\n```\n\nNotes:\n\n- In a colocated repo,\n`jj git push`\n\nuses jj's remote list, not git's. Add the remote in jj or set`[git] fetch/push`\n\nin`.jj/repo/config`\n\n. - If you already have git remotes, copy the SSH URL from\n`git remote -v`\n\ninto`jj git remote add`\n\n.\n\n- Run\n`jj git fetch`\n\nto bring down the latest remote refs. - Use\n`jj rebase -d <bookmark>@<remote>`\n\n(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\n`jj git export`\n\nafter jj changes and`jj git import`\n\nafter git changes. - Push with\n`jj git push -b <bookmark>`\n\n— new bookmarks are auto-tracked on push in jj 0.41+; for one-shot WIP/PR,`jj git push --change @`\n\nauto-creates a`push-<changeid>`\n\nbookmark and pushes it. - If you moved refs in Git directly, mirror those moves back into jj with\n`jj git import`\n\n.\n\n`@`\n\n- Current working copy`@-`\n\n- Parent of current working copy`@--`\n\n- Grandparent of current working copy`<bookmark>@<remote>`\n\n- Remote-tracking bookmark (e.g.,`main@origin`\n\n)`<commit_id>`\n\n- Specific commit by ID (prefix is enough to be unique)`<change_id>`\n\n- Change ID (shown at the start of`jj log`\n\n, stable across rewrites)`<bookmark_name>`\n\n- Points to commit with that bookmark\n\n```\n# Create a new change, then squash it into the previous commit\njj new\n# ... make changes ...\njj squash --from @ --into @-\n# Create a new branch\njj bookmark create feature-branch\n\n# Create a new commit (automatically on the new branch)\njj commit -m \"Start work on feature\"\n# Squash one revision into another\njj squash --from <rev> --into <target>\n# Rebase a range of commits onto a target\njj rebase -s <start>..<end> -d <target>\n# View conflicted files\njj status\n\n# Resolve conflicts with merge tool\njj resolve <file_path>\n\n# After resolving, continue with the operation\njj commit -m \"Resolved conflicts\"\n# Inspect the operation log\njj op log\n\n# Undo/redo the most recent operation(s)\njj undo\njj redo\n\n# Revert or restore a specific operation from the log\njj op revert <operation_id>\njj op restore <operation_id>\n```\n\njj auto-snapshots **all** non-ignored working-copy files into `@`\n\non every\ncommand. Colocating a repo (`jj git init --colocate`\n\n) or running any jj command\nwhile build caches / vendored deps / scratch files are still untracked will\npull that junk into your change. Two ways to back it out:\n\n```\n# BEST for untracked junk: ignore it, then untrack it (files stay on disk).\n# `jj file untrack` refuses unless the path is gitignored, so ignore it first.\necho 'some-build-dir/' >> .gitignore\njj file untrack some-build-dir scratch some-cache.bin\n\n# Operation-log rewind: undoes the LAST operation (rebase/squash/describe/etc.).\njj undo                      # revert the most recent op\njj op restore <operation_id> # rewind to a known-good op (see `jj op log`)\n```\n\nCaveat: `jj undo`\n\n/ `jj op restore`\n\nalone will **not** keep untracked files out —\nthe next jj command re-snapshots them. For stray untracked files the durable fix\nis always *gitignore + jj file untrack* (or delete the files). Tested on jj 0.41.\n\n```\n# Restore paths from another revision into the working copy\njj restore --from <rev> --into @ <paths>\n\n# Apply the inverse of a revision onto a destination\njj revert -r <rev> -o <dest>\n```\n\n- jj automatically snapshots your working copy before operations\n- There is no staging area; most\n`jj`\n\ncommands snapshot the working copy automatically - Use\n`jj op log`\n\n+`jj undo`\n\n/`jj redo`\n\nor`jj op revert`\n\n/`jj op restore`\n\nto recover - Use\n`jj abandon`\n\nto abandon a revision (use`--retain-bookmarks`\n\nif needed) - Use descriptive bookmark names for easier navigation\n`jj git`\n\nsubcommands provide interop with git repositories`jj log`\n\nshows the change ID first, then the commit ID\n\n| Git Command | Jujutsu Equivalent |\n|---|---|\n`git add` |\nAutomatic with jj (or `jj file track` ) |\n`git commit` |\n`jj commit -m \"message\"` |\n`git commit --amend` |\n`jj new` + `jj squash --into @-` |\n`git checkout branch` |\n`jj edit branch_name` |\n`git branch` |\n`jj bookmark list` |\n`git branch name` |\n`jj bookmark create name` |\n`git push` |\n`jj git push` |\n`git pull` |\n`jj git fetch` + `jj rebase -d <bookmark>@<remote>` |\n`git log` |\n`jj log` |\n`git diff` |\n`jj diff` |\n`git rebase` |\n`jj rebase` |\n`git reset --hard HEAD~1` |\n`jj abandon @` |\n`git stash` |\nNot needed (auto-snapshots) |", "url": "https://wpnews.pro/news/jujutsu-cheatsheet-for-llm-s-and-git-users", "canonical_source": "https://gist.github.com/pmarreck/03c006fb2f5b70dcc35bdadb2c101a12", "published_at": "2026-06-02 20:47:15+00:00", "updated_at": "2026-06-03 13:45:21.866227+00:00", "lang": "en", "topics": ["ai-tools"], "entities": ["Jujutsu", "Git", "GitHub"], "alternates": {"html": "https://wpnews.pro/news/jujutsu-cheatsheet-for-llm-s-and-git-users", "markdown": "https://wpnews.pro/news/jujutsu-cheatsheet-for-llm-s-and-git-users.md", "text": "https://wpnews.pro/news/jujutsu-cheatsheet-for-llm-s-and-git-users.txt", "jsonld": "https://wpnews.pro/news/jujutsu-cheatsheet-for-llm-s-and-git-users.jsonld"}}