About
jj is a Git-compatible version control system that is both simple and powerful.
See the installation instructions to get started.
Release highlights
-
Templates now have a top-level
revset(revset: Stringify) -> List<Commit>
function for evaluating revsets during templating. -
In colocated workspaces,
jj describe -r@,jj restore --into=@, etc. no
longer reset the staging area, just as snapshotting doesn't.jj new @-still
resets it.
Breaking changes
-
In non-colocated workspaces,
jj git fetchandpushno longer update
remote-tracking Git refs. Usejj git exportto export remote bookmarks to
Git. -
In non-colocated workspaces,
jj git import; jj undo; jj git importno longer
re-imports external changes. Runjj git exportto reflect undone changes in
Git.jj git fetch; jj undo; jj git fetchcontinues to work as expected. -
Timestamp.format()now follows jiff's strftime
syntax instead of
chrono's. Most directives, including the default format, are unchanged, but:%vand%+are no longer supported. Use%e-%b-%Yand
%Y-%m-%dT%H:%M:%S%.3f%:z(which always includes milliseconds) instead.%c,%x, and%rproduce different output. For example,%xnow
formats as2001 M07 8rather than07/08/01.%fnow prints only as many digits as needed rather than always 9. Use
%9for%Nfor the old behavior. Similarly,%.fno longer pads to 3, 6,
or 9 digits, so it formats as.12rather than.120.%Znow prints a time zone abbreviation. Use%:zto get an offset.%:::znow includes the minutes of an offset when they are non-zero.- New directives and flags such as
%N,%Q,%^a, and%5Yare now
accepted.%#zno longer panics. json(timestamp)now prints a UTC time zone offset as+00:00instead of
Z.
-
The bookmarks and tags list now include absent targets for conflicted
bookmarks and tags. The.removed_targets()and.added_targets()template
methods now returnList<Option<Commit>>.
New features
-
jj git pushwithgit.sign-on-pushenabled now signs commits in a
separate operation before the push, so commits stay signed if the push
fails and a new push doesn't have to sign them again. -
Diff hunk headers now include symbol context even for unsupported languages.
-
jj resolvegained a built-in:editormerge tool that opens the conflicted
file with conflict markers in your text editor. Unlike the other merge tools,
it supports conflicts with more than two sides. -
jj config gcnow also cleans up workspace configs whose paths no longer
exist. -
Commit.contained_in()now accepts aStringifyinstead of aStringLiteral.
This enables dynamic query building during templating. -
Templates now have a top-level
revset(revset: Stringify) -> List<Commit>
function for evaluating revsets during templating. -
The
TreeEntrytemplate type now has.removed_values() -> List<Option<TreeValue>>
and.added_values() -> List<Option<TreeValue>>methods, andTreeValuenow
exposes.object_id(),.file_type(), and.executable()methods for
inspecting each side of a (possibly conflicted) tree entry. -
The
WorkspaceReftemplate type now has a.current_workspace() -> Boolean
method, which can be used to identify the current workspace. This is slightly
different thanself.target().current_working_copy()because multiple
workspaces can point to the same commit. -
jj next/jj prevnow accept a change ID prefix when prompting for the
target commit. The specialqquit choice was removed; cancel with EOF.
#9790 -
jj convergenow accepts a change ID prefix when prompting for the change
to converge. The specialqabort choice was removed; canceling with EOF now
exits with an error (previouslyqaborted successfully). -
jj file searchnow detects binary files (any null byte in the first 8000
bytes) and emitsBinary file matches: <path>instead of dumping raw bytes to
stdout. Use--binary-as-textto force text treatment, or--skip-binaryto
skip binary files entirely.
Fixed bugs
-
jj git pushno longer validates (e.g. for empty descriptions) commits that
are already on the remote as a tag. -
jj git fetchno longer creates additional refs based on non-standard Git
remote.<name>.fetchconfiguration. -
jj gerrit uploadno longer rejects uploading empty merge commits. -
The operations created by
jj workspace addare now attributed to the
workspace the command was run in, sojj undothere undoes them instead of
refusing to undo an operation from another workspace. -
jj workspace add -rwith an invalid revision no longer leaves a
half-created workspace behind. -
Shell completion now suggests tag names for
jj tag track,jj tag untrack,
jj tag list,jj git fetch --tag, andjj git push --tag. -
Fixed tag deletion with
jj git fetch --tag=NAME. -
jj workspace removecan now remove stale workspaces.
#10276 -
Fixed issue with
config-schema.jsonwhere Taplo (TOML parsing library) would
flag anyaliasesdefined as a table but without an explicit
.enabled = trueas "valid under more than one of the schemas". This affected
downstream tools such as editor extensions showing errors in perfectly valid
config files. -
Fixed a race condition in colocated workspaces where concurrent
jj git fetch
andjjcommands could import partially fetched refs, causing divergence.
#7349 -
Fixed a race condition in colocated workspaces where changes to the Git index
made by a concurrent Git process could get lost. -
In colocated workspaces, Git export failures are no longer misidentified as
external changes. Those changes are now re-exported on the nextjj
invocation. #10478 -
In colocated workspaces,
jj describe -r@,jj restore --into=@, etc. no
longer reset the staging area, just as snapshotting doesn't.jj new @-still
resets it. -
jj runnow materializes conflicts usingui.conflict-marker-styleinstead
of always using thesnapshotstyle.
#10390 -
The Git backend now leaves out the root commit as a parent of a merge commit
instead of failing. This fixes abandoning a child of the root commit that is a
parent of a merge commit, including when a Git import abandons it.
#8076 -
On Unix, repository files under
.jjare now created with default file
permissions. -
Racy
jj config setinvocations no longer corrupt the target file. The last
save wins; changes from other concurrent invocations may be lost.
#10350 -
Date patterns such as
after:"2024-03-10 03:30"are now resolved with the
correct UTC offset on days with a daylight savings transition. Previously,
the offset from the start of the day was used, so times after were off
by an hour. Likely a niche bug fix, but a bug fix nonetheless! -
Deeply nested revset, fileset, and template expressions are now rejected
instead of causing a crash.
#10071 -
In graph output, an elided edge that passes through a merge or fork line is
now drawn as elided (╷) before reaching the node, instead of looking like a
direct edge. Consecutive unconnected nodes, such as in thejj op show
graph, are now separated by a blank line so they don't look connected. -
jj logno longer draws a commit as a merge with two elided edges to the
same commit when there's a merge between them whose parents both lead to
that commit. -
The "Did you mean" hint for a mistyped bookmark, revision, or function no
longer lists every similar name. It now shows the 5 most similar ones,
most similar first, followed by e.g.or 20 others.
#8017
Contributors
Thanks to the people who made this release happen!
- Aaron Sood (@arsood)
- abdoul-kader keita (@kkeita)
- abgox (@abgox)
- Alexey Sokolov (@alexey-arista)
- ase (@adamse)
- Brice Figureau (@masterzen)
- Bryan O'Sullivan (@bos)
- Byron (@Byron)
- Caleb White (@calebdw)
- David Barsky (@davidbarsky)
- David Rieber (@drieber)
- Eyüp Can Akman (@eyupcanakman)
- Greg Falcon (@vslashg)
- JamBalaya56562 (@JamBalaya56562)
- Jonas Natten (@jnatten)
- Joseph Lou (@josephlou5)
- Josh McKinney (@joshka)
- Kevin Liao (@kevincliao)
- Martin von Zweigbergk (@martinvonz)
- Marukome0743 (@Marukome0743)
- Matt Stark (@matts1)
- Nitzan Raz (@BackSlasher)
- Philip Metzger (@PhilipMetzger)
- Rebecca Turner (@9999years)
- Sami Hiltunen (@SamiHiltunen)
- Shardul Natu (@kiranani)
- Siva Mahadevan (@svmhdvn)
- xuanchangfeng (@xuanchangfeng)
- Yuya Nishihara (@yuja)