Files
2025-11-30 09:02:31 +08:00

2.4 KiB

JJ Templating Language

Source: https://docs.jj-vcs.dev/latest/templates/

Use templates only when plain jj log output is insufficient: machine-readable output, conditional formatting, scripting pipelines.

Invocation

jj log -r @ --template '...'                    # Single commit
jj log -r 'trunk()..@' --template '...'         # Range
jj log --no-pager --template '...' | jq ...     # Pipe to tools

Commit Fields

Field Description
commit_id / .short() Full/short commit id
change_id / .short() Change identity
description / subject Full message / first line
author.email / author.name Author metadata
timestamp Commit timestamp
bookmarks / tags Lists
conflict Boolean
is_empty Boolean
divergent Boolean
parents List of parent commits

Functions

Function Example
format() format("[", change_id.short(), "] ", subject)
if(cond, a, b) if(conflict, "⚠", "")
short() commit_id.short()
json() author.email.json()
contains() subject.contains("WIP")
truncate(n) description.truncate(80)
indent(n) description.indent(4)
join() bookmarks.join(", ")
map() / filter() bookmarks.map(lower())
len() parents.len()

Chaining: bookmarks.filter(!contains("WIP")).map(lower()).join(" ")

Examples

# Minimal
change_id.short() " " subject

# WIP emphasis
format(if(subject.contains("WIP"),"[WIP] ",""), change_id.short(), " ", subject)

# Conflicts
format(if(conflict,"⚠ ",""), change_id.short(), " ", subject)

# Bookmarks
format(change_id.short()," ",bookmarks.join(",")," ",subject)

# JSON output
format(
  '{"change":"', change_id.short().json(), '",',
  '"author":"', author.email.json(), '",',
  '"conflict":', if(conflict, 'true','false'), '}'
)

Revset + Template

# Divergent heads with conflicts
jj log -r 'heads(all()) & conflicts()' --template 'format(change_id.short()," ",subject)'

# Commits ahead of remote
jj log -r 'myfeature - myfeature@origin' --template 'format("AHEAD ", change_id.short())'

Pitfalls

Issue Fix
Unescaped quotes in JSON Use .json() on dynamic fields
Slow on huge histories Narrow revset first
Complex templates Build incrementally with format()