Initial commit
This commit is contained in:
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 = ""
|
||||
```
|
||||
Reference in New Issue
Block a user