Skip to main content

Why are my reviews being dismissed in my Pipeline? (GitHub)

Understanding the cause and resolution of the "The merge-base changed after approval" GitHub message

Written by Nicole Bazarova
Updated today

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

  1. When you first create your Pipeline, you create your environment branches (e.g. Int) as copies from the base branch (main in our example)

    1. Int is therefore a perfect copy of main, with both having the same last commit (let's call it C0)

  2. You create 2 feature branches from main at the point of C0

    1. You add commit 1 (C1) to feature branch 1

    2. You add commit 2 (C2) to feature branch 2

  3. When you open PRs from the feature branches to Int, GitHub compares:

    1. What is on the feature branch (C1 for feature 1, C2 for feature 2)

    2. With the last common ancestor of the feature branch and Int (C0)

  4. When you merge feature 1, GitHub checks if the merge base has changed for feature 2

    1. C1 has been added to the Int branch, but the last common ancestor for feature 2 remains C0

    2. Feature 2's review therefore still applies

Static branches are not in sync

  1. After you have been using your Pipeline for a while, features will be merged into main

    1. Because of Gearset's expanded branching model, each time a feature branch is merged, it creates unique merge commits on each static environment branch

    2. For example, as feature 1 and 2 get merged into main, they create merge commits M1 and M2

    1. Main now contains commits M1 and M2, whereas Int does not

  2. You create two new feature branches from main at the point of M2

    1. You add a new commit to feature 3 (C3)

    2. You add a new commit to feature 4 (C4)

  3. When you open PRs from the feature branches to Int, GitHub compares:

    1. What is on the feature branch (M1, M2, C3 for feature 3; M1, M2, C4 for feature 4)

    2. With the last common ancestor of the feature branch and Int (still C0)

  4. When you merge feature 3, GitHub checks if the merge base has changed for feature 4

    1. M1, M2, and C3 have been added to the Int branch

    2. The last common ancestor for feature 4 changes from C0 to M2 (M2 is now present on both feature branch 4 and Int)

    3. 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.

Did this answer your question?