This page aims to show a list of popular Jujutsu aliases and revset aliases. Each list is backed by a Q/A discussion in the jj project on GitHub, but has no official connection to or endorsement from the JJ project or its maintainers.
⚠️ Note that aliases can be submitted by anyone. Use them at your own risk! Be extra cautious with aliases using "util", "exec" as they can run arbitrary commands on your system.
To vote for an alias, click on the upvote arrow (▴) next to it. This will take you to the comment on GitHub, where you can vote for the comment using the up arrow button (↑).
If you want to add an alias to a list, please add a comment to the Github discussion of the appropriate list (see below) in the following format:
### alias_name: Short description of the alias
You can write closely coupled alias together by changing alias_name to alias_name_1 / alias_name_2.
Then add a reply to your own comment with the alias definition in the following format:
Any text you write at the top will be ignored.
#### Code
```toml
Alias code and any supporting lines here
If no supporting lines are needed, you can do this:
alias = ["command", "arg1", "arg2"]
If supporting lines are needed, do this (section order is not important):
[aliases]
alias = ["command", "custom_revset"]
[revset-aliases]
custom_revset = 'heads(::@ & bookmarks())'
```
#### Dependencies
Optional. Any extra tools needed for the alias? This includes shells such as Bash or Powershell, as these are not (always) available on all OSes. One entry per line.
Bash
Github client
#### Author
Optional. One author per line.
Name Name or username
#### Source
Optional. If the alias was taken from somewhere. Multiple sources can be listed, one per line.
https://address.to/source
#### Retrieved
Optional. When the code snippet was retrieved from the source. If not given, last edit date of the reply will be used. ISO-8601 format.
2026-01-06
#### Changes
Optional. You can explain any changes you made compared to a previous reply.
If the alias (source) updates over time, you can add more replies. The last reply with a valid definition will be used in the list.
The Github discussion is checked for updates several times per hour.
If you want to remove an alias from a list, prefer to just mark the alias as "removed" instead of removing the comment. This way we can keep the history of the alias.
To remove an alias, add a reply to the alias comment with the following content:
#### Remove
Reason for the removal.
Is a code snippet on this page outdated? Just click on the date to get to the Github "answer" and add a new reply with the updated info.
If you have a variant that improves the original alias, add a new reply to the alias and it will replace the alias in the list. Depending on the improvement, you might want to list both the old and new authors and sources.
If you have a new completely new variant of an alias or a competing version, just add a new "answer" to the Github discussion and the aliases can "compete" in the list!
The JJ configuration documentation describes how to use aliases.
In short, open ~/.config/jj/config.toml and add aliases under [aliases] and revset aliases under [revset-aliases].
You can list your current aliases with jj config list aliases [--include-defaults].
The list currently contains 21 aliases. Help us by voting on your favorites and adding more in the Github discussion!
| Votes | Alias | Description |
|---|---|---|
| ▴ 6 | tug |
Find the closest bookmark in history to advance it forward (edit workflow compatible)
tug = ["bookmark", "move", "--from", "closest_bookmark(@)", "--to", "closest_pushable(@)"]
[revset-aliases]
'closest_bookmark(to)' = 'heads(::to & bookmarks())'
'closest_pushable(to)' = 'heads(::to & ~description(exact:"") & (~empty() | merges()))'
[aliases]
tug = ["bookmark", "move", "--from", "closest_bookmark(@)", "--to", "closest_pushable(@)"]
Author: glehmann. Snippet updated: 2026-01-06. Sources: github.com |
| ▴ 1 |
bookmark_revs <name> bookmark_change_ids <name> |
List commit/change IDs a local bookmark has had over time
bookmark_revs = ["util", "exec", "--", "bash", "-c", """
(
[aliases]
# Get the commit IDs a bookmark has pointed locally to over time
# Usage: jj bookmark_revs <bookmark-name>
bookmark_revs = ["util", "exec", "--", "bash", "-c", """
(
# Grab the current commit ID in case the bookmark has never been set locally
jj log -n1 -G -T "concat(commit_id, '\n')" -r "$1"
jj op log -G -T "bookmark_set_revs('$1')"
) | uniq
""", ""]
# Get the change IDs a bookmark has pointed locally to over time
# Usage: jj bookmark_change_ids <bookmark-name>
bookmark_change_ids = ["util", "exec", "--", "bash", "-c", """
jj bookmark_revs "$1" | \
while read line; do
jj log -n1 -G -T "concat(change_id, '\n')" -r "$line"
done | uniq
""", ""]
[template-aliases]
# Get all commit IDs a bookmark has been set to locally over time from the op log.
# Note: It will not return any revisions if a bookmark has only been set remotely.
# " " around the branch name guarantees exact match.
# Matches both `create bookmark BOOKMARK pointing to commit COMMIT` and `point bookmark BOOKMARK to commit COMMIT`
'bookmark_set_revs(name)' = 'if(description.contains(" " ++ name ++ " ") && description.match(glob:"*bookmark*to commit*") != "",concat(description.match(regex:"([0-9a-z]{40})"),"\n"))'
Author: thomasa88. Deps: bash. Snippet updated: 2026-01-17. Sources: discord.com |
| ▴ 1 | restack /1 |
Rebase all my active branches on trunk (reachable through mutable() from @)
restack = ["rebase", "-o", "trunk()", "-s", "roots(trunk()..) & stack()"]
[revset-aliases]
'stack()' = 'stack(@)'
'stack(x)' = 'stack(x, 2)'
'stack(x, n)' = 'ancestors(reachable(x, mutable()), n)'
[aliases]
restack = ["rebase", "-o", "trunk()", "-s", "roots(trunk()..) & stack()"]
Author: Isaac Corbrey, Austin Seipp. Snippet updated: 2026-01-16. Sources: |
| ▴ 1 | l <revset> |
Show log for the given revset
l = ["log", "-r"]
Author: prkl. Snippet updated: 2026-01-09. Sources: discord.com |
| ▴ 1 | plan |
Create empty commit with description at the branch tip
plan = ["new", "--no-edit", "heads(@::)", "-m"]
Author: thomasa88. Snippet updated: 2026-01-06. Sources: github.com |
| ▴ 1 | collapse |
Collapse the current branch into one commit
collapse = ["squash", "-f", "branch_start(@)+::@", "-t", "branch_start(@)"]
[revset-aliases]
# From indigo
"branch_start(to)" = "heads(::to & trunk())+ & ::to"
[aliases]
collapse = ["squash", "-f", "branch_start(@)+::@", "-t", "branch_start(@)"]
Author: mrnugget, indigo. Snippet updated: 2026-01-06. Sources: github.com |
| ▴ 1 | difft |
Diff using difftastic (without having it as default)
difft = ["diff", "--tool", "difft"]
Snippet updated: 2026-01-06. Sources: github.com |
| ▴ 1 | issueprefix |
Add [ISSUE-<number>] prefix to every non-prefixed commit in the current branch
issueprefix = ["util", "exec", "--", "bash", "-c", """
set -euo pipefail
[aliases]
issueprefix = ["util", "exec", "--", "bash", "-c", """
set -euo pipefail
NUM=$1
PREFIX="[ISSUE-$NUM] "
# We don't actually need the editor, since we format the commit using the commit description template,
# but we want a command that returns success.
export JJ_EDITOR=/usr/bin/true
# Change all offending commits at once, to get only one operation in the operation log.
jj desc -r "((trunk()..@) | @::) ~ subject(glob:'\\[*')" --config templates.draft_commit_description="concat(\\"$PREFIX\\",coalesce(description, default_commit_description, \\"\n\\"))\"
""", ""]
Author: thomasa88. Deps: bash. Snippet updated: 2026-01-06. Sources: github.com |
| ▴ 1 | long |
Show detailed log
long = ["log", "-T", "builtin_log_detailed"]
Snippet updated: 2026-01-06. Sources: github.com |
| ▴ 1 | open /0 |
My branches (heads) that are not yet merged to trunk()
open = ["log", "-r", "heads(mine()) ~ ::trunk()"]
Snippet updated: 2026-01-06. Sources: github.com |
| ▴ 1 | open /1 |
My commits that are not yet merged to trunk()
open = ["log", "-r", "open()"]
[revset-aliases]
# stack(x, n) is the set of mutable commits reachable from 'x', with 'n'
# parents. 'n' is often useful to customize the display and return set for
# certain operations. 'x' can be used to target the set of 'roots' to traverse,
# e.g. @ is the current stack.
'stack()' = 'stack(@)'
'stack(x)' = 'stack(x, 2)'
'stack(x, n)' = 'ancestors(reachable(x, mutable()), n)'
# The current set of "open" works. It is defined as: all stacks that are
# reachable from my working copy, or any other commit I wrote.
# n = 1, meaning that nothing from `trunk()` is included, so all resulting
# commits are mutable by definition.
'open()' = 'stack(mine() | @, 1) ~ hidden()'
[aliases]
# Get all open stacks of work
open = ["log", "-r", "open()"]
Snippet updated: 2026-01-06. Sources: github.com |
| ▴ 1 | precommit |
Manually run pre-commit hooks
precommit = [
"util",
precommit = [
"util",
"exec",
"--",
"bash",
"-c",
"jj diff $1 $2 --name-only --no-pager | xargs pre-commit run --files", ""
]
Author: hdemers. Deps: bash. Snippet updated: 2026-01-07. Sources: github.com |
| ▴ 1 | slice |
View the entire branch being worked on in the log
slice = ["log", "-r", "slice()"]
[revset-aliases]
# View the entire branch being worked on
'slice()' = 'slice(@)'
'slice(from)' = 'ancestors(reachable(from, mutable()), 2)'
[aliases]
slice = ["log", "-r", "slice()"]
Author: jennings. Snippet updated: 2026-01-06. Sources: github.com |
| ▴ 1 | sync |
Fetch from all remotes
sync = ['git', 'fetch', '--all-remotes']
Snippet updated: 2026-01-06. Sources: github.com |
| ▴ 1 | fetch-pr <num> |
Fetch PR from origin and create pr-<num> bookmark (using git)
fetch-pr = ['util', 'exec', '--', 'bash', '-c', '''
count=1
fetch-pr = ['util', 'exec', '--', 'bash', '-c', '''
count=1
while true; do
git fetch origin pull/$1/head:pr-$1-$count && break
((count++))
done
jj git import
''', '']
Author: ase. Deps: bash, git. Snippet updated: 2026-01-17. Sources: discord.com |
| ▴ 1 | restack /0 |
Rebase all my branches/megamerge on trunk().
restack = ["rebase", "-o", "trunk()", "-s", "roots(trunk()..) & mutable()"]
[aliases]
# `jj restack` to rebase your changes onto `trunk()`
restack = ["rebase", "-o", "trunk()", "-s", "roots(trunk()..) & mutable()"]
Author: Isaac Corbrey. Snippet updated: 2026-01-16. Sources: discord.com |
| ▴ 0 | blame |
Annotate file with authors. Shorthand for jj file annotate.
blame = ["file", "annotate"]
Snippet updated: 2026-01-06. Sources: github.com |
| ▴ 0 | credit |
Annotate file with authors. Shorthand for jj file annotate.
credit = ["file", "annotate"]
Snippet updated: 2026-01-06. Sources: github.com |
| ▴ 0 | short |
Show oneline log
long = ["log", "-T", "builtin_log_oneline"]
Snippet updated: 2026-01-06. Sources: github.com |
| ▴ 0 | rebase-all |
Rebase all my branches on trunk()
rebase-all = ["rebase", "-s", "(::trunk())+ & mutable()", "-o", "trunk()"]
Author: steveklabnik. Snippet updated: 2026-01-16. Sources: lobste.rs |
| ▴ 0 |
track-github-PR untrack-github-PR |
fetching and pushing to someone else's PR on Github, with additional remote bookmark to show PR's number (using git, gh)
track-github-PR = ["util", "exec", "--", 'sh', '-euxc', '''
PR=$1
[aliases]
track-github-PR = ["util", "exec", "--", 'sh', '-euxc', '''
PR=$1
gh pr view --json headRepository,headRefName,headRepositoryOwner $PR --jq '"
set_remote() {
jj 2>/dev/null git remote add \"$1\" \"$2\" ||
jj git remote set-url \"$1\" \"$2\"
}
set_remote \(.headRepositoryOwner.login) git@github.com:\(.headRepositoryOwner.login)/\(.headRepository.name)
jj git fetch --remote \(.headRepositoryOwner.login) --branch \(.headRefName)
jj bookmark track \(.headRefName)@\(.headRepositoryOwner.login)
origin=$(gh repo view --json owner,name --jq .owner.login)
set_remote \"$origin\" \"$(gh repo view --json sshUrl --jq .sshUrl)\"
git fetch --force --update-head-ok \"$origin\" \"refs/pull/'"$PR"'/head:refs/remotes/$origin/pull/'"$PR"'\"
"' |
sh -euxs
''', "jj-track-github-PR"]
untrack-github-PR = ["util", "exec", "--", 'sh', '-euxc', '''
PR=$1
gh pr view --json headRepository,headRefName,headRepositoryOwner $PR --jq '"
jj bookmark forget \(.headRefName) || true
origin=$(gh repo view --json owner,name --jq .owner.login)
git for-each-ref --format \"delete %(refname)\" \\
\"refs/remotes/\(.headRepositoryOwner.login)/\(.headRefName)\" \\
\"refs/remotes/$origin/pull/'"$PR"'\" |
tee /dev/stderr |
git update-ref --stdin
"' |
sh -euxs
''', "jj-untrack-github-PR"]
Author: ju1m. Deps: sh, gh. Snippet updated: 2026-01-07. Sources: github.com |
The list currently contains 11 revset aliases. Help us by voting on your favorites and adding more in the Github discussion!
| Votes | Revset Alias | Description |
|---|---|---|
| ▴ 1 | recent() |
Recently created commits (1 month)
'recent()' = 'recent(all())'
'recent(r)' = 'r & committer_date(after:"1 month ago")'
Snippet updated: 2026-01-11. Sources: zerowidth.com |
| ▴ 1 | streams([x]) |
Find the closest bookmark(s) to (not after 'x').
"streams()" = "heads(::@ & bookmarks())"
"streams(x)" = "heads(::x & bookmarks())"
Author: bryce. Snippet updated: 2026-01-11. Sources: github.com |
| ▴ 1 | at |
Alternative to '@' in shells that don't support '@'
at = "@"
Author: jennings. Snippet updated: 2026-01-09. Sources: github.com |
| ▴ 1 | mine() |
Commits are mine if author if either e-mail or name matches, as opposed to only name. Overrides built-in `mine()`.
"mine()" = "author(exact:'My Name') | author(exact:'my.name@email.com')"
Author: bryce. Snippet updated: 2026-01-09. Sources: github.com |
| ▴ 1 | slice([from]) |
The entire branch being worked on
'slice()' = 'slice(@)'
'slice(from)' = 'ancestors(reachable(from, mutable()), 2)'
# View the entire branch being worked on
'slice()' = 'slice(@)'
'slice(from)' = 'ancestors(reachable(from, mutable()), 2)'
Author: jennings. Snippet updated: 2026-01-09. Sources: github.com |
| ▴ 1 | why_immutable(r) |
Find what makes revision 'r' immutable
'why_immutable(r)' = "(r & immutable()) | roots(r:: & immutable_heads())"
Author: jennings, hotsphink. Snippet updated: 2026-01-09. Sources: github.com |
| ▴ 1 | closest_bookmark(to) |
The closest bookmark(s) to 'to' (not after 'to')
'closest_bookmark(to)' = 'heads(::to & bookmarks())'
Snippet updated: 2026-01-08. Sources: github.com, discord.com |
| ▴ 1 | closest_pushable(to) |
The closest pushable commit to 'to' (not after 'to')
'closest_pushable(to)' = 'heads(::to & ~description(exact:"") & (~empty() | merges()))'
Snippet updated: 2026-01-08. Sources: github.com |
| ▴ 1 | stack([x[, n]]) |
The set of mutable commits reachable from 'x', with 'n' parents.
'stack()' = 'stack(@)'
'stack(x)' = 'stack(x, 2)'
# stack(x, n) is the set of mutable commits reachable from 'x', with 'n'
# parents. 'n' is often useful to customize the display and return set for
# certain operations. 'x' can be used to target the set of 'roots' to traverse,
# e.g. @ is the current stack.
'stack()' = 'stack(@)'
'stack(x)' = 'stack(x, 2)'
'stack(x, n)' = 'ancestors(reachable(x, mutable()), n)'
Author: aseipp. Snippet updated: 2026-01-08. Sources: github.com |
| ▴ 1 | tip |
The latest commit on the branch. Works with squash workflow. Use: jj new tip
tip = "exactly(heads(@-::~@), 1)"
Author: algmyr. Snippet updated: 2026-01-07. Sources: discord.com |
Last updated 2026-01-21 18:52 UTC