About
jj is a Git-compatible version control system that is both simple and powerful. See
the installation instructions to get started.
Release highlights
- Support for fetching and pushing tags has now been stabilized. Tags can be
tracked or untracked just like bookmarks. Tracked tags are pushed by default.
Breaking changes
-
jj git fetchnow fetches tags the same way it fetches bookmarks. Tags are
fetched as<name>@<remote>, and these remote tags are automatically tracked
by local tags of the same name. Runningjj git fetchin an existing
repository will re-fetch all tags to initialize the tracking state.Git's
tagOptis no longer respected. To disable tag fetching, set
remotes.<name>.fetch-tags = '~*'in the jj configuration. -
jj git clone --fetch-tags=all|none|includedis removed in favor of
--tag=PATTERN. -
jj git push --allnow pushes all tags in addition to bookmarks. -
The
WorkspaceRef.root()andRepoPath.absolute()template functions now
returnOption<FsPath>andFsPathrespectively, instead ofString. The
pathkeyword injj config listtemplates now returnsOption<FsPath>. -
jj file searchnow prints every matched line prefixed by the file path,
instead of only the file paths of files containing a match. Use
--name-onlyfor the previous behavior.
#9399 -
Passing an argument more than once is no longer an error. The last occurrence
wins, sojj --no-pager --no-pager versionandjj log -n 5 -n 10now work,
and an argument baked into an alias or a wrapper can be given explicitly as
well. Arguments that can be specified multiple times, such as--configand
jj log -r, are unaffected and still collect all of their values.
#8101
#9859
Deprecations
None
New features
-
New
merge_point()revset function which (similar tofork_point) finds the
point where multiple branches merge. -
jj workspace listnow shows workspace roots by default. The output can be
customized withtemplates.workspace_listor-T, andWorkspaceRef.root()
returns an optionalFsPathvalue.
#9713,
#9826 -
New
try(expr, fallback...)template function to suppress runtime errors. -
jj runnow processes revisions from oldest to newest by default. The start
order is guaranteed: each revision begins execution only after the previous
one has started, even with--jobshigher than 1. -
jj rungained a--passthroughflag that connects the subprocess's
stdout/stderr directly to the terminal instead of capturing output. -
jj rungained a--ignore-changesflag to avoid editing any revisions even
if the command modifies the working copy. -
jj rungained a--ignore-errorsflag to continue running against the
remaining revisions even if the command exits with a nonzero exit code. -
jj file searchnow supports-n/--line-numberto prefix each match with
its 1-based line number within the file. -
jj git pushgained a--allow-conflictsflag to allow pushing commits
containing conflicts. -
New
jj tag track/untrackcommands to associate local tags with remotes.
Note that fetched tags are tracked by default. -
Added
builtin_log()revset alias for the built-in defaultjj logrevset.
revsets.lognow defaults tobuiltin_log(), so custom log revsets can
reuse the built-in default instead of copying its full expression. -
Added config option
diff.stat.max-bar-widthfor use with--statto limit
the++--bar width. In the templating language,diff.stat()can optionally
take a second (positional or named) argumentmax_bar_widthfor an equivalent
effect. -
jj absorbnow supports--interactive/-i/--toolto let you
interactively choose which hunks from the source to consider for absorption.
This is useful when you only want to absorb part of a commit without first
splitting it. Any hunks that are not selected or cannot be absorbed remain in
the source commit.
Fixed bugs
-
Recursive alias definitions are detected more precisely. jj can now expand
aliases that are simply repeated. For example, with the aliasjj = [], the
commandjj jj jjwill resolve tojj. Aliases can also fall back to the
default command. For example, with the aliasi = ["--ignore-working-copy"],
jj iwill resolve tojj --ignore-working-copy. -
Git temporary files are now cleaned up more reliably in the presence of
signals (e.g.Ctrl-C). This should reduce the rate of "Could not acquire
lock for index file" errors.
(#7530) -
Fixed Git HEAD mismatch after the working copy became immutable.
#9827 -
jjnow creates a new working-copy revision as soon as the one of the current
workspace becomes immutable, as well as during snapshotting. This brings the
behavior closer tojj0.42 and earlier. -
Snapshotting no longer fails if the working copy contains a path whose name
isn't valid UTF-8. Such paths can't be tracked, so they are now skipped and
reported as a warning instead.
#9774 -
Fixed failure when reading configuration in copied repo with an empty
repo-level configuration directory. -
jj diffandjj statusno longer omit a rename or copy in a merge commit
when the renamed source is present in more than one parent. The identical copy
record reported for each parent was mistaken for a conflict and discarded.
#9752 -
jj runno longer panics when its revset includes a conflicted commit. The
conflict is now preserved in the rewritten commit.
#9747 -
Fixed a panic when passing overly-large length parameters to ID templater
functions (commit_id.short(),commit_id.shortest(), etc.).
#9833 -
jj git importandexportin colocated workspaces are now disabled by
default. These commands usually do nothing, but they had a race condition.
Contributors
Thanks to the people who made this release happen!
- Aaron Bies (@slerpyyy)
- Ada Alakbarova (@ada4a)
- Alexandre Hallaine (@alexandre-hallaine)
- Amaan Qureshi (@amaanq)
- Austin Seipp (@thoughtpolice)
- Caleb White (@calebdw)
- Chawye Hsu (@chawyehsu)
- David Rieber (@drieber)
- Gaëtan Lehmann (@glehmann)
- hexbinoct (@hexbinoct)
- ivelieu (@ivelieu)
- Joseph Lou (@josephlou5)
- Josh McKinney (@joshka)
- Josh Steadmon (@steadmon)
- Kevin Liao (@kevincliao)
- Luna Schwalbe (@lunagl)
- Martin von Zweigbergk (@martinvonz)
- Matt Van Horn (@mvanhorn)
- Nika Layzell (@mystor)
- Niko Savola (@nikosavola)
- Nitzan Raz (@BackSlasher)
- Noah Lev (@camelid)
- OlshaMB (@OlshaMB)
- Philip Metzger (@PhilipMetzger)
- Remo Senekowitsch (@senekor)
- Rob Pilling (@bobrippling)
- Stephen Jennings (@jennings)
- Techcable (@Techcable)
- TogarashiPepper (@TogarashiPepper)
- Vladimir Petrzhikovskii (@0xdeafbeef)
- Waleed Khan (@arxanas)
- Wang Yuantao (@0WD0)
- xtqqczze (@xtqqczze)
- Yash Bavadiya (@xevrion)
- Yuya Nishihara (@yuja)