Revsets: Powerful Commit Queries
Revsets (revision sets) are jj's query language for selecting commits—much more powerful than git's commit limiting.
Basic Revset Syntax
git
git log -n 10git log abc123jj
jj log -l 10jj log -r abc123jj log -r @| git | jj |
|---|---|
| git log -n 10 | jj log -l 10 |
| git log abc123 | jj log -r abc123 |
Common Revsets
Working copy and parents:
jj log -r @ # Current working copy
jj log -r @- # Parent of @
jj log -r @- # Grandparent (keeps adding -)
jj log -r @+ # Child of @
Branches:
jj log -r main # Commits in main
jj log -r main@origin # Remote-tracking main
jj log -r main.. # main and descendants
Ancestry:
jj log -r ::@ # Ancestors of @ (including @)
jj log -r @:: # Descendants of @ (including @)
jj log -r abc..def # abc to def (ancestors of def, not abc)
jj log -r abc:def # Range abc to def (inclusive)
Filtering by Description
git
git log --grep="fix"jj
jj log -r 'description("fix")'| git | jj |
|---|---|
| git log --grep="fix" | jj log -r 'description("fix")' |
Filtering by Author
git
git log --author="alice"jj
jj log -r 'author("alice")'| git | jj |
|---|---|
| git log --author="alice" | jj log -r 'author("alice")' |
Filtering by Time
git
git log --since="2024-01-01"git log --until="2024-02-01"jj
jj log -r 'today()'jj log -r 'yesterday()'jj log -r 'after("2024-01-01")'jj log -r 'before("2024-02-01")'| git | jj |
|---|---|
| git log --since="2024-01-01" | jj log -r 'today()' |
| git log --until="2024-02-01" | jj log -r 'yesterday()' |
Combining Filters
Revsets support boolean logic:
# Commits by Alice OR Bob
jj log -r 'author("alice") | author("bob")'
# Commits by Alice AND contain "fix"
jj log -r 'author("alice") & description("fix")'
# Commits by Alice but NOT "wip"
jj log -r 'author("alice") ~ description("wip")'
# All commits except those by Bob
jj log -r '~author("bob")'
Practical Examples
Show my recent work:
jj log -r 'author("me") & ::@'
Show what I'll push:
jj log -r 'main@origin..@'
Show commits since last release:
jj log -r 'tags("v1.0")..@'
Show merge commits:
jj log -r 'description("Merge")'
Empty Revsets
When a revset matches nothing:
$ jj log -r 'description("nonexistent")'
"..." (no matches)
This is useful for scripts—if a revset is empty, nothing happens.
Using Revsets with Commands
Revsets work with many jj commands:
# Show specific commits
jj show 'description("fix")'
# Diff between revsets
jj diff --from 'main@origin' --to @
# Rebase based on revset
jj rebase -d 'description("baseline")'
# Abandon multiple commits
jj abandon 'description("wip")'
Change IDs vs Commit IDs
Revsets can query by change ID (stable across rebases) or commit ID (specific instance):
# By change ID (survives rebases)
jj log -r 'change(abc)'
# By commit ID (specific)
jj log -r 'commit(xyz)'
All Commits
To see all commits including abandoned:
jj log --all
# or
jj log -r 'all()'
DAG Operations
Revsets understand the commit DAG:
# Heads of repository (branches without children)
jj log -r 'heads()'
# Roots (commits without parents)
jj log -r 'roots()'
# Visible commits (not hidden)
jj log -r 'visible_heads()'
Try It Yourself
# Make some commits
jj describe -m "Feature A"
jj new
jj describe -m "Feature B"
jj new
# Query them
jj log -r 'description("Feature")'
# Show ancestry
jj log -r '::@'
# Show just the last two
jj log -r '@- | @'
Key Takeaways
- Revsets are a powerful query language
-rflag accepts revset expressions::for ancestry,..for ranges- Boolean operators:
&,|,~ - Filter by author, description, time
- Use change IDs for stable references
Next Steps
Now let's explore jj's approach to rebasing and editing history.