Initial commit
This commit is contained in:
11
.claude-plugin/plugin.json
Normal file
11
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "jj",
|
||||||
|
"description": "Jujutsu (jj) version control system - a Git-compatible VCS with novel features. Use when working with jj repositories, managing stacked commits, needing automatic rebasing with first-class conflict handling, using revsets to select commits, or wanting enhanced Git workflows. Triggers on mentions of 'jj', 'jujutsu', change IDs, or operation log.",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": {
|
||||||
|
"name": "Alberto Leal"
|
||||||
|
},
|
||||||
|
"skills": [
|
||||||
|
"./"
|
||||||
|
]
|
||||||
|
}
|
||||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# jj
|
||||||
|
|
||||||
|
Jujutsu (jj) version control system - a Git-compatible VCS with novel features. Use when working with jj repositories, managing stacked commits, needing automatic rebasing with first-class conflict handling, using revsets to select commits, or wanting enhanced Git workflows. Triggers on mentions of 'jj', 'jujutsu', change IDs, or operation log.
|
||||||
288
SKILL.md
Normal file
288
SKILL.md
Normal file
@@ -0,0 +1,288 @@
|
|||||||
|
---
|
||||||
|
name: jj
|
||||||
|
description: Jujutsu (jj) version control system - a Git-compatible VCS with novel features. Use when working with jj repositories, managing stacked/dependent commits, needing automatic rebasing with first-class conflict handling, using revsets to select commits, or wanting enhanced Git workflows. Triggers on mentions of 'jj', 'jujutsu', change IDs, operation log, or jj-specific commands.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Jujutsu (jj) Version Control System
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Jujutsu is a powerful Git-compatible version control system that combines ideas from Git, Mercurial, Darcs, and adds novel features. It uses Git repositories as a storage backend, making it fully interoperable with existing Git tooling.
|
||||||
|
|
||||||
|
**Key differentiators from Git:**
|
||||||
|
- Working copy is automatically committed (no staging area)
|
||||||
|
- Conflicts can be committed and resolved later
|
||||||
|
- Automatic rebasing of descendants when commits change
|
||||||
|
- Operation log enables easy undo of any operation
|
||||||
|
- Revsets provide powerful commit selection
|
||||||
|
- Change IDs stay stable across rewrites (unlike commit hashes)
|
||||||
|
|
||||||
|
## When to Use This Skill
|
||||||
|
|
||||||
|
- User mentions "jj", "jujutsu", or "jujutsu vcs"
|
||||||
|
- Working with stacked/dependent commits
|
||||||
|
- Questions about change IDs vs commit IDs
|
||||||
|
- Revset queries for selecting commits
|
||||||
|
- Conflict resolution workflows in jj
|
||||||
|
- Git interoperability with jj
|
||||||
|
- Operation log, undo, or redo operations
|
||||||
|
- History rewriting (squash, split, rebase, diffedit)
|
||||||
|
- Bookmark management (jj's equivalent of branches)
|
||||||
|
|
||||||
|
## Key Concepts
|
||||||
|
|
||||||
|
### Working Copy as a Commit
|
||||||
|
|
||||||
|
In jj, the working copy is always a commit. Changes are automatically snapshotted:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# No need for 'git add' - changes are tracked automatically
|
||||||
|
jj status # Shows working copy state
|
||||||
|
jj diff # Shows changes in working copy commit
|
||||||
|
```
|
||||||
|
|
||||||
|
### Change ID vs Commit ID
|
||||||
|
|
||||||
|
- **Change ID**: Stable identifier that persists across rewrites (e.g., `kntqzsqt`)
|
||||||
|
- **Commit ID**: Hash that changes when commit is rewritten (e.g., `5d39e19d`)
|
||||||
|
|
||||||
|
Always prefer change IDs when referring to commits in commands.
|
||||||
|
|
||||||
|
### No Staging Area
|
||||||
|
|
||||||
|
Instead of staging, use these patterns:
|
||||||
|
- `jj split` - Split working copy into multiple commits
|
||||||
|
- `jj squash -i` - Interactively move changes to parent
|
||||||
|
- Direct editing with `jj diffedit`
|
||||||
|
|
||||||
|
### First-Class Conflicts
|
||||||
|
|
||||||
|
Conflicts are recorded in commits, not blocking operations:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj rebase -s X -d Y # Succeeds even with conflicts
|
||||||
|
jj log # Shows conflicted commits with ×
|
||||||
|
jj new <conflicted> # Work on top of conflict
|
||||||
|
# Edit files to resolve, then:
|
||||||
|
jj squash # Move resolution into parent
|
||||||
|
```
|
||||||
|
|
||||||
|
### Operation Log
|
||||||
|
|
||||||
|
Every operation is recorded and can be undone:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj op log # View operation history
|
||||||
|
jj undo # Undo last operation
|
||||||
|
jj op restore <op-id> # Restore to specific operation
|
||||||
|
```
|
||||||
|
|
||||||
|
## Essential Commands
|
||||||
|
|
||||||
|
| Command | Description | Git Equivalent |
|
||||||
|
|---------|-------------|----------------|
|
||||||
|
| `jj git clone <url>` | Clone a Git repository | `git clone` |
|
||||||
|
| `jj git init` | Initialize new repo | `git init` |
|
||||||
|
| `jj status` / `jj st` | Show working copy status | `git status` |
|
||||||
|
| `jj log` | Show commit history | `git log --graph` |
|
||||||
|
| `jj diff` | Show changes | `git diff` |
|
||||||
|
| `jj new` | Create new empty commit | - |
|
||||||
|
| `jj describe` / `jj desc` | Edit commit message | `git commit --amend` (msg only) |
|
||||||
|
| `jj edit <rev>` | Edit existing commit | `git checkout` + amend |
|
||||||
|
| `jj squash` | Move changes to parent | `git commit --amend` |
|
||||||
|
| `jj split` | Split commit in two | `git add -p` + multiple commits |
|
||||||
|
| `jj rebase` | Move commits | `git rebase` |
|
||||||
|
| `jj bookmark` / `jj b` | Manage bookmarks | `git branch` |
|
||||||
|
| `jj git fetch` | Fetch from remote | `git fetch` |
|
||||||
|
| `jj git push` | Push to remote | `git push` |
|
||||||
|
| `jj undo` | Undo last operation | `git reflog` + reset |
|
||||||
|
| `jj file annotate` | Show line origins | `git blame` |
|
||||||
|
|
||||||
|
## Common Workflows
|
||||||
|
|
||||||
|
### Starting a New Change
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Working copy changes are auto-committed
|
||||||
|
# When ready to start fresh work:
|
||||||
|
jj new # Create new commit on top
|
||||||
|
jj describe -m "message" # Set description
|
||||||
|
# Or combine:
|
||||||
|
jj new -m "Start feature X"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Editing a Previous Commit
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Option 1: Edit in place
|
||||||
|
jj edit <change-id> # Make working copy edit that commit
|
||||||
|
# Make changes, they're auto-committed
|
||||||
|
jj new # Return to working on new changes
|
||||||
|
|
||||||
|
# Option 2: Squash changes into parent
|
||||||
|
jj squash # Move all changes to parent
|
||||||
|
jj squash -i # Interactively select changes
|
||||||
|
jj squash <file> # Move specific file
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rebasing Commits
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Rebase current branch onto main
|
||||||
|
jj rebase -d main
|
||||||
|
|
||||||
|
# Rebase specific revision and descendants
|
||||||
|
jj rebase -s <rev> -d <destination>
|
||||||
|
|
||||||
|
# Rebase only specific revisions (not descendants)
|
||||||
|
jj rebase -r <rev> -d <destination>
|
||||||
|
|
||||||
|
# Insert commit between others
|
||||||
|
jj rebase -r X -A Y # Insert X after Y
|
||||||
|
jj rebase -r X -B Y # Insert X before Y
|
||||||
|
```
|
||||||
|
|
||||||
|
### Working with Bookmarks (Branches)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj bookmark list # List bookmarks
|
||||||
|
jj bookmark create <name> # Create at current commit
|
||||||
|
jj bookmark set <name> # Move bookmark to current commit
|
||||||
|
jj bookmark delete <name> # Delete bookmark
|
||||||
|
jj bookmark track <name>@<remote> # Track remote bookmark
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pushing Changes
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Push specific bookmark
|
||||||
|
jj git push --bookmark <name>
|
||||||
|
|
||||||
|
# Push change by creating auto-named bookmark
|
||||||
|
jj git push --change <change-id>
|
||||||
|
|
||||||
|
# Push all bookmarks
|
||||||
|
jj git push --all
|
||||||
|
```
|
||||||
|
|
||||||
|
### Resolving Conflicts
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# After a rebase creates conflicts:
|
||||||
|
jj log # Find conflicted commit (marked with ×)
|
||||||
|
jj new <conflicted> # Create commit on top
|
||||||
|
# Edit files to resolve conflicts
|
||||||
|
jj squash # Move resolution into conflicted commit
|
||||||
|
|
||||||
|
# Or use external merge tool:
|
||||||
|
jj resolve # Opens merge tool for each conflict
|
||||||
|
```
|
||||||
|
|
||||||
|
### Undoing Mistakes
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj undo # Undo last operation
|
||||||
|
jj op log # View operation history
|
||||||
|
jj op restore <op-id> # Restore to specific state
|
||||||
|
|
||||||
|
# View repo at past operation
|
||||||
|
jj --at-op=<op-id> log
|
||||||
|
```
|
||||||
|
|
||||||
|
## Revsets Quick Reference
|
||||||
|
|
||||||
|
Revsets select commits using a functional language:
|
||||||
|
|
||||||
|
| Expression | Description |
|
||||||
|
|------------|-------------|
|
||||||
|
| `@` | Working copy commit |
|
||||||
|
| `@-` | Parent of working copy |
|
||||||
|
| `x-` | Parents of x |
|
||||||
|
| `x+` | Children of x |
|
||||||
|
| `::x` | Ancestors of x (inclusive) |
|
||||||
|
| `x::` | Descendants of x (inclusive) |
|
||||||
|
| `x..y` | Ancestors of y not in ancestors of x |
|
||||||
|
| `x::y` | Commits between x and y (DAG path) |
|
||||||
|
| `bookmarks()` | All bookmark targets |
|
||||||
|
| `trunk()` | Main branch (main/master) |
|
||||||
|
| `mine()` | Commits by current user |
|
||||||
|
| `conflicts()` | Commits with conflicts |
|
||||||
|
| `description(text)` | Commits with matching description |
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
```bash
|
||||||
|
jj log -r '@::' # Working copy and descendants
|
||||||
|
jj log -r 'trunk()..@' # Commits between trunk and working copy
|
||||||
|
jj log -r 'mine() & ::@' # My commits in working copy ancestry
|
||||||
|
jj rebase -s 'roots(trunk()..@)' -d trunk() # Rebase branch onto trunk
|
||||||
|
```
|
||||||
|
|
||||||
|
## Git Interoperability
|
||||||
|
|
||||||
|
### Colocated Repositories
|
||||||
|
|
||||||
|
By default, `jj git clone` and `jj git init` create colocated repos where both `jj` and `git` commands work:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj git clone <url> # Creates colocated repo (default)
|
||||||
|
jj git clone --no-colocate <url> # Non-colocated (jj only)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using Git Commands
|
||||||
|
|
||||||
|
In colocated repos, Git changes are auto-imported. For non-colocated:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj git import # Import changes from Git
|
||||||
|
jj git export # Export changes to Git
|
||||||
|
```
|
||||||
|
|
||||||
|
### Converting Existing Git Repo
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd existing-git-repo
|
||||||
|
jj git init --colocate # Add jj to existing Git repo
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Edit config with `jj config edit --user`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[user]
|
||||||
|
name = "Your Name"
|
||||||
|
email = "your@email.com"
|
||||||
|
|
||||||
|
[ui]
|
||||||
|
default-command = "log" # Run 'jj log' when no command given
|
||||||
|
diff-editor = ":builtin" # Or "meld", "kdiff3", etc.
|
||||||
|
|
||||||
|
[revset-aliases]
|
||||||
|
'wip' = 'description(exact:"") & mine()' # Custom revset alias
|
||||||
|
```
|
||||||
|
|
||||||
|
## Advanced Topics
|
||||||
|
|
||||||
|
For comprehensive documentation, see:
|
||||||
|
- [references/revsets.md](references/revsets.md) - Complete revset reference
|
||||||
|
- [references/commands.md](references/commands.md) - Full command reference
|
||||||
|
- [references/git-comparison.md](references/git-comparison.md) - Git to jj command mapping
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
**"Working copy is dirty"** - Never happens in jj! Working copy is always a commit.
|
||||||
|
|
||||||
|
**Conflicts after rebase** - Normal in jj. Conflicts are recorded, resolve when convenient.
|
||||||
|
|
||||||
|
**Lost commits** - Use `jj op log` to find when commits existed, then `jj op restore`.
|
||||||
|
|
||||||
|
**Divergent changes** - Same change ID, different commits. Usually from concurrent edits:
|
||||||
|
```bash
|
||||||
|
jj log # Shows divergent commits
|
||||||
|
jj abandon <unwanted> # Remove one version
|
||||||
|
```
|
||||||
|
|
||||||
|
**Immutable commit error** - Can't modify trunk/tagged commits by default:
|
||||||
|
```bash
|
||||||
|
jj --ignore-immutable <command> # Override protection
|
||||||
|
```
|
||||||
61
plugin.lock.json
Normal file
61
plugin.lock.json
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||||
|
"pluginId": "gh:dashed/claude-marketplace:plugins/jj",
|
||||||
|
"normalized": {
|
||||||
|
"repo": null,
|
||||||
|
"ref": "refs/tags/v20251128.0",
|
||||||
|
"commit": "442bff07c9748b53336d513522bcb1c8eed5cd81",
|
||||||
|
"treeHash": "5a660cc6f4f6a2eaf497f7cc2c241b894d6400e6de1025f5fdb352703ab96b6e",
|
||||||
|
"generatedAt": "2025-11-28T10:16:05.918215Z",
|
||||||
|
"toolVersion": "publish_plugins.py@0.2.0"
|
||||||
|
},
|
||||||
|
"origin": {
|
||||||
|
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||||
|
"branch": "master",
|
||||||
|
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||||
|
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||||
|
},
|
||||||
|
"manifest": {
|
||||||
|
"name": "jj",
|
||||||
|
"description": "Jujutsu (jj) version control system - a Git-compatible VCS with novel features. Use when working with jj repositories, managing stacked commits, needing automatic rebasing with first-class conflict handling, using revsets to select commits, or wanting enhanced Git workflows. Triggers on mentions of 'jj', 'jujutsu', change IDs, or operation log.",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "README.md",
|
||||||
|
"sha256": "30721e1c4de730eb2d90af34b5ea780f70d7b822e093c898d76301501adfae46"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "SKILL.md",
|
||||||
|
"sha256": "392a27c60874f13ae43e313608e55f27900eba8553fa033a7ef310094c4a5220"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "references/git-comparison.md",
|
||||||
|
"sha256": "6109e4338d8da91ac1ac526aead4ab8155ff9cdc1633afdc61087aadfe49e840"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "references/commands.md",
|
||||||
|
"sha256": "6d9b9e31586313fe80be07ee7f6720d8657cb39eeb2297137ae8eeae0d9391c1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "references/configuration.md",
|
||||||
|
"sha256": "2f5d8566592a00d934d3486dc82112076960f77e8fcfebf62a09445d8ddcef75"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "references/revsets.md",
|
||||||
|
"sha256": "ae1d311521e7f31025e11dc6d3e2dbd2a3e6b70f9af5eebe3c975f80a77315c9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": ".claude-plugin/plugin.json",
|
||||||
|
"sha256": "9b7ee9cb24d7e4bd3cc615f3b7544404276eb4c0f3b79658c7d1a568d50bfb79"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dirSha256": "5a660cc6f4f6a2eaf497f7cc2c241b894d6400e6de1025f5fdb352703ab96b6e"
|
||||||
|
},
|
||||||
|
"security": {
|
||||||
|
"scannedAt": null,
|
||||||
|
"scannerVersion": null,
|
||||||
|
"flags": []
|
||||||
|
}
|
||||||
|
}
|
||||||
462
references/commands.md
Normal file
462
references/commands.md
Normal file
@@ -0,0 +1,462 @@
|
|||||||
|
# Commands Reference
|
||||||
|
|
||||||
|
Complete reference for jj commands and their options.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Repository Setup](#repository-setup)
|
||||||
|
- [Status and History](#status-and-history)
|
||||||
|
- [Creating and Editing Commits](#creating-and-editing-commits)
|
||||||
|
- [History Rewriting](#history-rewriting)
|
||||||
|
- [Bookmarks (Branches)](#bookmarks-branches)
|
||||||
|
- [Git Operations](#git-operations)
|
||||||
|
- [Operation Log](#operation-log)
|
||||||
|
- [File Operations](#file-operations)
|
||||||
|
- [Workspaces](#workspaces)
|
||||||
|
- [Configuration](#configuration)
|
||||||
|
|
||||||
|
## Repository Setup
|
||||||
|
|
||||||
|
### `jj git clone`
|
||||||
|
|
||||||
|
Clone a Git repository:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj git clone <url> [destination]
|
||||||
|
jj git clone --colocate <url> # Allow git commands (default)
|
||||||
|
jj git clone --no-colocate <url> # jj-only repo
|
||||||
|
jj git clone --branch <branch> # Clone specific branch
|
||||||
|
jj git clone --depth <n> # Shallow clone
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj git init`
|
||||||
|
|
||||||
|
Initialize a new repository:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj git init # New colocated repo (default)
|
||||||
|
jj git init --no-colocate # New jj-only repo
|
||||||
|
jj git init --git-repo <path> # Use existing git repo as backend
|
||||||
|
```
|
||||||
|
|
||||||
|
## Status and History
|
||||||
|
|
||||||
|
### `jj status` (alias: `st`)
|
||||||
|
|
||||||
|
Show working copy status:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj status
|
||||||
|
jj st [paths...] # Status for specific paths
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj log`
|
||||||
|
|
||||||
|
Show commit history:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj log # Default: mutable commits
|
||||||
|
jj log -r <revset> # Specific revisions
|
||||||
|
jj log -r '::' # All commits
|
||||||
|
jj log -n 10 # Limit to 10 commits
|
||||||
|
jj log -p # Show patches
|
||||||
|
jj log -s # Summary (files changed)
|
||||||
|
jj log --stat # Show diffstat
|
||||||
|
jj log --no-graph # Flat list, no graph
|
||||||
|
jj log --reversed # Oldest first
|
||||||
|
jj log -T <template> # Custom template
|
||||||
|
jj log [paths...] # Commits touching paths
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj show`
|
||||||
|
|
||||||
|
Show commit details:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj show # Current working copy
|
||||||
|
jj show <rev> # Specific revision
|
||||||
|
jj show -s # Summary only
|
||||||
|
jj show -p # Patch (default)
|
||||||
|
jj show --stat # Diffstat
|
||||||
|
jj show --git # Git-format diff
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj diff`
|
||||||
|
|
||||||
|
Show changes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj diff # Changes in working copy
|
||||||
|
jj diff -r <rev> # Changes in revision vs parent
|
||||||
|
jj diff --from <rev> # From specific revision
|
||||||
|
jj diff --to <rev> # To specific revision
|
||||||
|
jj diff --from <A> --to <B> # Between two revisions
|
||||||
|
jj diff -s # Summary
|
||||||
|
jj diff --stat # Diffstat
|
||||||
|
jj diff --git # Git format
|
||||||
|
jj diff --color-words # Word-level diff
|
||||||
|
jj diff [paths...] # Specific paths only
|
||||||
|
```
|
||||||
|
|
||||||
|
## Creating and Editing Commits
|
||||||
|
|
||||||
|
### `jj new`
|
||||||
|
|
||||||
|
Create a new commit:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj new # New commit on working copy parent
|
||||||
|
jj new <rev> # New commit on specific revision
|
||||||
|
jj new <A> <B> # Merge commit with multiple parents
|
||||||
|
jj new -m "message" # With description
|
||||||
|
jj new --no-edit # Don't make it working copy
|
||||||
|
jj new -A <rev> # Insert after revision
|
||||||
|
jj new -B <rev> # Insert before revision
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj describe` (alias: `desc`)
|
||||||
|
|
||||||
|
Edit commit description:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj describe # Edit working copy description
|
||||||
|
jj describe <rev> # Edit specific revision
|
||||||
|
jj describe -m "message" # Set message directly
|
||||||
|
jj describe --stdin # Read from stdin
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj edit`
|
||||||
|
|
||||||
|
Switch working copy to edit existing commit:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj edit <rev> # Edit specific revision
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj commit` (alias: `ci`)
|
||||||
|
|
||||||
|
Finalize working copy and create new commit:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj commit # Describe and create new
|
||||||
|
jj commit -m "message" # With message
|
||||||
|
jj commit -i # Interactive selection
|
||||||
|
jj commit [paths...] # Only specified paths
|
||||||
|
```
|
||||||
|
|
||||||
|
## History Rewriting
|
||||||
|
|
||||||
|
### `jj squash`
|
||||||
|
|
||||||
|
Move changes into parent:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj squash # All changes to parent
|
||||||
|
jj squash -r <rev> # From specific revision
|
||||||
|
jj squash -i # Interactive selection
|
||||||
|
jj squash [paths...] # Only specific paths
|
||||||
|
jj squash --from <A> --into <B> # Between arbitrary commits
|
||||||
|
jj squash -m "message" # Set combined description
|
||||||
|
jj squash -k # Keep source (don't abandon)
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj split`
|
||||||
|
|
||||||
|
Split commit into two:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj split # Interactive split of working copy
|
||||||
|
jj split -r <rev> # Split specific revision
|
||||||
|
jj split [paths...] # Put paths in first commit
|
||||||
|
jj split -i # Interactive mode
|
||||||
|
jj split -p # Parallel (sibling) commits
|
||||||
|
jj split -m "message" # First commit message
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj rebase`
|
||||||
|
|
||||||
|
Move commits to different parents:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# What to rebase:
|
||||||
|
jj rebase -b <rev> # Branch containing rev (default: -b @)
|
||||||
|
jj rebase -s <rev> # Source and descendants
|
||||||
|
jj rebase -r <rev> # Only revision (not descendants)
|
||||||
|
|
||||||
|
# Where to rebase:
|
||||||
|
jj rebase -d <dest> # Onto destination
|
||||||
|
jj rebase -A <rev> # Insert after
|
||||||
|
jj rebase -B <rev> # Insert before
|
||||||
|
|
||||||
|
# Examples:
|
||||||
|
jj rebase -d main # Rebase current branch onto main
|
||||||
|
jj rebase -s X -d Y # Rebase X and descendants onto Y
|
||||||
|
jj rebase -r X -d Y # Rebase only X onto Y
|
||||||
|
jj rebase -r X -A Y # Insert X after Y
|
||||||
|
jj rebase -r X -B Y # Insert X before Y
|
||||||
|
|
||||||
|
# Options:
|
||||||
|
jj rebase --skip-emptied # Abandon commits that become empty
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj diffedit`
|
||||||
|
|
||||||
|
Interactively edit commit contents:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj diffedit # Edit working copy
|
||||||
|
jj diffedit -r <rev> # Edit specific revision
|
||||||
|
jj diffedit --from <A> --to <B> # Edit diff between revisions
|
||||||
|
jj diffedit --tool <tool> # Use specific diff editor
|
||||||
|
jj diffedit --restore-descendants # Preserve descendant content
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj duplicate`
|
||||||
|
|
||||||
|
Copy commits:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj duplicate # Duplicate working copy
|
||||||
|
jj duplicate <revs> # Duplicate specific revisions
|
||||||
|
jj duplicate -A <rev> # Insert duplicates after
|
||||||
|
jj duplicate -B <rev> # Insert duplicates before
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj abandon`
|
||||||
|
|
||||||
|
Remove commits (keep content in descendants):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj abandon # Abandon working copy
|
||||||
|
jj abandon <revs> # Abandon specific revisions
|
||||||
|
jj abandon --retain-bookmarks # Move bookmarks to parents
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj restore`
|
||||||
|
|
||||||
|
Restore files from another revision:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj restore # Restore all from parent
|
||||||
|
jj restore [paths...] # Restore specific paths
|
||||||
|
jj restore --from <rev> # Source revision
|
||||||
|
jj restore --into <rev> # Destination revision
|
||||||
|
jj restore -c <rev> # Undo changes in revision
|
||||||
|
jj restore -i # Interactive mode
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj parallelize`
|
||||||
|
|
||||||
|
Make commits siblings instead of parent-child:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj parallelize <revs> # Make revisions parallel
|
||||||
|
```
|
||||||
|
|
||||||
|
## Bookmarks (Branches)
|
||||||
|
|
||||||
|
### `jj bookmark` (alias: `b`)
|
||||||
|
|
||||||
|
Manage bookmarks:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List
|
||||||
|
jj bookmark list
|
||||||
|
jj bookmark list -a # Include all remotes
|
||||||
|
jj bookmark list -r <revs> # Bookmarks at revisions
|
||||||
|
|
||||||
|
# Create/Set
|
||||||
|
jj bookmark create <name> # At working copy
|
||||||
|
jj bookmark create <name> -r <rev>
|
||||||
|
jj bookmark set <name> # Move to working copy
|
||||||
|
jj bookmark set <name> -r <rev> # Move to revision
|
||||||
|
jj bookmark set <name> -B # Allow moving backwards
|
||||||
|
|
||||||
|
# Modify
|
||||||
|
jj bookmark move <name> # Move to working copy
|
||||||
|
jj bookmark move --from <rev> # Move from revision
|
||||||
|
jj bookmark rename <old> <new>
|
||||||
|
|
||||||
|
# Delete
|
||||||
|
jj bookmark delete <name> # Delete (will push deletion)
|
||||||
|
jj bookmark forget <name> # Forget (won't push deletion)
|
||||||
|
|
||||||
|
# Remote tracking
|
||||||
|
jj bookmark track <name>@<remote>
|
||||||
|
jj bookmark untrack <name>@<remote>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Git Operations
|
||||||
|
|
||||||
|
### `jj git fetch`
|
||||||
|
|
||||||
|
Fetch from remote:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj git fetch # From default remote
|
||||||
|
jj git fetch --remote <name> # From specific remote
|
||||||
|
jj git fetch --all-remotes # From all remotes
|
||||||
|
jj git fetch --branch <pattern> # Specific branches
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj git push`
|
||||||
|
|
||||||
|
Push to remote:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj git push --bookmark <name> # Push specific bookmark
|
||||||
|
jj git push --all # Push all bookmarks
|
||||||
|
jj git push --tracked # Push all tracked
|
||||||
|
jj git push --deleted # Push deletions
|
||||||
|
jj git push --change <rev> # Create bookmark from change
|
||||||
|
jj git push --remote <name> # To specific remote
|
||||||
|
jj git push --dry-run # Show what would be pushed
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj git remote`
|
||||||
|
|
||||||
|
Manage remotes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj git remote list
|
||||||
|
jj git remote add <name> <url>
|
||||||
|
jj git remote remove <name>
|
||||||
|
jj git remote rename <old> <new>
|
||||||
|
jj git remote set-url <name> <url>
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj git import` / `jj git export`
|
||||||
|
|
||||||
|
Sync with underlying Git repo (rarely needed in colocated repos):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj git import # Import Git changes to jj
|
||||||
|
jj git export # Export jj changes to Git
|
||||||
|
```
|
||||||
|
|
||||||
|
## Operation Log
|
||||||
|
|
||||||
|
### `jj op log`
|
||||||
|
|
||||||
|
View operation history:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj op log # Full operation log
|
||||||
|
jj op log -n 10 # Limit entries
|
||||||
|
jj op log -p # Show patches
|
||||||
|
jj op log -d # Show operation diffs
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj undo` / `jj redo`
|
||||||
|
|
||||||
|
Undo/redo operations:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj undo # Undo last operation
|
||||||
|
jj redo # Redo after undo
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj op restore`
|
||||||
|
|
||||||
|
Restore to previous state:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj op restore <op-id> # Restore to operation
|
||||||
|
```
|
||||||
|
|
||||||
|
### `jj op show`
|
||||||
|
|
||||||
|
Show operation details:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj op show # Current operation
|
||||||
|
jj op show <op-id> # Specific operation
|
||||||
|
jj op show -p # With patches
|
||||||
|
```
|
||||||
|
|
||||||
|
## File Operations
|
||||||
|
|
||||||
|
### `jj file`
|
||||||
|
|
||||||
|
File-related commands:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj file list # List files in working copy
|
||||||
|
jj file list -r <rev> # Files in specific revision
|
||||||
|
jj file show <path> # Show file content
|
||||||
|
jj file show -r <rev> <path> # Content at revision
|
||||||
|
jj file annotate <path> # Blame (line origins)
|
||||||
|
jj file chmod x <path> # Make executable
|
||||||
|
jj file chmod n <path> # Remove executable
|
||||||
|
jj file track <paths> # Start tracking
|
||||||
|
jj file untrack <paths> # Stop tracking
|
||||||
|
```
|
||||||
|
|
||||||
|
## Workspaces
|
||||||
|
|
||||||
|
### `jj workspace`
|
||||||
|
|
||||||
|
Manage multiple working copies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj workspace list # List workspaces
|
||||||
|
jj workspace add <path> # Add workspace
|
||||||
|
jj workspace add -r <rev> <path> # At specific revision
|
||||||
|
jj workspace forget [name] # Remove workspace
|
||||||
|
jj workspace root # Show workspace root
|
||||||
|
jj workspace update-stale # Update stale workspace
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### `jj config`
|
||||||
|
|
||||||
|
Manage configuration:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj config list # Show all config
|
||||||
|
jj config get <key> # Get specific value
|
||||||
|
jj config set --user <key> <val> # Set user config
|
||||||
|
jj config set --repo <key> <val> # Set repo config
|
||||||
|
jj config edit --user # Edit user config
|
||||||
|
jj config edit --repo # Edit repo config
|
||||||
|
jj config path --user # Show config file path
|
||||||
|
```
|
||||||
|
|
||||||
|
## Utility Commands
|
||||||
|
|
||||||
|
### Other useful commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj root # Show repo root
|
||||||
|
jj version # Show jj version
|
||||||
|
jj resolve # Resolve conflicts
|
||||||
|
jj resolve -l # List conflicts
|
||||||
|
jj evolog # Show change evolution
|
||||||
|
jj interdiff --from <A> --to <B> # Compare changes of commits
|
||||||
|
jj next # Move to child commit
|
||||||
|
jj prev # Move to parent commit
|
||||||
|
jj fix # Run code formatters
|
||||||
|
jj sign # Sign commits
|
||||||
|
jj sparse set --add <path> # Add to sparse checkout
|
||||||
|
jj sparse set --remove <path> # Remove from sparse
|
||||||
|
jj util completion <shell> # Generate shell completions
|
||||||
|
jj util gc # Garbage collect
|
||||||
|
```
|
||||||
|
|
||||||
|
## Global Options
|
||||||
|
|
||||||
|
Available on all commands:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj -R <path> # Use different repo
|
||||||
|
jj --at-op <op-id> # Load at operation
|
||||||
|
jj --ignore-working-copy # Skip working copy snapshot
|
||||||
|
jj --ignore-immutable # Allow modifying immutable
|
||||||
|
jj --color <when> # always/never/auto
|
||||||
|
jj --no-pager # Disable pager
|
||||||
|
jj --config <key=value> # Override config
|
||||||
|
jj --config-file <path> # Additional config file
|
||||||
|
jj --quiet # Less output
|
||||||
|
jj --debug # Debug output
|
||||||
|
```
|
||||||
470
references/configuration.md
Normal file
470
references/configuration.md
Normal file
@@ -0,0 +1,470 @@
|
|||||||
|
# Configuration Reference
|
||||||
|
|
||||||
|
Comprehensive reference for jj configuration options, templates, filesets, and aliases.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Config Files](#config-files)
|
||||||
|
- [User Settings](#user-settings)
|
||||||
|
- [UI Settings](#ui-settings)
|
||||||
|
- [Aliases](#aliases)
|
||||||
|
- [Templates](#templates)
|
||||||
|
- [Filesets](#filesets)
|
||||||
|
- [Git Settings](#git-settings)
|
||||||
|
- [Signing](#signing)
|
||||||
|
|
||||||
|
## Config Files
|
||||||
|
|
||||||
|
jj loads configuration from multiple sources (in order of precedence):
|
||||||
|
|
||||||
|
1. **Built-in** - Cannot be edited
|
||||||
|
2. **User** - `~/.config/jj/config.toml` or `~/.jjconfig.toml`
|
||||||
|
3. **Repo** - `.jj/repo/config.toml`
|
||||||
|
4. **Workspace** - `.jj/workspace-config.toml`
|
||||||
|
5. **Command-line** - `--config key=value`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj config path --user # Show user config path
|
||||||
|
jj config edit --user # Edit user config
|
||||||
|
jj config edit --repo # Edit repo config
|
||||||
|
jj config list # Show all config values
|
||||||
|
jj config get <key> # Get specific value
|
||||||
|
```
|
||||||
|
|
||||||
|
## User Settings
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[user]
|
||||||
|
name = "Your Name"
|
||||||
|
email = "your@email.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
## UI Settings
|
||||||
|
|
||||||
|
### Basic UI
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[ui]
|
||||||
|
# Color output: always, never, auto, debug
|
||||||
|
color = "auto"
|
||||||
|
|
||||||
|
# Default command when running 'jj' with no args
|
||||||
|
default-command = "log"
|
||||||
|
# Or with arguments:
|
||||||
|
default-command = ["log", "--reversed"]
|
||||||
|
|
||||||
|
# Pager command
|
||||||
|
pager = "less -FRX"
|
||||||
|
|
||||||
|
# Editor for descriptions
|
||||||
|
editor = "vim"
|
||||||
|
|
||||||
|
# Diff format: :color-words, :git, :summary, :stat, :types, :name-only
|
||||||
|
diff-formatter = ":color-words"
|
||||||
|
|
||||||
|
# Movement commands (next/prev) edit instead of creating new commit
|
||||||
|
movement.edit = false
|
||||||
|
```
|
||||||
|
|
||||||
|
### Colors and Styles
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[colors]
|
||||||
|
# Simple foreground color
|
||||||
|
commit_id = "green"
|
||||||
|
change_id = "magenta"
|
||||||
|
|
||||||
|
# Hex colors
|
||||||
|
bookmark = "#ff1525"
|
||||||
|
|
||||||
|
# Full style specification
|
||||||
|
commit_id = { fg = "green", bg = "black", bold = true }
|
||||||
|
change_id = { underline = true, italic = true }
|
||||||
|
|
||||||
|
# Combined labels (like CSS selectors)
|
||||||
|
"working_copy commit_id" = { underline = true }
|
||||||
|
"conflict description" = "red"
|
||||||
|
|
||||||
|
# Diff colors
|
||||||
|
"diff removed" = "red"
|
||||||
|
"diff added" = "green"
|
||||||
|
"diff removed token" = { bg = "#221111", underline = false }
|
||||||
|
"diff added token" = { bg = "#002200", underline = false }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Diff Options
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[diff.color-words]
|
||||||
|
# Max removed/added alternation to inline (-1 = all)
|
||||||
|
max-inline-alternation = 3
|
||||||
|
# Lines of context
|
||||||
|
context = 3
|
||||||
|
|
||||||
|
[diff.git]
|
||||||
|
context = 3
|
||||||
|
```
|
||||||
|
|
||||||
|
### External Diff Tools
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[ui]
|
||||||
|
diff-formatter = ["difft", "--color=always", "$left", "$right"]
|
||||||
|
# Or reference a named tool:
|
||||||
|
diff-formatter = "difftastic"
|
||||||
|
|
||||||
|
[merge-tools.difftastic]
|
||||||
|
program = "difft"
|
||||||
|
diff-args = ["--color=always", "$left", "$right"]
|
||||||
|
diff-invocation-mode = "dir" # or "file-by-file"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Aliases
|
||||||
|
|
||||||
|
### Command Aliases
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[aliases]
|
||||||
|
# Simple alias
|
||||||
|
l = ["log", "-r", "@::"]
|
||||||
|
|
||||||
|
# Complex alias
|
||||||
|
show-tree = ["log", "-r", "@::", "--no-graph", "-T", "commit_id.short() ++ ' ' ++ description.first_line()"]
|
||||||
|
|
||||||
|
# External command (via util exec)
|
||||||
|
my-script = ["util", "exec", "--", "my-jj-script"]
|
||||||
|
|
||||||
|
# Inline script
|
||||||
|
format = ["util", "exec", "--", "bash", "-c", """
|
||||||
|
set -euo pipefail
|
||||||
|
jj fix
|
||||||
|
""", ""]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Revset Aliases
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[revset-aliases]
|
||||||
|
# Custom revsets
|
||||||
|
'wip' = 'description(exact:"") & mine()'
|
||||||
|
'stacked' = 'trunk()..@'
|
||||||
|
'recent' = 'ancestors(@, 20) & mine()'
|
||||||
|
'feature(x)' = 'bookmarks(glob:"feature-" ++ x ++ "*")::'
|
||||||
|
|
||||||
|
# Override built-in trunk() detection
|
||||||
|
'trunk()' = 'latest(remote_bookmarks(exact:"main", exact:"origin") | remote_bookmarks(exact:"master", exact:"origin"))'
|
||||||
|
|
||||||
|
# Customize immutable commits
|
||||||
|
'immutable_heads()' = 'trunk() | tags()'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Template Aliases
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[template-aliases]
|
||||||
|
# Custom formatting
|
||||||
|
'format_short_id(id)' = 'id.shortest(8)'
|
||||||
|
'format_timestamp(ts)' = 'ts.ago()'
|
||||||
|
|
||||||
|
# Custom commit format
|
||||||
|
'my_log' = '''
|
||||||
|
change_id.short() ++ " " ++
|
||||||
|
if(description, description.first_line(), "(no description)") ++
|
||||||
|
if(conflict, " CONFLICT", "")
|
||||||
|
'''
|
||||||
|
```
|
||||||
|
|
||||||
|
## Templates
|
||||||
|
|
||||||
|
Templates are a functional language for customizing output.
|
||||||
|
|
||||||
|
### Log Template
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[templates]
|
||||||
|
log = 'builtin_log_oneline'
|
||||||
|
# Or custom:
|
||||||
|
log = '''
|
||||||
|
separate(" ",
|
||||||
|
format_short_change_id_with_hidden_and_divergent_info(self),
|
||||||
|
format_short_commit_id(commit_id),
|
||||||
|
bookmarks,
|
||||||
|
tags,
|
||||||
|
if(conflict, label("conflict", "conflict")),
|
||||||
|
if(empty, label("empty", "(empty)")),
|
||||||
|
if(description, description.first_line(), description_placeholder),
|
||||||
|
) ++ "\n"
|
||||||
|
'''
|
||||||
|
```
|
||||||
|
|
||||||
|
### Draft Description Template
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[templates]
|
||||||
|
draft_commit_description = '''
|
||||||
|
concat(
|
||||||
|
builtin_draft_commit_description,
|
||||||
|
"\nJJ: ignore-rest\n",
|
||||||
|
diff.git(),
|
||||||
|
)
|
||||||
|
'''
|
||||||
|
|
||||||
|
[template-aliases]
|
||||||
|
default_commit_description = '''
|
||||||
|
"
|
||||||
|
|
||||||
|
Closes #NNNN
|
||||||
|
"
|
||||||
|
'''
|
||||||
|
```
|
||||||
|
|
||||||
|
### Commit Trailers
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[templates]
|
||||||
|
commit_trailers = '''
|
||||||
|
format_signed_off_by_trailer(self)
|
||||||
|
++ if(!trailers.contains_key("Change-Id"), format_gerrit_change_id_trailer(self))
|
||||||
|
'''
|
||||||
|
```
|
||||||
|
|
||||||
|
### Template Syntax
|
||||||
|
|
||||||
|
```
|
||||||
|
# Literals
|
||||||
|
"string"
|
||||||
|
true / false
|
||||||
|
42
|
||||||
|
|
||||||
|
# Operators
|
||||||
|
x ++ y # Concatenate
|
||||||
|
x && y # Logical and
|
||||||
|
x || y # Logical or
|
||||||
|
!x # Logical not
|
||||||
|
x == y # Equality
|
||||||
|
|
||||||
|
# Conditionals
|
||||||
|
if(condition, then, else)
|
||||||
|
|
||||||
|
# Functions
|
||||||
|
separate(sep, items...) # Join non-empty with separator
|
||||||
|
concat(items...) # Join all items
|
||||||
|
coalesce(items...) # First non-empty
|
||||||
|
surround(prefix, suffix, content) # Wrap if non-empty
|
||||||
|
label(name, content) # Apply color label
|
||||||
|
indent(prefix, content) # Indent lines
|
||||||
|
fill(width, content) # Word wrap
|
||||||
|
```
|
||||||
|
|
||||||
|
### Commit Methods
|
||||||
|
|
||||||
|
Available in log/show templates:
|
||||||
|
|
||||||
|
```
|
||||||
|
self.commit_id()
|
||||||
|
self.change_id()
|
||||||
|
self.description()
|
||||||
|
self.author()
|
||||||
|
self.committer()
|
||||||
|
self.parents()
|
||||||
|
self.bookmarks()
|
||||||
|
self.tags()
|
||||||
|
self.working_copies()
|
||||||
|
self.conflict()
|
||||||
|
self.empty()
|
||||||
|
self.immutable()
|
||||||
|
self.divergent()
|
||||||
|
self.hidden()
|
||||||
|
self.mine()
|
||||||
|
self.contained_in(revset)
|
||||||
|
self.diff([fileset])
|
||||||
|
```
|
||||||
|
|
||||||
|
## Filesets
|
||||||
|
|
||||||
|
Filesets select files for commands like `jj diff`, `jj split`, `jj squash`.
|
||||||
|
|
||||||
|
### Patterns
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Path prefix (default)
|
||||||
|
jj diff src # Files under src/
|
||||||
|
|
||||||
|
# Exact file
|
||||||
|
jj diff 'file:README.md'
|
||||||
|
|
||||||
|
# Glob patterns
|
||||||
|
jj diff 'glob:*.rs' # .rs in current dir
|
||||||
|
jj diff 'glob:**/*.rs' # All .rs files
|
||||||
|
jj diff 'glob-i:*.TXT' # Case-insensitive
|
||||||
|
|
||||||
|
# Root-relative (from repo root)
|
||||||
|
jj diff 'root:src'
|
||||||
|
jj diff 'root-glob:**/*.rs'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Operators
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Negation
|
||||||
|
jj diff '~Cargo.lock' # Everything except Cargo.lock
|
||||||
|
|
||||||
|
# Intersection
|
||||||
|
jj diff 'src & glob:**/*.rs' # Rust files in src/
|
||||||
|
|
||||||
|
# Difference
|
||||||
|
jj diff 'src ~ glob:**/*.rs' # Non-Rust files in src/
|
||||||
|
|
||||||
|
# Union
|
||||||
|
jj diff 'glob:*.rs | glob:*.toml'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Functions
|
||||||
|
|
||||||
|
```bash
|
||||||
|
all() # All files
|
||||||
|
none() # No files
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Diff excluding lock files
|
||||||
|
jj diff '~Cargo.lock'
|
||||||
|
|
||||||
|
# Split: put all except foo in first commit
|
||||||
|
jj split '~foo'
|
||||||
|
|
||||||
|
# List non-Rust files in src
|
||||||
|
jj file list 'src ~ glob:**/*.rs'
|
||||||
|
|
||||||
|
# Squash only specific files
|
||||||
|
jj squash 'glob:*.md'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Git Settings
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[git]
|
||||||
|
# Auto-local-bookmark for new remote bookmarks
|
||||||
|
auto-local-bookmark = true
|
||||||
|
|
||||||
|
# Default push/fetch remote
|
||||||
|
push = "origin"
|
||||||
|
fetch = "origin"
|
||||||
|
|
||||||
|
# Push bookmark naming template
|
||||||
|
push-bookmark-prefix = "push-"
|
||||||
|
|
||||||
|
# Private commits (won't be pushed)
|
||||||
|
private-commits = "description(glob:'wip:*')"
|
||||||
|
|
||||||
|
# Colocate by default
|
||||||
|
colocate = true
|
||||||
|
|
||||||
|
# Shallow clone depth
|
||||||
|
shallow-clone-depth = 0 # 0 = full clone
|
||||||
|
|
||||||
|
# Fetch tags
|
||||||
|
fetch-tags = "included" # all, included, none
|
||||||
|
|
||||||
|
# Abandon unreachable commits from remote
|
||||||
|
abandon-unreachable-commits = true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Signing
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[signing]
|
||||||
|
# Enable signing
|
||||||
|
sign-all = false
|
||||||
|
|
||||||
|
# Signing backend: gpg, ssh, none
|
||||||
|
backend = "gpg"
|
||||||
|
|
||||||
|
# GPG settings
|
||||||
|
[signing.backends.gpg]
|
||||||
|
program = "gpg"
|
||||||
|
# Allow expired keys
|
||||||
|
allow-expired-keys = false
|
||||||
|
|
||||||
|
# SSH settings
|
||||||
|
[signing.backends.ssh]
|
||||||
|
program = "ssh-keygen"
|
||||||
|
# Allowed signers file
|
||||||
|
allowed-signers = "~/.ssh/allowed_signers"
|
||||||
|
# Key to use
|
||||||
|
key = "~/.ssh/id_ed25519.pub"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Immutable Commits
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[revset-aliases]
|
||||||
|
# Default: trunk and tags are immutable
|
||||||
|
'immutable_heads()' = 'trunk() | tags()'
|
||||||
|
|
||||||
|
# More restrictive: only trunk
|
||||||
|
'immutable_heads()' = 'trunk()'
|
||||||
|
|
||||||
|
# Include release branches
|
||||||
|
'immutable_heads()' = 'trunk() | tags() | bookmarks(glob:"release-*")'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Fix Tools (Formatters)
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[fix.tools.rustfmt]
|
||||||
|
command = ["rustfmt", "--emit=stdout"]
|
||||||
|
patterns = ["glob:'**/*.rs'"]
|
||||||
|
|
||||||
|
[fix.tools.black]
|
||||||
|
command = ["black", "-", "--stdin-filename=$path"]
|
||||||
|
patterns = ["glob:'**/*.py'"]
|
||||||
|
|
||||||
|
[fix.tools.prettier]
|
||||||
|
command = ["prettier", "--stdin-filepath=$path"]
|
||||||
|
patterns = ["glob:'**/*.{js,ts,jsx,tsx,json,md}'"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Merge Tools
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[merge-tools.meld]
|
||||||
|
program = "meld"
|
||||||
|
merge-args = ["$left", "$base", "$right", "-o", "$output"]
|
||||||
|
edit-args = ["$left", "$right"]
|
||||||
|
|
||||||
|
[merge-tools.vimdiff]
|
||||||
|
program = "vim"
|
||||||
|
merge-args = ["-d", "$left", "$base", "$right", "$output"]
|
||||||
|
merge-tool-edits-conflict-markers = true
|
||||||
|
|
||||||
|
[ui]
|
||||||
|
merge-editor = "meld"
|
||||||
|
diff-editor = ":builtin"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Snapshot Settings
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[snapshot]
|
||||||
|
# Max file size to track (bytes)
|
||||||
|
max-new-file-size = "1MiB"
|
||||||
|
|
||||||
|
# Auto-track patterns (default: all)
|
||||||
|
auto-track = "all()"
|
||||||
|
# Or selective:
|
||||||
|
auto-track = "glob:**/*.rs"
|
||||||
|
|
||||||
|
# Watchman integration
|
||||||
|
use-watchman = "if-available"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Debug Settings
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[debug]
|
||||||
|
# Randomize commit IDs (for testing)
|
||||||
|
randomness-seed = ""
|
||||||
|
```
|
||||||
380
references/git-comparison.md
Normal file
380
references/git-comparison.md
Normal file
@@ -0,0 +1,380 @@
|
|||||||
|
# Git to jj Command Comparison
|
||||||
|
|
||||||
|
This reference maps common Git commands and workflows to their jj equivalents.
|
||||||
|
|
||||||
|
## Quick Reference Table
|
||||||
|
|
||||||
|
| Git Command | jj Equivalent | Notes |
|
||||||
|
|-------------|---------------|-------|
|
||||||
|
| `git init` | `jj git init` | Creates colocated repo by default |
|
||||||
|
| `git clone` | `jj git clone` | Creates colocated repo by default |
|
||||||
|
| `git status` | `jj status` | Alias: `jj st` |
|
||||||
|
| `git log` | `jj log` | Shows graph by default |
|
||||||
|
| `git log --oneline` | `jj log --no-graph` | Or customize template |
|
||||||
|
| `git show` | `jj show` | |
|
||||||
|
| `git diff` | `jj diff` | |
|
||||||
|
| `git diff --staged` | N/A | No staging area in jj |
|
||||||
|
| `git add` | N/A | Auto-tracked |
|
||||||
|
| `git add -p` | `jj split -i` | Interactive commit splitting |
|
||||||
|
| `git commit` | `jj commit` or `jj new` | Different workflow |
|
||||||
|
| `git commit --amend` | `jj describe` + changes | Working copy is always amendable |
|
||||||
|
| `git commit --amend -m` | `jj describe -m "msg"` | |
|
||||||
|
| `git reset HEAD~` | `jj squash` | Move changes to parent |
|
||||||
|
| `git reset --hard` | `jj restore` | |
|
||||||
|
| `git checkout <file>` | `jj restore <file>` | |
|
||||||
|
| `git checkout <branch>` | `jj new <bookmark>` | Creates new working copy |
|
||||||
|
| `git switch` | `jj new` | |
|
||||||
|
| `git branch` | `jj bookmark` | Alias: `jj b` |
|
||||||
|
| `git branch -d` | `jj bookmark delete` | |
|
||||||
|
| `git merge` | `jj new <A> <B>` | Creates merge commit |
|
||||||
|
| `git rebase` | `jj rebase` | More powerful |
|
||||||
|
| `git rebase -i` | `jj squash -i`, `jj split` | Different approach |
|
||||||
|
| `git cherry-pick` | `jj new <rev>; jj squash` | Or `jj duplicate` |
|
||||||
|
| `git revert` | `jj revert` | |
|
||||||
|
| `git stash` | N/A | Not needed - use `jj new` |
|
||||||
|
| `git stash pop` | N/A | Use `jj squash` |
|
||||||
|
| `git fetch` | `jj git fetch` | |
|
||||||
|
| `git pull` | `jj git fetch` + `jj rebase` | No single command |
|
||||||
|
| `git push` | `jj git push` | |
|
||||||
|
| `git blame` | `jj file annotate` | |
|
||||||
|
| `git reflog` | `jj op log` | More powerful |
|
||||||
|
| `git tag` | `jj tag` | |
|
||||||
|
|
||||||
|
## Workflow Comparisons
|
||||||
|
|
||||||
|
### Creating a New Commit
|
||||||
|
|
||||||
|
**Git:**
|
||||||
|
```bash
|
||||||
|
git add .
|
||||||
|
git commit -m "message"
|
||||||
|
```
|
||||||
|
|
||||||
|
**jj:**
|
||||||
|
```bash
|
||||||
|
# Changes are auto-tracked
|
||||||
|
jj describe -m "message"
|
||||||
|
jj new # Start new work
|
||||||
|
# Or:
|
||||||
|
jj commit -m "message" # Same effect
|
||||||
|
```
|
||||||
|
|
||||||
|
### Amending the Last Commit
|
||||||
|
|
||||||
|
**Git:**
|
||||||
|
```bash
|
||||||
|
git add .
|
||||||
|
git commit --amend
|
||||||
|
```
|
||||||
|
|
||||||
|
**jj:**
|
||||||
|
```bash
|
||||||
|
# Changes automatically amend current working copy
|
||||||
|
# Just edit files, done!
|
||||||
|
# To change message:
|
||||||
|
jj describe -m "new message"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Interactive Staging
|
||||||
|
|
||||||
|
**Git:**
|
||||||
|
```bash
|
||||||
|
git add -p
|
||||||
|
git commit
|
||||||
|
```
|
||||||
|
|
||||||
|
**jj:**
|
||||||
|
```bash
|
||||||
|
# Split current changes into separate commits
|
||||||
|
jj split -i
|
||||||
|
# Or squash parts into parent
|
||||||
|
jj squash -i
|
||||||
|
```
|
||||||
|
|
||||||
|
### Undoing Last Commit (Keep Changes)
|
||||||
|
|
||||||
|
**Git:**
|
||||||
|
```bash
|
||||||
|
git reset HEAD~
|
||||||
|
```
|
||||||
|
|
||||||
|
**jj:**
|
||||||
|
```bash
|
||||||
|
jj squash # Moves changes to parent, abandons if empty
|
||||||
|
```
|
||||||
|
|
||||||
|
### Discarding Changes
|
||||||
|
|
||||||
|
**Git:**
|
||||||
|
```bash
|
||||||
|
git checkout -- .
|
||||||
|
git reset --hard
|
||||||
|
```
|
||||||
|
|
||||||
|
**jj:**
|
||||||
|
```bash
|
||||||
|
jj restore # Restore from parent
|
||||||
|
```
|
||||||
|
|
||||||
|
### Switching Branches
|
||||||
|
|
||||||
|
**Git:**
|
||||||
|
```bash
|
||||||
|
git checkout feature
|
||||||
|
# or
|
||||||
|
git switch feature
|
||||||
|
```
|
||||||
|
|
||||||
|
**jj:**
|
||||||
|
```bash
|
||||||
|
jj new feature # Create working copy on feature
|
||||||
|
# Or to edit feature directly:
|
||||||
|
jj edit feature
|
||||||
|
```
|
||||||
|
|
||||||
|
### Creating a Branch
|
||||||
|
|
||||||
|
**Git:**
|
||||||
|
```bash
|
||||||
|
git checkout -b feature
|
||||||
|
# or
|
||||||
|
git switch -c feature
|
||||||
|
```
|
||||||
|
|
||||||
|
**jj:**
|
||||||
|
```bash
|
||||||
|
jj bookmark create feature
|
||||||
|
# Then work - changes go to working copy
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stashing Changes
|
||||||
|
|
||||||
|
**Git:**
|
||||||
|
```bash
|
||||||
|
git stash
|
||||||
|
# ... do other work ...
|
||||||
|
git stash pop
|
||||||
|
```
|
||||||
|
|
||||||
|
**jj:**
|
||||||
|
```bash
|
||||||
|
# Not needed! Working copy is already a commit.
|
||||||
|
# To work on something else:
|
||||||
|
jj new main # Start new work from main
|
||||||
|
# ... do other work ...
|
||||||
|
jj edit <original-change-id> # Go back
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rebasing a Branch
|
||||||
|
|
||||||
|
**Git:**
|
||||||
|
```bash
|
||||||
|
git checkout feature
|
||||||
|
git rebase main
|
||||||
|
```
|
||||||
|
|
||||||
|
**jj:**
|
||||||
|
```bash
|
||||||
|
jj rebase -b feature -d main
|
||||||
|
# Or if on feature:
|
||||||
|
jj rebase -d main
|
||||||
|
```
|
||||||
|
|
||||||
|
### Interactive Rebase
|
||||||
|
|
||||||
|
**Git:**
|
||||||
|
```bash
|
||||||
|
git rebase -i HEAD~5
|
||||||
|
```
|
||||||
|
|
||||||
|
**jj:**
|
||||||
|
```bash
|
||||||
|
# Different approach - use individual commands:
|
||||||
|
jj squash # Combine commits
|
||||||
|
jj split # Split commits
|
||||||
|
jj rebase # Reorder
|
||||||
|
jj describe # Edit messages
|
||||||
|
jj abandon # Drop commits
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cherry-picking
|
||||||
|
|
||||||
|
**Git:**
|
||||||
|
```bash
|
||||||
|
git cherry-pick <commit>
|
||||||
|
```
|
||||||
|
|
||||||
|
**jj:**
|
||||||
|
```bash
|
||||||
|
jj new <commit> # Create child of commit
|
||||||
|
jj rebase -r @ -d main # Move to destination
|
||||||
|
# Or simpler:
|
||||||
|
jj duplicate <commit>
|
||||||
|
jj rebase -r <duplicated> -d main
|
||||||
|
```
|
||||||
|
|
||||||
|
### Resolving Conflicts
|
||||||
|
|
||||||
|
**Git:**
|
||||||
|
```bash
|
||||||
|
git merge feature
|
||||||
|
# Conflicts occur
|
||||||
|
# Edit files
|
||||||
|
git add .
|
||||||
|
git commit
|
||||||
|
```
|
||||||
|
|
||||||
|
**jj:**
|
||||||
|
```bash
|
||||||
|
jj new main feature # Create merge (may have conflicts)
|
||||||
|
# Conflicts are recorded in commit
|
||||||
|
jj log # Shows conflict marker
|
||||||
|
# Edit files
|
||||||
|
# Changes auto-commit, conflict resolved
|
||||||
|
```
|
||||||
|
|
||||||
|
### Undoing Operations
|
||||||
|
|
||||||
|
**Git:**
|
||||||
|
```bash
|
||||||
|
git reflog
|
||||||
|
git reset --hard HEAD@{2}
|
||||||
|
```
|
||||||
|
|
||||||
|
**jj:**
|
||||||
|
```bash
|
||||||
|
jj op log
|
||||||
|
jj op restore <op-id>
|
||||||
|
# Or simply:
|
||||||
|
jj undo
|
||||||
|
```
|
||||||
|
|
||||||
|
### Viewing History at a Point
|
||||||
|
|
||||||
|
**Git:**
|
||||||
|
```bash
|
||||||
|
git log HEAD@{yesterday}
|
||||||
|
```
|
||||||
|
|
||||||
|
**jj:**
|
||||||
|
```bash
|
||||||
|
jj --at-op=<op-id> log
|
||||||
|
```
|
||||||
|
|
||||||
|
## Conceptual Differences
|
||||||
|
|
||||||
|
### No Staging Area
|
||||||
|
|
||||||
|
Git has a staging area (index) between working directory and commits. jj doesn't:
|
||||||
|
|
||||||
|
- **Git**: working directory → staging area → commit
|
||||||
|
- **jj**: working copy (IS a commit) → new commit
|
||||||
|
|
||||||
|
### Working Copy is a Commit
|
||||||
|
|
||||||
|
In jj, the working copy is always a commit. Changes are automatically recorded:
|
||||||
|
|
||||||
|
- No "dirty" working directory
|
||||||
|
- No lost changes from checkout
|
||||||
|
- Can always undo
|
||||||
|
|
||||||
|
### Change IDs vs Commit IDs
|
||||||
|
|
||||||
|
- **Git**: Only commit hashes (SHA), change when commit is amended
|
||||||
|
- **jj**: Change IDs (stable) + Commit IDs (change on rewrite)
|
||||||
|
|
||||||
|
Use change IDs (`kntqzsqt`) when referring to commits.
|
||||||
|
|
||||||
|
### Conflicts as First-Class Citizens
|
||||||
|
|
||||||
|
- **Git**: Conflicts block operations, must resolve immediately
|
||||||
|
- **jj**: Conflicts are recorded in commits, resolve when convenient
|
||||||
|
|
||||||
|
### Operations are Atomic
|
||||||
|
|
||||||
|
Every jj operation is recorded and reversible:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
jj op log # See all operations
|
||||||
|
jj undo # Undo last operation
|
||||||
|
jj op restore # Go to any point
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bookmarks vs Branches
|
||||||
|
|
||||||
|
- **Git branches**: Automatically move with commits
|
||||||
|
- **jj bookmarks**: Named pointers, move explicitly
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Git: branch moves with HEAD
|
||||||
|
git commit # branch advances
|
||||||
|
|
||||||
|
# jj: bookmark stays unless moved
|
||||||
|
jj new # bookmark doesn't move
|
||||||
|
jj bookmark set <name> # explicit move
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### "Pull and Rebase"
|
||||||
|
|
||||||
|
**Git:**
|
||||||
|
```bash
|
||||||
|
git pull --rebase
|
||||||
|
```
|
||||||
|
|
||||||
|
**jj:**
|
||||||
|
```bash
|
||||||
|
jj git fetch
|
||||||
|
jj rebase -d <remote>@origin # or main@origin
|
||||||
|
```
|
||||||
|
|
||||||
|
### "Push New Branch"
|
||||||
|
|
||||||
|
**Git:**
|
||||||
|
```bash
|
||||||
|
git push -u origin feature
|
||||||
|
```
|
||||||
|
|
||||||
|
**jj:**
|
||||||
|
```bash
|
||||||
|
jj git push --bookmark feature
|
||||||
|
# Or create bookmark from change:
|
||||||
|
jj git push --change <change-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
### "Squash Last N Commits"
|
||||||
|
|
||||||
|
**Git:**
|
||||||
|
```bash
|
||||||
|
git rebase -i HEAD~3
|
||||||
|
# Mark commits as squash
|
||||||
|
```
|
||||||
|
|
||||||
|
**jj:**
|
||||||
|
```bash
|
||||||
|
# Squash into parent repeatedly:
|
||||||
|
jj squash -r <commit>
|
||||||
|
jj squash -r <commit>
|
||||||
|
# Or use revsets:
|
||||||
|
jj squash --from 'trunk()..@'
|
||||||
|
```
|
||||||
|
|
||||||
|
### "Edit Old Commit"
|
||||||
|
|
||||||
|
**Git:**
|
||||||
|
```bash
|
||||||
|
git rebase -i <commit>^
|
||||||
|
# Mark commit as edit
|
||||||
|
# Make changes
|
||||||
|
git commit --amend
|
||||||
|
git rebase --continue
|
||||||
|
```
|
||||||
|
|
||||||
|
**jj:**
|
||||||
|
```bash
|
||||||
|
jj edit <commit>
|
||||||
|
# Make changes (auto-committed)
|
||||||
|
jj new # Continue with new work
|
||||||
|
# Descendants auto-rebased!
|
||||||
|
```
|
||||||
265
references/revsets.md
Normal file
265
references/revsets.md
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
# Revsets Reference
|
||||||
|
|
||||||
|
Revsets are a functional language for selecting commits in jj. This reference covers all operators, functions, and patterns.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Basic Symbols](#basic-symbols)
|
||||||
|
- [Operators](#operators)
|
||||||
|
- [Functions](#functions)
|
||||||
|
- [String Patterns](#string-patterns)
|
||||||
|
- [Common Patterns](#common-patterns)
|
||||||
|
|
||||||
|
## Basic Symbols
|
||||||
|
|
||||||
|
| Symbol | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `@` | Working copy commit |
|
||||||
|
| `root()` | Repository root (empty commit) |
|
||||||
|
| `<change_id>` | Commit by change ID (e.g., `kntqzsqt`) |
|
||||||
|
| `<commit_id>` | Commit by commit hash (prefix ok) |
|
||||||
|
| `<bookmark>` | Commit at bookmark (e.g., `main`) |
|
||||||
|
| `<bookmark>@<remote>` | Remote bookmark (e.g., `main@origin`) |
|
||||||
|
| `<tag>` | Commit at tag |
|
||||||
|
|
||||||
|
## Operators
|
||||||
|
|
||||||
|
### Parent/Child Navigation
|
||||||
|
|
||||||
|
| Operator | Description | Example |
|
||||||
|
|----------|-------------|---------|
|
||||||
|
| `x-` | Parents of x | `@-` (parent of working copy) |
|
||||||
|
| `x+` | Children of x | `main+` (children of main) |
|
||||||
|
| `x--` | Grandparents | `@--` |
|
||||||
|
| `x++` | Grandchildren | `main++` |
|
||||||
|
|
||||||
|
### Ancestry/Descendant
|
||||||
|
|
||||||
|
| Operator | Description | Example |
|
||||||
|
|----------|-------------|---------|
|
||||||
|
| `::x` | Ancestors of x (inclusive) | `::@` |
|
||||||
|
| `x::` | Descendants of x (inclusive) | `main::` |
|
||||||
|
| `x::y` | DAG path from x to y | `main::@` |
|
||||||
|
| `:x` | Ancestors of x (exclusive) | `:@` (excludes @) |
|
||||||
|
| `x:` | Descendants of x (exclusive) | `main:` (excludes main) |
|
||||||
|
|
||||||
|
### Range
|
||||||
|
|
||||||
|
| Operator | Description | Example |
|
||||||
|
|----------|-------------|---------|
|
||||||
|
| `x..y` | Ancestors of y minus ancestors of x | `main..@` |
|
||||||
|
| `x..` | Descendants of x minus x | `main..` |
|
||||||
|
| `..y` | Ancestors of y minus root | `..@` |
|
||||||
|
|
||||||
|
### Set Operations
|
||||||
|
|
||||||
|
| Operator | Description | Example |
|
||||||
|
|----------|-------------|---------|
|
||||||
|
| `x \| y` | Union (x or y) | `main \| develop` |
|
||||||
|
| `x & y` | Intersection (x and y) | `mine() & ::@` |
|
||||||
|
| `x ~ y` | Difference (x minus y) | `::@ ~ ::main` |
|
||||||
|
| `~x` | Complement (not x) | `~empty()` |
|
||||||
|
|
||||||
|
### Grouping
|
||||||
|
|
||||||
|
Use parentheses for grouping: `(x | y) & z`
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
|
||||||
|
### Commit Selection
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `all()` | All commits |
|
||||||
|
| `none()` | Empty set |
|
||||||
|
| `visible_heads()` | Visible branch heads |
|
||||||
|
| `heads(x)` | Commits in x with no descendants in x |
|
||||||
|
| `roots(x)` | Commits in x with no ancestors in x |
|
||||||
|
| `latest(x, n)` | Latest n commits from x by committer date |
|
||||||
|
|
||||||
|
### Bookmarks and Tags
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `bookmarks()` | All local bookmark targets |
|
||||||
|
| `bookmarks(pattern)` | Bookmarks matching pattern |
|
||||||
|
| `remote_bookmarks()` | All remote bookmark targets |
|
||||||
|
| `remote_bookmarks(pattern)` | Remote bookmarks matching pattern |
|
||||||
|
| `tracked_remote_bookmarks()` | Tracked remote bookmarks |
|
||||||
|
| `untracked_remote_bookmarks()` | Untracked remote bookmarks |
|
||||||
|
| `tags()` | All tag targets |
|
||||||
|
| `tags(pattern)` | Tags matching pattern |
|
||||||
|
| `trunk()` | Main branch (main, master, trunk) |
|
||||||
|
|
||||||
|
### Author/Committer
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `author(pattern)` | Commits by matching author name/email |
|
||||||
|
| `author_date(pattern)` | Commits by author date |
|
||||||
|
| `committer(pattern)` | Commits by committer |
|
||||||
|
| `committer_date(pattern)` | Commits by committer date |
|
||||||
|
| `mine()` | Commits by configured user |
|
||||||
|
|
||||||
|
### Content
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `description(pattern)` | Match commit description |
|
||||||
|
| `description(exact:"text")` | Exact description match |
|
||||||
|
| `empty()` | Empty commits (no file changes) |
|
||||||
|
| `file(pattern)` | Commits modifying matching files |
|
||||||
|
| `diff_contains(pattern)` | Commits with matching diff content |
|
||||||
|
|
||||||
|
### Conflicts and Status
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `conflicts()` | Commits containing conflicts |
|
||||||
|
| `signed()` | Cryptographically signed commits |
|
||||||
|
| `working_copies()` | All working copy commits |
|
||||||
|
|
||||||
|
### Mutability
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `mutable()` | Commits that can be rewritten |
|
||||||
|
| `immutable()` | Protected commits (trunk, tags) |
|
||||||
|
| `immutable_heads()` | Heads of immutable commits |
|
||||||
|
|
||||||
|
### Ancestry
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `ancestors(x)` | Same as `::x` |
|
||||||
|
| `ancestors(x, depth)` | Ancestors up to depth |
|
||||||
|
| `descendants(x)` | Same as `x::` |
|
||||||
|
| `descendants(x, depth)` | Descendants up to depth |
|
||||||
|
| `connected(x)` | x plus ancestors and descendants within x |
|
||||||
|
| `reachable(x, domain)` | Commits reachable from x within domain |
|
||||||
|
|
||||||
|
### Structure
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `parents(x)` | Parents of commits in x |
|
||||||
|
| `children(x)` | Children of commits in x |
|
||||||
|
| `present(x)` | x if it exists, else empty |
|
||||||
|
| `coalesce(x, y)` | x if non-empty, else y |
|
||||||
|
|
||||||
|
## String Patterns
|
||||||
|
|
||||||
|
Used in functions like `bookmarks()`, `description()`, `author()`:
|
||||||
|
|
||||||
|
| Pattern | Description | Example |
|
||||||
|
|---------|-------------|---------|
|
||||||
|
| `substring:text` | Contains text (default) | `description("fix")` |
|
||||||
|
| `exact:text` | Exact match | `description(exact:"")` |
|
||||||
|
| `glob:pattern` | Glob pattern | `bookmarks(glob:"feature-*")` |
|
||||||
|
| `regex:pattern` | Regular expression | `author(regex:"^J.*")` |
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### Working with Current Work
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# My work in progress
|
||||||
|
jj log -r 'trunk()..@'
|
||||||
|
|
||||||
|
# My recent changes
|
||||||
|
jj log -r 'mine() & ancestors(@, 20)'
|
||||||
|
|
||||||
|
# Empty commits I made (WIP markers)
|
||||||
|
jj log -r 'mine() & empty()'
|
||||||
|
|
||||||
|
# Commits with empty descriptions
|
||||||
|
jj log -r 'description(exact:"")'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Branch Operations
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Commits on feature branch not on main
|
||||||
|
jj log -r 'main..feature'
|
||||||
|
|
||||||
|
# All commits on any feature branch
|
||||||
|
jj log -r 'bookmarks(glob:"feature-*")::'
|
||||||
|
|
||||||
|
# Diverged commits
|
||||||
|
jj log -r 'heads(trunk()..)'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Finding Commits
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Commits touching specific file
|
||||||
|
jj log -r 'file("src/main.rs")'
|
||||||
|
|
||||||
|
# Commits containing "TODO" in diff
|
||||||
|
jj log -r 'diff_contains("TODO")'
|
||||||
|
|
||||||
|
# Commits by specific author
|
||||||
|
jj log -r 'author("alice@")'
|
||||||
|
|
||||||
|
# Commits from last week
|
||||||
|
jj log -r 'committer_date(after:"1 week ago")'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Conflicts
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# All conflicted commits
|
||||||
|
jj log -r 'conflicts()'
|
||||||
|
|
||||||
|
# Conflicted commits in my branch
|
||||||
|
jj log -r 'conflicts() & trunk()..@'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rebasing Patterns
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Rebase entire branch onto trunk
|
||||||
|
jj rebase -s 'roots(trunk()..@)' -d trunk()
|
||||||
|
|
||||||
|
# Rebase all mutable descendants
|
||||||
|
jj rebase -s 'roots(mutable())' -d <dest>
|
||||||
|
|
||||||
|
# Find commits to squash (empty changes)
|
||||||
|
jj log -r 'empty() & trunk()..@'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Working Copies (Multiple Workspaces)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# All working copy commits
|
||||||
|
jj log -r 'working_copies()'
|
||||||
|
|
||||||
|
# Current workspace's working copy
|
||||||
|
jj log -r '@'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Date Patterns
|
||||||
|
|
||||||
|
For `author_date()` and `committer_date()`:
|
||||||
|
|
||||||
|
| Pattern | Example |
|
||||||
|
|---------|---------|
|
||||||
|
| `after:date` | `author_date(after:"2024-01-01")` |
|
||||||
|
| `before:date` | `committer_date(before:"yesterday")` |
|
||||||
|
| Relative | `"1 week ago"`, `"2 days ago"` |
|
||||||
|
| Absolute | `"2024-06-15"`, `"2024-06-15T10:30:00"` |
|
||||||
|
|
||||||
|
## Combining Expressions
|
||||||
|
|
||||||
|
Complex queries combine operators and functions:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# My non-empty commits on feature branch, excluding conflicts
|
||||||
|
jj log -r '(mine() & feature::@) ~ (empty() | conflicts())'
|
||||||
|
|
||||||
|
# Latest 5 commits touching src/ by any author
|
||||||
|
jj log -r 'latest(file("src/**"), 5)'
|
||||||
|
|
||||||
|
# All commits between two tags
|
||||||
|
jj log -r 'v1.0::v2.0'
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user