v0.39.0

sxyazi/yaziv0.39.0Mar 4, 2026by thoughtpolice

AI Summary

This release significantly enhances the jj version control system with new commands for revision management and bookmark automation, alongside improvements to templates, filesets, and Git integration.

Key Highlights

  • New `jj arrange` command for TUI reordering and abandoning revisions
  • New `jj bookmark advance` command for automatic bookmark movement
  • Support for push options in `jj git push`
  • Templates now support list manipulation methods

Breaking Changes

  • Dropped support for legacy index files written by jj < 0.33
  • Removed deprecated config options (`core.fsmonitor` and `core.watchman.register-snapshot-trigger`)
  • Removed deprecated command `jj op undo` (use `jj op revert` or `jj undo`/`redo`) instead

New Features

  • `jj arrange` command
  • `jj bookmark advance` command
  • Push options support (`--option` flag)
  • Template list manipulation methods (`first()`, `last()`, etc.)
  • New `jj util snapshot` command
  • Revsets pattern aliases (`name:x`)

Full Release Notes

### About

jj is a Git-compatible version control system that is both simple and powerful. See
the [installation instructions](https://jj-vcs.github.io/jj/v0.39.0/install-and-setup/) to get started.

### Release highlights

* `jj arrange` command brings up a TUI where you can reorder and abandon
  revisions. [#1531](https://github.com/jj-vcs/jj/issues/1531)

* `jj bookmark advance` automatically moves bookmarks forward to a
  target revision (defaults to `@`) using customization points
  `revsets.bookmark-advance-from` and `revsets.bookmark-advance-to`.
  It is heavily inspired by the longstanding community alias `jj tug`.

### Breaking changes

* Dropped support for legacy index files written by jj < 0.33. New index files
  will be created as needed.

* The following deprecated config options have been removed:
  - `core.fsmonitor`
  - `core.watchman.register-snapshot-trigger`

* The deprecated command `jj op undo` has been removed. Use `jj op revert` or
  `jj undo`/`redo` instead.

### Deprecations

* `jj debug snapshot` is deprecated in favor of `jj util snapshot`. Although
  this was an undocumented command in the first place, it will be removed after
  6 months (v0.45.0) to give people time to migrate away.

### New features

* Add support for push options in `jj git push` with the `--option` flag.
  This allows users to pass options to the remote server when pushing commits.
  The short alias `-o` is also supported.

* `jj new` now evaluates the `new_description` template to populate the
  initial commit description when no `-m` message is provided.

* Templates now support `first()`, `last()`, `get(index)`, `reverse()`,
  `skip(count)`, and `take(count)` methods on list types for more flexible
  list manipulation.

* New `builtin_draft_commit_description_with_diff` template that includes the
  diff in the commit description editor, making it easier to review changes
  while writing commit messages.

* Revsets and templates now support `name:x` pattern aliases such as `'grep:x' =
  'description(regex:x)'`.

* Filesets now support [user aliases](docs/filesets.md#aliases).

* `jj workspace add` now links with relative paths. This enables workspaces to work
  inside containers or when moved together. Existing workspaces with absolute paths
  will continue to work as before.

* `jj undo` now also outputs what operation was undone, in addition to the
  operation restored to.

* Bookmarks with two or more consecutive `-` characters no longer need to be quoted
  in revsets. For example, `jj diff -r '"foo--bar"'` can now be written as `jj diff -r foo--bar`.

* New flag `--simplify-parents` on `jj rebase` to apply the same transformation
  as `jj simplify-parents` on the rebased commits.
  [#7711](https://github.com/jj-vcs/jj/issues/7711)

* `jj rebase --branch` and `jj rebase --source` will no longer return an error
  if the given argument resolves to an empty revision set
  (`jj rebase --revisions` already behaved this way). Instead, a message will be
  printed to inform the user why nothing has changed.

* Changed Git representation of conflicted commits to include files from the
  first side of the conflict. This should prevent unchanged files from being
  highlighted as "added" in editors when checking out a conflicted commit in a
  colocated workspace.

* New template function `Timestamp::since(ts)` that returns the `TimestampRange`
  between two timestamps. It can be used in conjunction with `.duration()` in
  order to obtain a human-friendly duration between two `Timestamp`s.

* Added new `jj util snapshot` command to manually or programmatically trigger a
  snapshot. This introduces an official alternative to the
  previously-undocumented `jj debug snapshot` command. The Watchman integration
  has also been updated to use this command instead.

* Changed background snapshotting to suppress stdout and stderr to avoid long
  hangs.

* `jj gerrit upload` now supports a variety of new flags documented in
  [gerrit's documentation](https://gerrit-review.googlesource.com/Documentation/user-upload.html).
  This includes, for example, `--reviewer=foo@example.com` and
  `--label=Auto-Submit`.

* `jj gerrit upload` now recognizes Change-Id explicitly set via the alternative
  trailer `Link`, and will generate a `Link: <review-url>/id/<change-id>` trailer
  if `gerrit.review-url` option is set.

* `jj gerrit upload` no longer requires the `-r` flag, and will default to
  uploading what you're currently working on.

* Templates now support `Serialize` operations on the result of `map()` and
  `if()`, when supported by the underlying type.

* `jj bookmark rename` now supports `--overwrite-existing` to allow renaming a
  bookmark even if the new name already exists, effectively replacing the
  existing bookmark.

* Conditional configuration based on environment variables with `--when.environments`.
  [#8779](https://github.com/jj-vcs/jj/pull/8779)

### Fixed bugs

* Windows: use native file locks (`LockFileEx`) instead of polling with file
  creation, fixing issues with "pending delete" semantics leaving lock files
  stuck.

* `jj` now safely detaches the `HEAD` of alternate Git worktrees if their
  checked-out branch is moved or deleted during Git export.

* `jj file track --include-ignored` now works when `fsmonitor.backend="watchman"`.
  [#8427](https://github.com/jj-vcs/jj/issues/8427)

### Contributors

Thanks to the people who made this release happen!

* Aaron Christiansen (@AaronC81)
* Andy Brenneke (@abrenneke)
* Anton Älgmyr (@algmyr)
* Austin Seipp (@thoughtpolice)
* Benjamin Tan (@bnjmnt4n)
* Bram Geron (@bgeron)
* Bryce Berger (@bryceberger)
* Caleb White (@calebdw)
* countskm (@countdigi)
* David Higgs (@higgsd)
* Evan Simmons (@estk)
* Fedor Sheremetyev (@sheremetyev)
* Gaëtan Lehmann (@glehmann)
* George Christou (@gechr)
* Hubert Lefevre (@Paluche)
* Ian (@chronologos)
* Ilya Grigoriev (@ilyagr)
* Jaen (@jaens)
* Joseph Lou (@josephlou5)
* Josh Steadmon (@steadmon)
* Martin von Zweigbergk (@martinvonz)
* Matt Kulukundis (@fowles)
* Matt Stark (@matts1)
* max (@pr2502)
* Nika Layzell (@mystor)
* Philip Metzger (@PhilipMetzger)
* Richard Smith (@zygoloid)
* Scott Taylor (@scott2000)
* Steve Klabnik (@steveklabnik)
* Theodore Dubois (@tbodt)
* William Phetsinorath (@shikanime)
* xtqqczze (@xtqqczze)
* Yuya Nishihara (@yuja)