v0.44.0

boratanrikulu/gecitv0.44.0Aug 6, 2026by martinvonz

AI Summary

This release stabilizes Git tag fetching and pushing in jj, introduces a new merge point revset function, and enhances the `jj run` command with subprocess passthrough and error handling capabilities.

Key Highlights

  • Git tags fetching and pushing are now stabilized and tracked by default.
  • New `jj run` flags include `--passthrough`, `--ignore-changes`, and `--ignore-errors`.
  • New `merge_point()` revset function to find branch merge points.
  • Improved `jj file search` with line number support and full path printing.

Breaking Changes

  • `jj git fetch` now fetches tags as `<name>@<remote>` and tracks them automatically.
  • `jj git clone --fetch-tags=all|none|included` is removed in favor of `--tag=PATTERN`.
  • `jj git push --all` now pushes all tags in addition to bookmarks.
  • `WorkspaceRef.root()` and `RepoPath.absolute()` now return `Option<FsPath>` and `FsPath` respectively.
  • `jj file search` now prints every matched line prefixed by the file path instead of just file paths.
  • Passing an argument more than once is no longer an error; the last occurrence wins.

New Features

  • New `merge_point()` revset function.
  • New `try(expr, fallback...)` template function.
  • `jj workspace list` now shows workspace roots by default.
  • `jj run` processes revisions oldest to newest by default.
  • `jj file search` supports `-n`/`--line-number`.
  • New `jj tag track`/`untrack` commands.
  • Added `builtin_log()` revset alias.
  • Added `diff.stat.max-bar-width` config option.
  • `jj absorb` now supports `--interactive`/`--tool`.

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.44.0/install-and-setup/) 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 fetch` now 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. Running `jj git fetch` in an existing
  repository will re-fetch all tags to initialize the tracking state.

  Git's `tagOpt` is no longer respected. To disable tag fetching, set
  `remotes.<name>.fetch-tags = '~*'` in the jj configuration.

* `jj git clone --fetch-tags=all|none|included` is removed in favor of
  `--tag=PATTERN`.

* `jj git push --all` now pushes all tags in addition to bookmarks.

* The `WorkspaceRef.root()` and `RepoPath.absolute()` template functions now
  return `Option<FsPath>` and `FsPath` respectively, instead of `String`. The
  `path` keyword in `jj config list` templates now returns `Option<FsPath>`.

* `jj file search` now prints every matched line prefixed by the file path,
  instead of only the file paths of files containing a match. Use
  `--name-only` for the previous behavior.
  [#9399](https://github.com/jj-vcs/jj/issues/9399)

* Passing an argument more than once is no longer an error. The last occurrence
  wins, so `jj --no-pager --no-pager version` and `jj log -n 5 -n 10` now 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 `--config` and
  `jj log -r`, are unaffected and still collect all of their values.
  [#8101](https://github.com/jj-vcs/jj/issues/8101)
  [#9859](https://github.com/jj-vcs/jj/issues/9859)

### Deprecations

None

### New features

* New `merge_point()` revset function which (similar to `fork_point`) finds the
  point where multiple branches merge.

* `jj workspace list` now shows workspace roots by default. The output can be
  customized with `templates.workspace_list` or `-T`, and `WorkspaceRef.root()`
  returns an optional `FsPath` value.
  [#9713](https://github.com/jj-vcs/jj/pull/9713),
  [#9826](https://github.com/jj-vcs/jj/pull/9826)

* New `try(expr, fallback...)` template function to suppress runtime errors.

* `jj run` now 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 `--jobs` higher than 1.

* `jj run` gained a `--passthrough` flag that connects the subprocess's
  stdout/stderr directly to the terminal instead of capturing output.

* `jj run` gained a `--ignore-changes` flag to avoid editing any revisions even
  if the command modifies the working copy.

* `jj run` gained a `--ignore-errors` flag to continue running against the
  remaining revisions even if the command exits with a nonzero exit code.

* `jj file search` now supports `-n`/`--line-number` to prefix each match with
  its 1-based line number within the file.

* `jj git push` gained a `--allow-conflicts` flag to allow pushing commits
  containing conflicts.

* New `jj tag track`/`untrack` commands to associate local tags with remotes.
  Note that fetched tags are tracked by default.

* Added `builtin_log()` revset alias for the built-in default `jj log` revset.
  `revsets.log` now defaults to `builtin_log()`, so custom log revsets can
  reuse the built-in default instead of copying its full expression.

* Added config option `diff.stat.max-bar-width` for use with `--stat` to limit
  the `++--` bar width. In the templating language, `diff.stat()` can optionally
  take a second (positional or named) argument `max_bar_width` for an equivalent
  effect.

* `jj absorb` now supports `--interactive`/`-i`/`--tool` to 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 alias `jj = []`, the
  command `jj jj jj` will resolve to `jj`. Aliases can also fall back to the
  default command. For example, with the alias `i = ["--ignore-working-copy"]`,
  `jj i` will resolve to `jj --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](https://github.com/jj-vcs/jj/issues/7530))

* Fixed Git HEAD mismatch after the working copy became immutable.
  [#9827](https://github.com/jj-vcs/jj/issues/9827)

* `jj` now 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 to `jj` 0.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](https://github.com/jj-vcs/jj/issues/9774)

* Fixed failure when reading configuration in copied repo with an empty
  repo-level configuration directory.

* `jj diff` and `jj status` no 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](https://github.com/jj-vcs/jj/issues/9752)

* `jj run` no longer panics when its revset includes a conflicted commit. The
  conflict is now preserved in the rewritten commit.
  [#9747](https://github.com/jj-vcs/jj/issues/9747)

* Fixed a panic when passing overly-large length parameters to ID templater
  functions (`commit_id.short()`, `commit_id.shortest()`, etc.).
  [#9833](https://github.com/jj-vcs/jj/issues/9833)

* `jj git import` and `export` in 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)