Skip to main content

Why do Gearset's reverse merge commits contain lots of unrelated changes?

The semantic reverse merge commit that Gearset will sometimes add to a PR is often a source of confusion. Here we attempt to explain it.

Written by Steve Ballantine

When a PR is created against a pipeline environment, Gearset will sometimes perform a reverse merge to pull changes from the target environment branch into the promotion branch. (For information on the pipelines branching model and what a promotion branch is see this article.) This is similar to the standard git practice of keeping your pull requests in sync. In the context of Gearset, it ensures conflicts are resolved early and allows us to address things that the standard git merge gets wrong. (See the why reverse merge at all section below for more detail on this.)

However, due to the way git works and the way features are promoted through the pipeline, this reverse merge commit can occasionally cause confusion.

Example

Consider the following simple pipeline. On the VCS side, we have 2 long lived branches, uat and main.
New feature branches are created from main.


uat is precisely aligned with main. If we create a feature branch feature and commit a change to it then our git graph will look like this.

For the sake of this example, we'll say that the feature just adds a new field. We'll also assume that reverse merges always happen in this example. In reality, Gearset will only do this some of the time.

When a PR is created to move these changes to uat, Gearset creates a promotion branch feature_-_uat. and merges uat into that promotion branch.
Later, when the feature is promoted, Gearset merges the promotion branch into uat, leaving us with this git graph:

Lets say that we now decide to start a new feature before this one is promoted through to main or to just abandon this feature completely. The change to add the new field is still committed against uat but the new feature branch we create will not have that change in its history.

When we start work on this new feature, we go through the same process:

This time, the reverse merge from uat into the promotion branch will include the change to add the new field from the first feature. If the first feature had been promoted all the way through to main before feature2 was created then feature2 would already have that change, but because it didn't get any further than uat, it will be added to future promotion branches by the reverse merge.

When do reverse merges happen?

Gearset will only add the reverse merge commit if at least one file has been modified on both the source and the target branch of the PR.
​
For example, if there are 2 feature branches that both add new fields to the same layout. The first is promoted all the way through the pipeline so that change is now in all environments. Now, when the second is promoted through, Gearset will add the reverse merge commits (or possibly flag up a merge conflict that needs to be resolved, depending on the precise details of the changes)

Why reverse merge at all?

When we complete a PR, the source branch (the *_-_uat branches in the example above) get merged into the target branch (uat in the example above).

This merge happens on the VCS provider's servers using a standard git merge process.

Git merge is a fantastic tool. It is totally generic and can be used to merge any type of data. However, this means that it can make sub-optimal choices when merging specific types of files.

This is where Gearset's Semantic merge driver comes in. It is written with the knowledge that it will only be used for merging XML files containing Salesforce meta data. (Semantic merge will pass Apex code and other file types through to the standard git merge.)

Unfortunately, it is not possible to insert this merge driver into the workflow for when a PR is merged as that happens on the VCS provider's servers as described above.

Instead, we need to do the merge locally on Gearset's servers. We don't want to be pushing commits to the long-lived branch, so the only option here is to perform the reverse merge onto the promotion branch and then push that change to the VCS to become part of the PR.

Proactive Semantic Merge Comments on your PR

When a Proactive semantic merge has been completed on your PR, we will post a comment on it outlining what has been done and why. The comment will look similar to this, depending on your VCS provider:

Depending on your branch protection rules, this comment should not block the PR from being merged. If it does or any other issues with the comment or with semantic merges, let us know in the in-app chat!

Why do my long lived branches have these changes in them?

There are 2 reasons that the long lived branch might have changes that are not in the feature branch:

  1. Other features are flowing through the pipeline normally, but:

    1. Those features were not in main when your feature branch was created and

    2. They were already in, or have since been added to, intermediate environments.

  2. Features are abandoned after being promoted part way through the pipeline.

The first case above should be considered normal operation. In this situation, the reverse merge is making sure that the changes you've made will not cause conflicts with the changes that others have made to those intermediate environments since you took your feature branch from main.

The fact that these changes then appear as part of the changes in the promotion branch is annoying in some cases, but it is necessary to allow us to use Gearset semantic merge, which is in turn necessary to avoid validation errors following standard git merges as described in What is Semantic merge.

The second case is also expected, but will add noise that will increase over time as more and more changes are abandoned part way through. We'd strongly recommend avoiding this if at all possible.

If you must abandon a feature part way through then we would recommend updating the feature branch so that it makes no changes and then promoting that through from the start of the pipeline. See this article for more guidance about making changes to a feature that is already partially propagated.

How can I fix my environment branch?

If a reverse semantic merge is causing validation errors that you don't expect, please follow the guidance in our semantic merge document here: A reverse semantic merge is including changes in my validation and causing validation errors

Did this answer your question?