About
jj is a Git-compatible version control system that is both simple and powerful. See
the installation instructions to get started.
Release highlights
- Per-repo and per-workspace config is now stored outside the repo, for security
reasons. This is not a breaking change because we automatically migrate
legacy repos to this new format..jj/repo/config.tomland
.jj/workspace-config.tomlshould no longer be used.
Breaking changes
-
The minimum supported
gitcommand version is now 2.41.0. macOS users will
need to either upgrade "Developer Tools" to 26 or install Git from
e.g. Homebrew. -
Deprecated
ui.always-allow-large-revsetssetting andall:revset modifier
have been removed. -
<name>@<remote>revset symbols can also be resolved to remote tags. Tags are
prioritized ahead of bookmarks. -
Legacy placeholder support used for unset
user.nameoruser.emailhas been
removed. Commits containing these values will now be pushed withjj git push
without producing an error. -
If any side of a conflicted file is missing a terminating newline, then the
materialized file in the working copy will no longer be terminated by a
newline.
Deprecations
- The revset function
diff_contains()has been renamed todiff_lines().
New features
-
jj git fetchnow shows details of abandoned commits (change IDs and
descriptions) by default, matching thejj abandonoutput format.
#3081 -
jj workspace rootnow accepts an optional--nameargument to show
the root path of the specified workspace (defaults to the current one). When
given a workspace that was created before this release, it errors out. -
jj git push --bookmark <name>will now automatically track the bookmark if
it isn't tracked with any remote already. -
Add
git_web_url([remote])template function that converts a git remote URL
to a web URL, suitable for opening in a browser. Defaults to the "origin"
remote. -
New
divergent()revset function for divergent changes. -
String pattern values in revsets and templates can now be substituted by
aliases. For example,grep(x) = description(regex:x)now works. -
A new config option
remotes.<name>.auto-track-created-bookmarksbehaves
similarly toauto-track-bookmarks, but it only applies to bookmarks created
locally. Setting it to"*"is now the closest replacement for the deprecated
git.push-new-bookmarksoption. -
jj tag listcan now be filtered by revset. -
Conflict markers will use LF or CRLF as the line ending according to the
contents of the file.
#7376 -
New experimental
jj git fetch --tagflag to fetch tags in the same way as
bookmarks. If specified, tags won't be fetched implicitly, and only tags
matching the pattern will be fetched as<name>@<remote>tags. The fetched
remote tags will be tracked by the local tags of the same name. -
New
remote_tags()revset function to query remote tags. -
New builtin
hyperlink()template function that gracefully falls back to
text when outputting to a non-terminal, instead of emitting raw OSC 8 escape
codes. #7592
Fixed bugs
-
jj git init --colocatenow refuses to run inside a Git worktree, providing
a helpful error message with alternatives.
#8052 -
jj git pushnow ensures that tracked remote bookmarks are updated even if
there are no mappings in the Git fetch refspecs.
#5115 -
jj git fetch/pushnow forwards most ofgitstderr outputs such as
authentication requests. #5760 -
Conflicted bookmarks and tags in
trunk()will no longer generate verbose
warnings. The configuredtrunk()alias will temporarily be disabled.
#8501 -
Dynamic shell completion for
jj config unsetnow only completes
configuration options which are set.
#7774 -
Dynamic shell completion no longer attempts to resolve aliases at the
completion position. This previously prevented a fully-typed alias from
being accepted on some shells and replaced it entirely with its expansion on
bash. Now, the completion will only resolve the alias, and suggest candidates
accordingly, after the cursor has been advanced to the next position.
#7773 -
Setting the editor via
ui.editor,$EDITOR, orJJ_EDITORnow respects shell quoting. -
jj gerrit uploadwill no longer swallow errors and surface if changes fail
to get pushed to gerrit.
#8568 -
jj file track --include-ignorednow works whenfsmonitor.backend="watchman".
#8427 -
Conflict labels are now preserved correctly when restoring files from commits
with different conflict labels. -
The empty tree is now always written when the working copy is empty.
#8480 -
When using the Watchman filesystem monitor, changes to .gitignore now trigger
a scan of the affected subtree so newly unignored files are discovered.
#8427 -
--quietnow hides progress bars.
Contributors
Thanks to the people who made this release happen!
- Benjamin Davies (@Benjamin-Davies)
- Bryce Berger (@bryceberger)
- Chris Rose (@offbyone)
- Daniel Morsing (@DanielMorsing)
- David Fröhlingsdorf (@2079884FDavid)
- David Higgs (@higgsd)
- David Rieber (@drieber)
- Federico G. Schwindt (@fgsch)
- Gaëtan Lehmann (@glehmann)
- George Christou (@gechr)
- itstrivial
- Jeff Turner (@jefft)
- Jonas Greitemann (@jgreitemann)
- Jonas Helgemo (@jonashelgemo)
- Joseph Lou (@josephlou5)
- Kaiyi Li (@06393993)
- Lukas Wirth (@Veykril)
- Martin von Zweigbergk (@martinvonz)
- Matt Stark (@matts1)
- Paul Smith (@paulsmith)
- Pavan Kumar Sunkara (@pksunkara)
- Philip Metzger (@PhilipMetzger)
- Remo Senekowitsch (@senekor)
- Sami Jawhar (@sjawhar)
- Scott Taylor (@scott2000)
- Simone Cattaneo (@simonecattaneo91)
- Steve Klabnik (@steveklabnik)
- tom (@lecafard)
- Vincent Ging Ho Yim (@cenviity)
- _WD_ (@0WD0)
- xtqqczze (@xtqqczze)
- Yuya Nishihara (@yuja)
- yz (@yzheng453)