Manage version control with Jujutsu (jj) — no staging area, immediate changes, smart rebasing. Use when navigating history, squashing, or pushing to Git remotes.
Scanned 9/7/2026
Install to Claude Code
npx -y skills add knoopx/pi --skill jj-core --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Jj Core?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/knoopx-jj-core)More formats (shields.io, HTML) on the badges page.
---
name: jj-core
description: "Manage version control with Jujutsu (jj) — no staging area, immediate changes, smart rebasing. Use when navigating history, squashing, or pushing to Git remotes."
token_cost: 220
related: [jj-hunk, conventional-commits, sem]
keywords: ["jujutsu", "jj", "rebase", "squash", "split", "push", "commit"]
requires_tools: [bash]
---
# Jujutsu
Git-compatible VCS with a different data model — no staging area, changes are immediate. Every file is tracked in the working copy as "changes" (like commits without parents).
> ⚠️ **Never use `git` for mutations in a jj repo** — it corrupts history. Allowed: `git log`, `git diff`, `git show`, `git blame`, `git grep`.
## Basic Workflow
Create a change, describe it, view history:
```bash
jj new # Start a new change (like working on a commit)
jj desc -m "feat: add login" # Write the message
jj log # View history — this is your main view command
jj diff # See what changed in working copy
```
Edit an existing change:
```bash
jj edit <change-id> # Switch to a specific change
# Make changes to files...
jj squash # Move new edits into the parent change
```
## Time Travel & Navigation
Jump to any point in history:
```bash
jj edit @- # Go to parent
jj next --edit # Go to child
jj edit <change-id> # Jump to specific change
jj new --before @ # Insert a new change before current
```
## Squash & Split Changes
Combine changes into one:
```bash
# Merge two changes together
jj squash -m "combined message"
# Split working copy into separate commits
jj split # Interactive — pick hunks to commit separately
```
Auto-move changes to relevant commits in a stack:
```bash
jj absorb # Smart squashing across mutable revisions
```
## Rebasing & Merging
Rebase changes onto another:
```bash
jj rebase -s @- -d main # Rebase current change onto main
jj rebase -d main -s ::@ # Rebase all descendants of @ onto main
```
Merge two changes:
```bash
jj new x yz -m "merge" # Create merge of x and yz
```
## Conflicts
Resolve interactively:
```bash
# Edit conflicted files, then continue
jj resolve
```
## Pushing to Git
Bookmarks are like branches. Track and push them:
```bash
jj bookmark create main -r @ # Create a bookmark at current change
jj git push --bookmark main # Push that bookmark
jj git fetch # Fetch from remote
jj bookmark track main@origin # Track a remote bookmark
```
## Useful Patterns
**Undo an operation:** `jj undo` — reverses the last jj command.
**Get git commit hash from jj change:**
```bash
jj log -T 'commit_id\n' -r @ # Full hash
jj log -T 'commit_id.short()\n' -r @ # Short hash
git rev-parse @ # Also works in colocated repos
```
**Operation history:** `jj op log` — see all jj operations.
## Template Syntax (`-T` / `--template`)
Templates use jj's own language — NOT JavaScript, NOT shell interpolation.
**String concatenation requires `concat()`:**
```bash
# ❌ WRONG — no implicit joining
jj log -r @ -T 'commit_id.short() description'
# ❌ WRONG — method chaining without concat
jj log -r @ -T 'change_id.short() " | " commit_id.short()'
# ✅ RIGHT — explicit concat
jj log -r @ -T 'concat(change_id.short(), " | ", description)'
```
**Common fields:** `change_id`, `commit_id`, `description`, `author`, `committer`, `signature`
**Field name is `description`, NOT `desc`:**
```bash
# ❌ WRONG — undefined field
jj log -r @ -T 'desc'
# ✅ RIGHT
jj log -r @ -T 'description'
```
**Double quotes for pipe alternation in bash:**
```bash
# ✅ RIGHT — double quotes around revision set with pipe
jj log -r "id1 | id2" -T 'concat(change_id.short(), "\n", description)'
# ❌ WRONG — single quotes don't expand variables and can nest incorrectly
jj log -r 'id1 | id2' -T 'description'
```
**After `jj desc`, the working copy (`@`) moves:**
```bash
# Always verify with the original change ID, not @
jj desc -r <change-id> -m "new description"
jj log --no-graph -r <change-id> -T 'concat(change_id.short(), " | ", description)'
```
## Common Pitfalls
- ❌ Use `@~1` → ✅ Use `@-` (parent)
- ❌ Use `a,b,c` for union → ✅ Use `a | b | c` (pipe, not comma)
- ❌ Use `jj changes` → ✅ Use `jj log` or `jj diff`
- ❌ Template: implicit string joining → ✅ Always use `concat(a, b)`
- ❌ Template: `desc` → ✅ Always use `description`
- ❌ Verify with `@` after `jj desc` → ✅ Always use original change ID
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!