Ensuring Engineering Quality Software: CI/CD on Rebase & Merge
Maintaining high standards for engineering quality software in a continuous integration and continuous delivery (CI/CD) environment requires robust safeguards. One common challenge arises when teams adopt a "Rebase & Merge" strategy for a linear Git history, specifically concerning how CI workflows behave after a rebase but before the final merge to main.
The Rebase & Merge CI Dilemma
A developer from the GitHub Community, loryruta, highlighted a prevalent pain point. Their team uses protected main branches and feature branches, triggering CI workflows on every push to a PR. If the PR is 'green' (all tests pass), contributors are allowed to "Rebase & Merge."
The core issue surfaces when the commit history changes due to the rebase, but the CI isn't re-triggered on the newly rebased commits before they hit main. As loryruta illustrated:
main: a => b => c
PR: a => d => e
If the user clicks "Rebase & Merge" (assuming no conflicts):
PR: a => b => c => d => e
In this scenario, the CI might not run again, even though the commit history for the PR has fundamentally changed by incorporating b and c. This leaves a gap where potential integration issues with the latest main could slip through, compromising engineering quality software.
Strategies for Robust CI on Rebase & Merge
Community experts WalkedPlate and pratikrath126 offered several effective solutions to ensure CI runs on the most current state of the code, safeguarding your engineering quality software:
1. Require Branches to be Up-to-Date Before Merging
This is widely considered the most common and effective solution for teams using rebase workflows. By enabling "Require branches to be up to date before merging" in your GitHub branch protection rules, you force contributors to rebase their feature branch onto the latest main *before* they can merge. This action triggers the CI workflows on the PR branch, ensuring that by the time the PR is green and ready to merge, it has already been tested against the most recent state of main. This eliminates the risk of untested rebased commits.
2. Run CI on Push to main
While not preventing the initial merge of potentially untested rebased commits, adding a push: branches: [main] trigger to your workflow configuration acts as a crucial safety net. It guarantees that a CI run occurs immediately after any code lands on main. For performance-sensitive teams, this could be a lighter suite of tests (e.g., just a build or critical smoke tests) to quickly catch major regressions without incurring the full cost of a comprehensive CI run.
3. Leverage GitHub's Merge Queue
GitHub's Merge Queue feature (now Generally Available) automates and enhances the "require branches to be up-to-date" approach. It automatically rebases PRs against the latest main and runs tests in a controlled queue environment before merging. This ensures that every merge is validated against the very latest version of main, providing an even higher level of confidence in your engineering quality software. While powerful, it might be considered overkill for smaller teams or simpler repositories.
Conclusion
The pursuit of a linear Git history with "Rebase & Merge" is a valid and often preferred strategy. The key to preventing CI gaps and maintaining high engineering quality software lies in configuring your GitHub Actions and branch protection rules intelligently. For most teams, enabling "Require branches to be up to date before merging" is the sweet spot, ensuring that all code is thoroughly tested against the latest main before it ever becomes part of your production branch.