Enforce rebasing before merge

Posted on Apr 24, 2024
tl;dr: How to setup a gitlab pipeline job to make sure a branch is rebased

Gitlab Pipelines

We defined a policy in our development workflow to rebase a feature branch before merging it into the mainline branch.

Since a merge into the mainline branch triggers a deployment into our staging environment, we need to ensure that only stable code is merged. If merge conflicts occur during a merge request, we decided that these should be resolved by the developer who introduced the conflict by rebasing and updating the merge request.

To ensure this was done correctly, we added a test in our CI/CD pipeline that fails if a merge request branch is rebaseable onto the mainline branch.

Script to Check Rebaseability

The following script is meant to be used in a GitLab pipeline job for merge requests. It resolves the commit hashes for the merging branch, the target branch, and the hash where the merging branch branched off the mainline branch.

By comparing these hashes, we can determine if the branch can be rebased onto the target branch.

# file: ci/rebase_check.sh
#!/bin/bash

# fetch to make sure the required refs a available
git fetch

# resolve the commit hash fo the MR source branch
echo "Source: ${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}"
SOURCE_SHA=$(git show-ref -s "${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}")
echo "Source SHA1: ${SOURCE_SHA}"

# resolve the commit has of the target branch (usually mainline)
echo "Target: ${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}"
TARGET_SHA=$(git show-ref -s "${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}")
echo "Target SHA1: ${TARGET_SHA}"

# resolve the commit at which we branched of the mainline branch
ORIGIN_SHA=$(git merge-base "${SOURCE_SHA}" "${TARGET_SHA}")
echo "Origin SHA1: ${ORIGIN_SHA}"

if [ "$ORIGIN_SHA" = "$TARGET_SHA" ]; then
  echo "Branch seem fine, go ahead!"
  exit 0
else
  echo "Branch ${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME} should be rebased!"
  exit 1
fi

Gitlab CI Example

Exampe for a Gitlab CI job configuration for this script:

# file: .gitlab-ci.yml

...

git:
  image: debian:stable
  only:
    - merge_requests
  stage: test
  script:
    - ./ci/rebase_check.sh