API Changelog

Compatibility Policy

Bitbucket Server (formerly Stash) aims to maintain API compatibility between minor releases (e.g. between 4.0 and 4.1). Methods and classes marked as deprecated will be removed in the next major release. For example, methods marked as deprecated in Bitbucket Server 4.1 or 4.2 will be removed in Bitbucket Server 5.0.

Expected future changes

Pull request server-rendered plugins

Some plugin points on the pull request page are rendered server-side, and some are rendered client-side. As more of this page is rendered client-side, we will be deprecating the server-rendered plugin points in favor of client-rendered ones.

The following locations, sections, and decorators will be converted from server-rendered to client-rendered plugin points, or removed entirely, in a future version of Bitbucket Server:

Locations and sections

  • bitbucket.pull-request.nav
  • bitbucket.pull-request.nav.overview.meta
  • bitbucket.pull-request.nav.diff.meta
  • bitbucket.pull-request.nav.commits.meta
  • bitbucket.repository.difftree.header
  • bitbucket.commits.extras


  • bitbucket.pullrequest.view

When they are removed, we will make our best effort to support them in an altered, deprecated fashion until 5.0. See the Bitbucket Server 4.4 notes below for how this will likely occur. To guard against this, we recommend that you rely only on your own styleClass and link id when selecting your elements, and to select them using jQuery live/delegated events.

Bitbucket Server 4.6

Shared Access Layer (SAL) LocaleResolver getLocale implementation change

Prior to Bitbucket Server 4.6 in the case where a user had set their Bitbucket Server language in their Account settings to "Automatically detect browser setting", and had a language set in their browser that was not one of the languages for which a language pack was installed in Bitbucket Server, calling getLocale on the SAL LocaleResolver would return a Locale based on the preferred locale they had set in their browser.

In Bitbucket Server 4.6+ the Locale returned will be the Locale that is the closest match for an installed language. This is a more correct implementation of the LocaleResolver API description which states that getLocale should return "the Locale that should be used in internationalization and localization", as now this Locale will match that used by other parts of the system for internationalization and localization.

Bitbucket Server 4.4

Pull request toolbar plugins moved and deprecated

The web sections and web items at the following locations and sections have been deprecated:

  • bitbucket.pull-request.toolbar
  • bitbucket.pull-request.toolbar.actions
  • bitbucket.pull-request.toolbar.section.user-actions

The web items have been moved into a '…' dropdown menu as menu items, and if you were relying on specific DOM rendering of your plugin, it may cease to function. We no longer refresh the page after a merge or decline, and a reviewer can be added to the pull request without a page refresh. This means your web-item may be out of date in these cases.

A live JS event handling the click event of elements matching your styleClass or <link id="" /> will continue to function until 5.0. You should convert your web-items into client-web-items and add them directly to the new section 'bitbucket.pullrequest.action'. You should remove any intermediary web-sections.

Roles updated event has been deprecated

PullRequestRolesUpdatedEvent has been deprecated for removal in 5.0. Plugin developers who wish to be notified when a user is added/removed as a reviewer should use PullRequestReviewersUpdatedEvent instead

Bitbucket Server 4.2

This public constructor on FileContentCache has been deprecated

FileContentCache now requires a FileContentCacheManager as a constructor dependency. The recommended way to build a FileContentCache is now to use the FileContentCacheManager.Builder a FileContentCache can then be created by calling FileContentCacheManager#createContentCache. NOTE Special care must be taken when migrating to the FileContentCacheManager to ensure that cacheDirectory paths remain correct.


File cacheDirectory = new File(propertiesService.getCacheDir(), CACHE_REGION);
new FileContentCache(CACHE_KEY, cacheDirectory, new TtlCacheExpiryStrategy(), minFreeSpace, cachePump);


File cacheDirectory = new File(propertiesService.getCacheDir());
FileContentCache cache = new FileContentCacheManager.Builder(cacheDirectory)

Stash 3.10

Branch permissions get an update

The BranchPermissionService and version 1.0 of the branch permissions REST API are being deprecated.

In Stash 3.10 we are introducing several new types of branch permissions and are adding the ability to add restrictions based on the branching model.

As a result, we are introducing a new service to interact with branch permissions, the RefRestrictionService. This service can be accessed by adding ref-restriction-api to your pom.xml as a dependency using:


Along with this change, we are updating the version of the branch permissions REST API to version 2.0. It is important to note that any REST calls to branch permissions version 1.0 using 'latest' in the REST URLs should be changed to use '1.0' instead, as version 2.0 of the REST API is not backwards compatible.

We've added new APIs to create, update and remove branch permissions:

Additionally we have added the ref-restriction-spi, which provides interfaces to allow plugin developers to create their own RefMatcher implementations. This opens up the possibility of customizing what type of Ref is restricted by a given branch permission. Add the following to your dependencies to use the ref-restriction-spi:


RepositoryMetadataService has been renamed to RefService

The RepositoryMetadataService is used to retrieve branches and tags for a repository. The "repository metadata" name isn't very self-documenting. Since the service is used to interact with the refs in a repository, it has been renamed to the RefService. The RepositoryMetadataService will remain available to plugins until it is removed in with the 4.0 release.

ChangesetReader is deprecated; use CommitReader

As part of the ongoing work to normalize the API to use "commit" instead of "changeset", the ChangesetReader has been deprecated and CommitReader has been added to take its place.

The format constants previously public on ChangesetReader are now private on CommitReader. Having the constants exposed made changing the format a semantically incompatible change because any plugins relying directly on those constants and not using the ChangesetReadert to parse the output would be broken. If plugins are parsing output for themselves, they should use their own format. If they're using the CommitReader to parse the output, they should call getFormat() on the instantiated reader to get the format and make no assumptions about the format returned.

Stash 3.7

Changeset is deprecated; long live Commit

Throughout the Stash codebase there's been a bit of a split between the term "changeset" and the term "commit". The two have often been used interchangeably, but each represents a distinct concept:

  • A commit represents a snapshot of a complete repository at a given point in time. It captures metadata about who authored the changes and when as well as, optionally, a message about why the changes were made.
    • Different SCMs may include additional metadata in their commits, but Stash's API doesn't include it
    • This was represented by Changeset in Stash
  • A changeset represents how the repository's contents changed between two commits
    • Merge commits, for example, have at least two changesets
    • This was represented by DetailedChangeset in Stash because the name Changeset was already taken

Starting from 3.7 Stash's API is being normalized, replacing Changeset with Commit and replacing DetailedChangeset with Changeset. Because this normalization will touch so many classes and interfaces, the deprecated elements will be retained through the entire 4.x release cycle and will be removed in 4.0. This means plugins developed using the now- deprecated names will continue to work, unchanged, until 4.0.

Stash 3.7 includes the following changes related to this API normalization:

  • The existing MinimalChangeset, Changeset and DetailedChangeset interfaces have been deprecated
    • All of the related data classes (InternalMinimalChangeset, InternalChangeset and InternalDetailedChangeset) have been deprecated
    • All of the related request objects (ChangesetsBetweenRequest, DetailedChangesetsRequest) have been deprecated
    • ChangesetCallback, and all of its related classes, has been deprecated
  • In parallel, completely independent MinimalCommit, Commit and Changeset interfaces have been added
    • New data classes (SimpleMinimalCommit, SimpleCommit and SimpleChangeset) have been added
    • New request objects (CommitRequest, CommitsRequest, CommitsBetweenRequest and ChangesetsRequest) have been added
    • CommitCallback, and related classes, has been added
  • All methods which return the legacy Changeset and DetailedChangeset types have been deprecated, with new variants that return the new Commit and Changeset types added alongside them

For those implementing the SCM SPI or directly using the SCM API, Stash 3.7 introduces:

Unfortunately, because PluginCommandFactory (and the more user-facing ScmCommandFactory) use the names commit and commits for their methods which return Command<Changeset> and Command<Page<Changeset>>, respectively, there is no backward-compatible way to introduce methods which return Command<Commit> and Command<Page<Commit>>. Because of this, the SCM contract will be broken in the Stash 4.0 release.

  • If you are calling any of these methods, you should update your plugin to call one of Stash's API services instead. The API services exposing each SCM command are documented on the ScmCommandFactory interface
    • Switching to an API service will allow your plugin to be compatible with both Stash 3.x and Stash 4.x, which will not be possible if you use the SCM interfaces directly
    • If you cannot switch, you'll need to release distinct versions of your plugin for 3.x and 4.x compatibility
  • If you have implemented an SCM plugin, you will need to release distinct versions of it for 3.x and 4.x compatibility

Additional changes may be made in Stash 3.8, and subsequent releases, to further normalize the API. The goal of these changes is for Stash 4.0 to have a consistent, clear API. If your plugins use the existing Changeset API we strongly encourage you to start updating them to use the new Commit API as soon as possible, and to keep an eye out for EAP builds of Stash 4.0 so you can verify their compatibility with the next major release.

Last authentication timestamps for users

In Stash 3.7, the last timestamp for users' most recent authentication is now tracked. This information cannot be reconstructed retroactively, so after the upgrade each user will have an unknown timestamp. Their next authentication will set that to the current time, and it will be tracked and updated going forward.

Authenticating via the web UI's login screen, via HTTP (pushing to or pulling from a repository over HTTP, for example) or via SSH will all update the last authentication timestamp. Browsing via the web UI will not update the timestamp for each page viewed; the timestamp will only be updated when the user gets a new session with the server. If the user has checked "Remember me", each time they get a new session with the server (generally after ~30 minutes of inactivity), their timestamp will be updated when their new session is created.

The existing DetailedUser has a new getLastAuthenticationTimestamp() accessor. That property is marshaled as "lastAuthenticationTimestamp" when the DetailedUser is returned via REST. See the documentation for /admin/users for example JSON.

Custom pull request notification SPI

In Stash 3.7, plugins can add custom sections in the pull request notifications. For an example, see the new Comment Likes notifications. Adding custom notifications is performed as follows:

  • The plugin fires an event extending CustomPullRequestNotificationEvent (using SAL's EventPublisher); the event should include a renderer ID, the intended recipients of the notification, plus any data needed to render the notification encapsulated in a CustomNotificationData object (for example in Comment Like notifications, this includes the comment ID, plus the user ID of the user who liked the comment);
  • When the pull request notification is rendered, the notifications plugin in Stash calls the registered renderer with the renderer ID included in the CustomPullRequestNotificationEvent, transforming the CustomNotificationData into a CustomNotificationSection rendered in the notification's email.
  • Users' notification preferences determine when notifications will be rendered. Notifications may be rendered several minutes later for users with batch notifications enabled.

Note that the data provided by the event (CustomPullRequestNotificationEvent.getData()) should be as lightweight as possible because it is persisted as JSON data in the database for any recipient configured to receive batched notifications. For example, use IDs (such as the repository ID and pull request ID for a pull request) rather than the full object (such as a pull request instance).

Custom notification renderers are registered by implementing the interface CustomPullRequestNotificationRenderer in a plugin and declaring it in the plugin's atlassian-plugin.xml as follows:

<custom-pull-request-notification-renderer key="my-custom-notification-renderer" class="com.myorganisation.MyCustomNotificationRenderer"/>

Custom pull request comment actions

In Stash 3.7, plugins can add custom actions to notification emails associated with pull request comments. For example, the 'Like' and 'Reply' links in pull request comment emails are implemented as custom actions. To add your own custom action to pull request notifications, declare a web-item in your plugin's atlassian-plugin.xml with section="stash.notification.comment.actions", and a <link> to the URL you want the user to navigate to when clicking on the action. For example:

<web-item key="my-comment-action" name="My Comment Action" section="stash.notification.comment.actions">
    <label key="com.myorganisation.comment.action.label" />
    <tooltip key="com.myorganisation.comment.action.tooltip" />

The custom action renders as a link below each comment in immediate and batched email notifications. Define the link that your custom action navigates to, e.g. a servlet in your plugin that performs an action before navigating to the pull request page, or a link that navigates to the comment on the pull request page and performs some action there. The ${pullRequest} and ${comment} variables are provided in the notification context to help render the web-item's link (e.g. ${pullRequest.id} and ${comment.id}).

Stash 3.5

Atlassian Soy 3.x

In Stash 3.4, the closure template (soy) compiler was upgraded to the latest version as part of the upgrade of Atlassian Soy. This includes the removal of some legacy APIs as well as a stricter compiler of soy templates. The compiler is stricter than the old compiler so some templates which were previously allow may start to have compilation errors. It is possible to write templates which are compatible with both versions. Below are some of the common errors which may occur as part of the upgrade and how to fix them.

Missing required param


template stash.feature.pullRequest.mergeHelpDialog: Call to 'aui.dialog.dialog2' is missing required param 'content'.

This is due to the strictness change in the soy compiler. the parameter on the sub template is defined as required but you are not providing it to the call. You must either mark the parameter on the sub template as optional or pass in a value for the parameter.

ClassCastException: java.lang.Long cannot be cast to java.lang.Integer

This is due to a change in the soy compiler where it represents numbers as longs where it previously represented them as integers. This exception is most likely coming from a custom soy function you have written. Cast to a Number instead and call .intValue() or .longValue().

Comment Likes API

The comment likes feature introduced in 3.5 comes with Java and REST APIs that may be used to add, remove and query comment likes programatically:

Stash 3.4

Properties API

Selected domain objects in Stash that inherit from PropertySupport can now have custom information associated with them. The data is stored against an entity using PropertyMap, which is essentially a map of string keys to any type of value. Properties supersede the AttributeSupport API as a more flexible alternative, with the latter being deprecated and scheduled for removal in Stash 4.0.

Alongside AttributeSupport the following attribute provider plugin modules have been deprecated and replaced with a property provider alternative. Plugin developers are encouraged to switch to property providers, as the replaced modules will be removed in Stash 4.0:

Properties must be convertible to JSON, or otherwise REST requests to resources including properties will fail.

Stash 3.3

Short (display) SHA-1 changes

In Stash 3.3, short SHA-1s are no longer generated by Git. Instead, they are now generated using a fixed length of 11 characters. This change was made because generating short SHA-1s in Git requires it to load the SHA-1s of every object in the repository for consideration. For larger repositories this produces a significant amount of overhead, slowing down several pages in Stash such as listing a repository's commits and displaying individual commits. This overhead is compounded when using a filesystem such as NFS for STASH_HOME or STASH_SHARED_HOME.

11 characters was chosen as the default length because it greatly increases the number of objects a repository needs to have in order to have a high chance of conflict on a given short SHA-1:

  • 7 characters requires only 20,000 objects in the repository to have a 50% chance of collision
  • 11 characters requires nearly 5,000,000 objects to have a 50% chance of collision

All URLs in Stash use full 40 character SHA-1s so, even if there is a conflict on a given 11 character short SHA-1, navigating Stash will not be affected. Longer short SHA-1s are used to reduce the likelihood that copying a short SHA-1 from the UI, since those are all the UI generally displays, and pasting it into a console window, or any other external Git tool, will fail due to ambiguity.

As part of making this change, ChangesetReader.FORMAT, part of stash-scm-git-common, was changed to eliminate the %h and %p elements. Any plugin code which just uses the ChangesetReader should not require a change, as long as they pass ChangesetReader.getFormat() to --format on their command, but any plugin code which directly references ChangesetReader.FORMAT and then does its own parsing will no longer work.

Stash 3.2

Home directory re-organisation

As part of Stash 3.2, the home directory was re-organised. The following changes have been made:

  • The data/ directory has been moved to shared/data/
  • The config/ directory has moved to shared/config
  • The plugins/installed-plugins/ directory has moved to shared/plugins/installed-plugins/
  • The stash-config.properties file has moved to shared/stash-config.properties

The correponding methods on ApplicationPropertiesService for these directories will return the new locations so plugins should be able to continue using these seamlessly.

Atlassian Plugin SDK compatibility

As a result of the home directory re-organisation, Stash 3.2 requires Atlassian Plugin SDK 5.0.3 and above. Stash will fail to start if you attempt to run your plugin via the SDK in a previous version.

Asynchronous startup

Previously, Stash would initialize synchronously with the web container and be unable to service requests. In Stash 3.2 the startup was changed to be asynchronous, with Stash displaying progress of its initialization in the web UI.

Currently this can cause issues when trying to run integration tests against a Stash application as the Atlassian Plugin SDK will start running the tests before the application is fully initialized. In an upcoming release of the Atlassian Plugin SDK this will be fixed but as a workaround you can add the following configuration to your pom.xml to force Stash to initialize synchronously.

                <!-- Force Stash to start up synchronously -->

Atlassian SAL UserSettingsService

Stash now correctly implements the SAL UserSettingsService. Plugins can now use this service to retrieve and update settings associated with users. Prior to Stash 3.2 the service could be injected but it would not persist any settings.

Stash 3.0

Stash 3.0 is the first major release of Stash in over a year. All interfaces that were marked deprecated in Stash 2.11 and earlier have been removed completely. As a result, existing Stash 2.x plugins that use any deprecated interfaces are not be automatically compatible with Stash 3.0.

Deprecated Java APIs removed

Interfaces, classes, and methods in the Java API that were marked deprecated in Stash versions from 2.0 up to and including 2.11 have been removed.

Plugins that use any of these interfaces (which would have generated deprecation warnings when built against Stash 2.12) generally won't compile with Stash 3.0.

Precompiled plugins that used any of the deprecated interfaces will fail to install or run in Stash 3.0, typically with java.lang.NoSuchMethodError.

Updating your plugin for Stash 3.0 shouldn't be too difficult, as alternatives to most deprecated APIs have been documented in the Java API Reference for Stash 2.12.

The following classes and interfaces have been moved to new packages or superseded by newer alternatives.

A few classes and interfaces have also been removed altogether, with no equivalent alternative.

In addition, deprecated methods in existing classes and interfaces across the whole Stash API (too many to list here) have been removed.

Consult the Java API Reference for Stash 2.12 for details on the removed methods, and their alternatives in Stash 3.0.

Deprecated Web UI components removed

Stash 3.0 has also removed Web UI Components (JavaScript, Soy, and LESS) that were marked as deprecated in Stash versions 2.0 to 2.11 inclusive.

Plugins should not be depending on any of these deprecated components, as they do not include any Atlassian standard AUI components or published Stash extensions.

Nevertheless, if you want to verify that your plugin is not affected by the removal of deprecated Web UI APIs, try installing it in the latest 2.x release of Stash. All the removed interfaces were present in this release and annotated with @deprecated, so any use should result in deprecation warnings in the Developer Tools of your browser.

Internationalisation (I18n)

Stash 3.0 now has internationalisation (i18n) support, and includes three language packs: French, German and Japanese! Internationalising your plugin for these languages is highly recommended to provide a consistent look and feel for customers in their own native language. The i18n API's for plugins have been available for some time, see Internationalising your plugin for details.

Java 1.6

Stash 3.0 requires Java 1.7 (Oracle or OpenJDK) or higher, for both plugin development and runtime environment. Java 1.6 is no longer supported.

Scala 2.10

Stash 3.0 requires Scala 2.10 for plugin development. Scala 2.9 and earlier versions are no longer supported.

Help Soy functions deprecated

The Soy functions cav_help_url and cav_help_title for referencing help documentation are deprecated for removal in 4.0. Use stash_help_url and stash_help_title instead.

PullRequestLock and RepositoryLock moved to stash-api

The PullRequestLock and RepositoryLock which were previous in the stash-util module have been moved to the stash-api to facilitate the implementation of a LockService. The interfaces were moved verbatim and thus maintain their binary compatibility.

Stash 2.12

Changeset.getAuthor() and Person.getName() have always been expected to return a non-null value. Explicit @Nonnull annotations have now been added to those methods to explicitly document that expectation.

Scala 2.9 is deprecated for plugin development and will be removed in Stash 3.0. Scala 2.10 has been available to plugins since Stash 2.11.

Stash 2.11

Commit Comments

The HistoryService has been deprecated and renamed to CommitService. New methods have been added in CommitService which support commenting on commits. New REST resources have been added, similar to those used for pull requests, for adding, deleting and updating comments and for watching and unwatching commits.

  • To allow the new REST URLs to match the URL structure for pull requests, ref names are no longer supported by the commits REST resource (rest/api/latest/projects/KEY/repos/SLUG/commits/ID). Instead, you must provide a SHA1 to identify the commit. For example, rest/api/latest/projects/KEY/repos/SLUG/commits/refs/heads/master will no longer work. Instead, use the SHA1 for the latest commit on refs/heads/master, like rest/api/latest/projects/KEY/repos/SLUG/commits/5bad17727d52c17fa7f3a20ed433ebd2c1cdfa21.
  • rest/api/latest/projects/KEY/repos/SLUG/changes is now deprecated and will be removed in 3.0. Instead, use rest/api/latest/projects/KEY/repos/SLUG/commits/ID/changes, where ID is the value previously sent as ?until
  • rest/api/latest/projects/KEY/repos/SLUG/diff is now deprecated and will be removed in 3.0. Instead, use rest/api/latest/projects/KEY/repos/SLUG/commits/ID/diff, where ID is the value previously sent as ?until

The pullRequest context param provided to the stash.comments.actions and stash.comments.info web item locations for comments has been deprecated to be optional for 3.0. In 3.0, web-items for these locations should not always expect the pullRequest object as comments can also be made on commits.

Branching Model API

The Branch Model feature introduced in Stash 2.8 now offers Java and REST API, allowing plugin developers to:

  • Query whether a repository has a Branching Model associated with it
  • Get the Development and the Production branch
  • Get enabled branch types (Bugfix, Feature, Hotfix, Release)
  • Get a list of branches belonging to a given branch type
  • Classify a branch (get its category, if any)

Java API

The following interfaces are the entry point to the API and may be consumed from the branch-utils artifact:


As of Stash 2.11, the branch model for a given repository may be also queried via the REST API.

Stash 2.10

Log level when developing a plugin

When starting Stash with AMPS, the default log level of the Stash instance was changed from DEBUG to WARN.

Empty repository web panels

The stash.web.repository.empty location for web-panels has been deprecated and replaced with client-web-panels at the location stash.empty.repository.instructions. These client-web-panels will now receive the user preferred clone url (HTTP or SSH) as a context param and re-rendered when the user changes their clone URL preference.

Updating the base URL

Updating the base URL with ApplicationPropertiesService.setBaseUrl(URI) now requires SYS_ADMIN permission.

Streaming callbacks

The following callbacks have been added, extending existing callbacks:

These new interfaces make the callbacks more consistent with each other. They also introduce new onStart and onEnd methods which accept readily-extensible context and summary objects, respectively. The context provided to onStart offers insight into the shape of the command for which results are being streamed, with a summary of those results provided to onEnd. Some of these objects are simple placeholders, in this release, and will be fleshed out in future releases. Those changes, when they happen, will be backwards-compatible and will not require introducing new interfaces.

The existing interfaces are unchanged, so these new interfaces should not break any existing plugins. They are included in 2.10 to give plugin developers more time to update to the new interfaces. For each callback, an abstract base class is provided. Plugin developers should always extend from one of these base classes when implementing any callback. The base classes will make the callback implementations more resilient to future changes to the callbacks.

All of the new interfaces are deprecated, and will be folded back into their respective non-versioned interfaces and removed in Stash 3.0. Plugin developers who extend their implementations from one of the base classes should not be affected by that change. Each new interface describes how its non-versioned interface will change in the 3.0 release.

FileContentCallback.appendBlame(List) and FileContentCallback.onEndPage(Page)

In previous releases, FileContentCallback.appendBlame(List) was called after FileContentCallback.onEndPage(Page). Stash 2.10 introduces a non-backwards-compatible change where appendBlame is now called before onEndPage. The onEnd method on each callback is intended to always be the final method invoked, so this ordering change makes the FileContentCallback consistent with all of the other callbacks, where onEnd is already always called last.

New columns in the audit log file

The audit log format has been extended with two new columns: the ID of the request in scope and the ID of the session of the request in scope.

Stash 2.9

Renaming users

Stash 2.9 allows for users to be renamed in both internal and remote directories. Plugins which are using the username as a key to store data against will break when a user is renamed.

In order to cope with user renames, Stash-specific plugins should use StashUser.getId(), whereas Cross-product plugins should use SAL's UserKey to store data against a user. In order to detect when a rename occurs, plugins should listen for the UserRenamedEvent.

Stash now built with Maven 3.0.x

As of 2.5.5, 2.6.6, 2.7.7, 2.8.5 and 2.9.0, Stash uses maven 3.0 to build. This should not affect the development of plugins using the Atlassian SDK nor how Stash is built from source.

Stash 2.8

Pull Request Merge SPI

Stash 2.8 introduces a new SPI to allow plugin developers to inspect pull request merges before they are applied to the repository. In the stash-scm-git-api module, there is a new GitPullRequestMergeRequestEvent which they can listen for.

This event includes the pull request being merged, as well as the SHA1 of the merge commit. It is raised before the pull request's target ref is updated, and can be canceled to prevent the update. When canceling a merge, the plugin must provide a message explaining why. This message will be shown to the user, so it should be clear and descriptive to help the user resolve whatever error is preventing the merge.

For more information, see STASH-3122.

Ref Metadata Provider SPI

Stash 2.8 introduces an SPI for providing metadata associated with refs. This metadata can be accessed via REST when retrieving a list of branches.

See the reference documentation for more information.

Changeset Plugin Formatting

Previously the web fragment stash.changeset.extras would expect <dl> elements for display, with labels. For consistency with the pull request page, and making things pretty, Stash has introduced a new fragment stash.changeset.related-entities which is shown in the same location, but prefers the use of an icon over a label. The old stash.changeset.extras is now considered deprecated and will be removed in 3.0.

New placeholder text param for Branch Selector Field Soy template

The Stash.template.branchSelector.input template now takes in a text param which can be used to override the default placeholder text for the branch selector dropdown when no ref is selected.

Moving repositories

Stash 2.8 now supports moving a repository between different projects. When moved, repositories retain the same unique ID, even though the Project is changed. Plugins which use project key and repository slug together as a key to store data against instead of the repository's ID, will break when a repository is moved. Plugins should instead use the repository's ID.

Stash 2.7

Backup/restore (beta)

Stash 2.7 supports a BETA version of backup and restore. In order for your plugin's data to be included within the backup archive you will need to ensure it is stored in one of two locations:

  • In database tables managed by ActiveObjects
  • In the <STASH_HOME> directory with the exception of the a few excludes the most notable of which are the <STASH_HOME>/tmp and <STASH_HOME>/export directories.

Inactive users

Stash 2.7 now respects the active state of users which are synchronized from an external user directory. Inactive users are will no longer be counted towards the license count and will not be returned from any of Stash's services unless explicitly requested. This is consistent with how Stash handles deleted users. More detailed documentation on how inactive users are handled can be found in the documentation for the UserService.

Stash 2.6

Page limit

Stash is very strict about performance requirements, and as such uses Page everywhere to help encourage this behaviour.

Previously it was possible to see an extremely large PageRequest limit size. In many cases this is reduced to a hard-limit, but in others it was respected and may have resulted in poor performance.

Now setting the limit larger than PageRequest.MAX_PAGE_LIMIT will result in an exception, which may break some plugins. Instead of using a large limit, it is strongly suggested to page with a reasonable limit and process in batches.

Stash 2.5

Anonymous access

Stash 2.5 introduces the concept of anonymous access to projects and repositories. There are a few implications for plugins that need to be taken into consideration.

Null user

The StashAuthenticationContext.getCurrentUser() method has always been annotated with @Nullable, but until now it was fairly unlikely for a null to be returned. With anonymous access previous invocations of plugin that code that assumed a non-null result may now throw an exception. This also include calls to StashEvent.getUser() and javascript calls to pageState.getCurrentUser().

Callers of any of any of these methods should always check the result to avoid errors caused by anonymous users.


To confirm if an anonymous user has access to a resource an extra check must be made in addition to verifying standard permissions. It's worth noting that calls to the standard ProjectService and RepositoryService already have the appropriate permissions, and manual validation is not required in the majority of cases.

Manual anonymous permission checking is possible through new methods added to the PermissionService such as isPublicAccessEnabled(), isProjectAccessible() and isRepositoryAccessible(). Plugins that only check permissions such as REPO_READ will continue to return false for anonymous users.

Stash 2.4

Support for forks

Prefer changesets to branches/tag

With the introduction of forks it is now crucial to recognise what repository is being handled when making SCM or history calls and the implications of which branches/tags are visible.

To explain further, consider creating a pull request from a fork to the parent repository. When trying to calculate the changes between a branch on the fork to master on the parent, which branches are available will depend entirely on which repository is being referenced. In short the branch on the fork doesn't actually exist on the parent and must be referenced by changeset instead.


There are some implications to hook developers who plan on enforcing a specific workflow for forks as well as branches. Please see the hook documentation for more details.

Repository permissions

Stash 2.4 has introduced Repository Permissions which, among other things, alter the concept of what it means to access a Project and Repository.

One important change is the introduction of a virtual permission PROJECT_VIEW. The PROJECT_VIEW permission is transient and is granted when a user is able to view a project, when they have either a repository permission on a single repository, or a direct permission on the project itself. An example of the PROJECT_VIEW permission can be seen on the screen listing the projects. By comparison, the PROJECT_READ permission is a super-set and allows a user to access the entire project and all the child repositories.

This change has implications to plugin developers who are either granting permissions, or using something like the SecurityService to elevate permissions for a particular operation. Previously there was no technical difference between granting PROJECT_READ and REPOSITORY_READ, but after 2.4 some operations may not function correctly.

User profiles and accounts

Stash 2.4 introduces a public user profile page as well as a private account management page. The following changes have been introduced to the way that plugins can interact with these pages:

User slugs

There is no restriction on characters that may be present in a username, since the Stash userbase may be sourced from an external directory, such as LDAP. As such, the username property of a User is not guaranteed to be URL safe (consider a forward or backward slash in the username).

Inserting the username of a User into a path component of a URL is highly ill-advised, and the StashUser.slug property should be used instead. For example, /plugins/servlet/my-plugin/{$user.slug}. Relatedly, use UserService.getUserBySlug(String slug) to retrieve a user from Stash.

User profile

Prior to Stash 2.4, the profile was only visible to the current user; a user's profile is now visible to any user.

Plugins injecting resources into the stash.page.userProfile context are now only rendered when a user is viewing his or her own profile. This context is deprecated, and stash.page.user.profile.self should be used in preference. If your plugin was using this context to render user preference fields, you should use the Account Management pages instead.

The architecture of the profile page has also changed in Stash 2.4; previously, a plugin would inject a navigation tab and render content using a web panel. Due to the restructuring of these pages, this is no longer possible and you will need to now use a decorated page to inject a new tab. Please follow our how-to on decorating the profile page.

Other notes:

  • The context atl.userprofile is available on the account pages only (see below), not the public user profile. This is in contrast to Stash 2.3 and below which made no distinction as there was no account management pages. Use stash.page.user.profile to target these pages; see web resource contexts for other options.
  • stash.web.userprofile.secondary.tabs web item location has been deprecated. Use stash.user.profile.secondary.tabs instead, which provides the profileUser and project (User's project object) in it's context.

Account management

The account management pages are used to view and modify user account information and user preferences. These are new in Stash 2.4.

Please follow our how-to on decorating the user account page for details on how to inject data here with your plugin.

Project list

The 'stash.project.help.basics' and 'stash.project.help.reference' web item plugin points on the Project list page sidebar are deprecated. You should use 'stash.project.list.sidebar.items' instead.

Repository header

The stash.web.repository.clone.before and stash.web.repository.clone.after web panel locations have been deprecated. Use stash.web.repository.header.buttons for web items and web sections or stash.web.repository.header for web panels.

Stash 2.3

Detecting when the repository has changed

The new RepositoryRefsChangedEvent gives developers an easy way to receive notification of changes to a repository. The two existing ref change events, RepositoryPushEvent and PullRequestMergedEvent, now implement RepositoryRefsChangedEvent. As a result, developers needing to know about changes can use a single event listener:

public void onRefsChangedEvent(final RepositoryRefsChangedEvent event) {
    // Take action when refs have changed

New cancelable events

Two new CancelableEvents allow plugins to veto modifications to project settings and repository settings.

Stash authentication plugin modules Beta

We have added three experimental plugin modules designed to support custom authentication in Stash, such as Kerberos or custom SSO integration. See the documentation for the Http Authentication Handler, Http Authentication Success Handler and Http Authentication Failure Handler module types.

Hook settings permissions

Previously hook settings were available (also via REST) for users granted the REPO_READ permission. This has been increased to REPO_ADMIN and the documentation updated. The implications for this are plugin developers that require these settings on non-admin pages will need to introduce their own REST endpoint and manually elevate permission as required.

ContentTreeCallback changes

Introduced a new ContentTreeCallback2, which extends the original ContentTreeCallback, and introduces a new onTreeNode()) method for handling extra parameters on the ContentTreeNode, such as URLs for the newly introduced Submodule.

Plugin developers are strongly advised to extend AbstractContentTreeCallback which provides better compatibility for future changes to either of these two interfaces.

Stash 2.0

Cancelable events

The CancelableEvent interface gives developers a chance to cancel certain operations. Stash currently allows cancellation of project creation, project deletion, repository creation and repository deletion. If you are listening to a cancelable event, you can cancel the operation by calling the the cancel() method on the event, passing a KeyedMessage that explains the reason for cancellation.

Stash 1.3

As part of the 1.3 release Stash has made some small breaking API changes in respect to version 1.2.


  1. The content Callback interfaces com.atlassian.stash.content.*Callback have been modified slightly to include extra arguments. For example the onHunkStart method now requires 4 arguments instead of the original 2. These changes will require the extra parameters to be added to any implementations, and the plugins recompiled.
  2. com.atlassian.stash.content.PagedCallback has been removed and the onStartPage and onEndPage methods have been lifted into the various implementations. This affects ContentTreeCallback and FileContentCallback. These changes are a binary-incompatible update, and do not require any source-level changes, but do need to be recompiled.


  1. com.atlassian.stash.scm.git.remote.GitRemote*Builder.build() now returns GitCommand instead of the super-class Command. This is a binary-incompatible change, and does not require any source-level changes, but does need to be recompiled.
  2. com.atlassian.stash.scm.git.GitScmCommandBuilder.config() now returns GitConfig instead of GitConfigBuilder.
  3. com.atlassian.stash.scm.git.config.GitConfigBuilder has been split into GitConfigGetBuilder, GitConfigSetBuilder and GitConfigUnsetBuilder.