The situation
In your Gearset Pipeline, you have multiple PRs waiting for review in order to be deployed into a subsequent environment (e.g. Int). Your team reviews and approves all the PRs, but as soon as you merge the first feature, you notice that all the other PR reviews become invalidated with the message "The merge-based changed after approval".
So, what's going on? Your other PRs haven't changed their contents, so why does GitHub invalidate them?
The cause
If you are seeing this behaviour, you likely have a GitHub branch protection in place called "Dismiss stale pull request approvals when new commits are pushed"
According to GitHub, this setting means "approving reviews will be dismissed as stale if the merge base introduces new changes after the review was submitted. The merge base is the commit that is the last common ancestor between the topic branch and the base branch. If the merge base changes, the pull request cannot be merged until someone approves the work again".
We explain how GitHub calculates the merge base in more detail here, but essentially this means that because the last common ancestor is calculated as the last shared commit between the feature branch and the environment branch, whether you see the review invalidation depends on whether your static environment branch (e.g. Int) is in sync with the base branch's (e.g. main) commits.
For example, let's imagine a simple Pipeline: Dev --> Int --> Prod. You set the "base branch" as main.
Static branches are in sync
When you first create your Pipeline, you create your environment branches (e.g.
Int) as copies from the base branch (mainin our example)Intis therefore a perfect copy ofmain, with both having the same last commit (let's call it C0)
You create 2 feature branches from
mainat the point of C0You add commit 1 (C1) to feature branch 1
You add commit 2 (C2) to feature branch 2
When you open PRs from the feature branches to
Int, GitHub compares:What is on the feature branch (C1 for feature 1, C2 for feature 2)
With the last common ancestor of the feature branch and
Int(C0)
When you merge feature 1, GitHub checks if the merge base has changed for feature 2
C1 has been added to the
Intbranch, but the last common ancestor for feature 2 remains C0Feature 2's review therefore still applies
Static branches are not in sync
After you have been using your Pipeline for a while, features will be merged into
mainBecause of Gearset's expanded branching model, each time a feature branch is merged, it creates unique merge commits on each static environment branch
For example, as feature 1 and 2 get merged into
main, they create merge commits M1 and M2
Mainnow contains commits M1 and M2, whereasIntdoes not
You create two new feature branches from
mainat the point of M2You add a new commit to feature 3 (C3)
You add a new commit to feature 4 (C4)
When you open PRs from the feature branches to
Int, GitHub compares:What is on the feature branch (M1, M2, C3 for feature 3; M1, M2, C4 for feature 4)
With the last common ancestor of the feature branch and
Int(still C0)
When you merge feature 3, GitHub checks if the merge base has changed for feature 4
M1, M2, and C3 have been added to the
IntbranchThe last common ancestor for feature 4 changes from C0 to M2 (M2 is now present on both feature branch 4 and
Int)Feature 4's review therefore becomes invalidated and requires re-approval
The solution
If you only want PRs to require re-approval if the features themselves are updated, you simply need to ensure that you keep your static environment branches in sync with main's commits.
This means that after each release to production, you should merge a sync PR from main into each static environment. These can be created manually, or automated in the Pipeline.
Because merging the sync PR will update the last common ancestor for any open pull requests, ensure these are merged before you start approving any PRs.


