Download: 3.15.0-rc1

Documentation: 3.15.0

Release highlights

Java 25

Gerrit is now built and tested with JDK 25 by default, producing Java 25 bytecode (major version 69).

The optional java21 Bazel configuration is still available to build and release Gerrit for Java 21 (bazel build --config=java21 release).

Bazel modules

The migration of Gerrit’s build to Bazel modules (Bzlmod), started in Gerrit 3.14, is now complete: the legacy WORKSPACE-based dependency mechanism, including external_plugin_deps.bzl and the maven_jar rule, has been removed, the web UI build has also moved to Bazel modules, and Gerrit is built with Bazel 9, where Bazel modules are the only supported dependency model.

All plugins must move to Bazel modules. Plugins that still declare their external dependencies in external_plugin_deps.bzl no longer build and must declare them in their own MODULE.bazel with rules_jvm_external, as described in Plugins with external dependencies.

Stack Diff

An experimental Stack Diff dialog, opened from the Relation Chain section, shows the cumulative file list and diff of a whole relation chain against its base parent commit, so the combined changes of a stack can be viewed in one place, similar to PRs. Enable it with the UiFeature__stack_diff experiment.

Submit Requirement Templates

Administrators can now define reusable submit requirement templates in [submit-requirement-template "<name>"] sections of project.config, which project owners can pick from in the UI when creating submit requirements.

Templates are inherited from parent projects and exposed through the new GET /projects/{project}/submit_requirements_templates and GET /projects/{project}/submit_requirements_templates/{name} REST endpoints.

Rich Markdown Diff

A rich rendered view for the diff of Markdown files has been introduced, which can be toggled from the diff view and the file list, with inline word and block highlighting.

Comments can be added directly in the rendered Markdown view, including with the C shortcut and on a text selection.

Searching Changes

New search operators have been added to the change index:

  • onlypaths: finds changes touching exactly the given set of files, allowing submit requirements to replace Prolog rules based on the exact list of modified files. Magic files such as /COMMIT_MSG are ignored, and a single regular expression starting with ^ can be used instead of a comma-separated list of paths.

    NOTE: Using the operator with a very commonly changed file may produce a large intermediate result set and be expensive.

  • filecount: finds changes whose latest patch set touches a given number of files, e.g. filecount:>2.

  • unmet_requirement:'NAME' and unsatisfied_requirement_count:'RELATION''NUMBER' find changes by their unmet submit requirements. These operators are not allowed inside submit requirement expressions.

  • has:hashtag matches changes that carry at least one hashtag.

Committing Files to a Branch via REST API

The new POST /projects/{project-name}/branches/{branch-id}/commit REST endpoint creates, updates, deletes or renames files on a branch in a single commit, without cloning the repository or creating a change.

The caller needs Push access on the branch; commit and ref-update validators (including plugin validators) run, but push-only receive-pack checks are not applied and matching open changes are not auto-closed.

An optional base_revision rejects the request with 409 Conflict if the branch has moved, and a request that would not change the tree is rejected with 400 Bad Request.

OAuth Tokens Lifecycle

For sites using OAuth authentication (auth.type = OAUTH), OAuth token handling now covers the whole token lifecycle. The OAuthServiceProvider extension point supports OAuth 2.0 with PKCE (Proof Key for Code Exchange) and can refresh and revoke tokens, with a new OAuthTokenRevokedListener extension point notified on revocation; existing providers remain compatible. Expired access tokens are renewed from their refresh token when the provider supports it, including when retrieved through the REST API, and a failed refresh is retried after auth.oauthTokenRefreshInterval. Tokens stored in the oauth_tokens cache are encrypted at rest with AES-256-GCM using auth.tokenEncryptionKey, which init generates automatically. PKCE, token refresh and token revocation take effect only when the OAuth provider plugin implements the new extension point methods; the oauth plugin supports all of them.

Administration & Configuration

  • Stale change index recovery

    Gerrit can now automatically recover change index updates that were lost when the process crashed or was interrupted between the NoteDb write and the index write. Enable it with index.staleChangeRecovery = true (default false): Gerrit writes per-change intent files under $site_path/data/pending-index/, recovers leftovers from a crashed process at startup and runs a background scanner every index.staleChangeRecoveryInterval (default 5m).

    NOTE: Recovery is only effective when index.commitWithin is set to zero and index.indexChangesAsync is false.

High-Availability Configuration

The new index.directory setting configures where Gerrit stores its index independently of the site path (default $site_path/index; relative paths are resolved against $site_path).

Important Notes

Schema and index changes

Gerrit schema version is updated to 187.

The Changes index has been upgraded from v88 to v90.

Offline upgrade

  • Stop Gerrit
  • Download the new gerrit.war and move it to $GERRIT_SITE/bin
  • Extract all the plugins from gerrit.war and move the ones needed into $GERRIT_SITE/plugins
  • Run the full reindex: java -jar $GERRIT_SITE/bin/gerrit.war reindex --index changes -d $GERRIT_SITE
  • Start Gerrit

Online upgrade with zero-downtime

Gerrit v3.15.x supports zero-downtime upgrade from Gerrit v3.13 when configured using a high-availability setup.

During the zero-downtime upgrade, Gerrit end-users will not experience any outage or service disruption and will be able to perform any read/write Gerrit operation seamlessly.

The zero-downtime upgrade process for high-availability setups consists of the following steps (demo):

  1. Have Gerrit servers running v3.13 in high-availability configuration, healthy and able to handle the incoming traffic properly.
  2. Set one of the Gerrit servers to unhealthy.
  3. Shutdown the Gerrit server, update gerrit.war, plugins and libs to v3.15.x and start Gerrit again.
  4. Verify that the Gerrit server is working properly (e.g. run automated smoke tests) and then make it healthy again.
  5. Ensure the Gerrit server is fully caught up with the events that happened while it was down before directing traffic to it.
  6. Repeat steps 2 to 6 for each of the remaining Gerrit servers.

Known issues

  • Issue 309098227 Change 360646: The introduction of a per-request ref cache for better performance may break the repository consistency

    The addition of a new core.usePerRequestRefCache setting, true by default, introduced a per request (currently per request thread) ref cache, helping reduce the overhead of checking if the packed-refs file was outdated. However, in some scenarios, such as multi-site or concurrency between git-receive-pack and git-gc, it may lead to split-brain inconsistencies and, in the worst-case scenario, to the corruption of the underlying repository.

  • Issue 380898784: The new changes_by_project cache will make the git-upload-pack fail intermittently on projects containing one or more inconsistent changes.

    The introduction of the changes_by_project cache is incompatible with projects having one or more inconsistent changes, like changes with /meta refs coming from unexpected Gerrit serverId. The cache makes the git-upload-pack fail intermittently with internal server errors when it fails to load the change meta-data depending on the status of the cache. As a workaround, disable the changes_by_project cache as follows in gerrit.config:

    [cache "changes_by_project"]
          memoryLimit = 0
    

Breaking Changes

Performance Changes

Permissions & Security Changes

New Features

Bug fixes

Frontend changes

Documentation changes

Plugin changes

JGit Changes

  $ git log --oneline --no-merges 182a14056..87eaf6628

Notable changes are:

-

Other dependency changes

Community

Welcome to our new contributors

Welcome to the new contributors that had their first patch merged in 3.15.0:

* *

Thank you for your contributions!