Maintaining a clean and stable main branch in software development is crucial for a smooth and efficient development process. Making you save time and money so you can focus on projects that matter.
However, as teams grow and projects become more complex, managing your dev team pull requests, and their merges while preventing conflicts can become a frustrating task. Indeed, sometimes engineers spend hours managing their code merge, conflicts, etc... And when you do it every day, simultaneously with your colleagues, things become complex.
In a typical software development workflow, multiple developers work on different features or bug fixes simultaneously, often requiring them to merge their changes into the main branch. This process can introduce conflicts and bugs, or even cause the main branch to become unstable if not handled carefully.
This article will explore the concept of a merge queue and how it can help keep your main branch safer.
I. The Main Problem
Let's imagine a GitHub repository in the following situation: a pull request is created and passes the CI.
While the PR is open, you push another commit to the main branch. CI tests pass, PR is marked as valid.
No code conflict? Then the PR is considered mergeable by GitHub: the merge button is green.
You merge your PR and then you realize that the PR broke the main branch! You actually merged a stalled pull request that introduces a regression or breakages into the production system.
Tons of engineers are confronted with this problem every day. This can lead to conflicts between code changes, breaking functionality, and introducing bugs into the main branch. Fixing these issues can be time-consuming and may disrupt the workflow of other developers relying on the main branch.
II. Underlying Issues
Many clients of ours told us that before Mergify, they were facing daily code-breaking, leading them to a lack of safety and making them spend hours correcting it. Like Orca:
Some circumstances can explain all of that. ⬇️
1. ❌ Lack of Coordination Between Developers
The lack of coordination between developers can lead to conflicts and issues when merging changes into the main branch. Without effective managing solutions and a clear understanding of who is working on what, developers may inadvertently overlap their changes or merge conflicting code simultaneously. This can result in code conflicts, decreased productivity, and overall instability in the main branch.
2. ❌ Merging Untested or Incomplete Code
When developers merge untested or incomplete code into the main branch, it poses a significant risk to the stability of the codebase. Without proper testing, these changes may introduce bugs, cause unexpected behavior, or even break existing functionality. Merging code that hasn't undergone thorough testing can result in a less reliable and more error-prone main branch.
3. ❌ Absence of a Systematic Review and Approval Process
Without a structured review and approval process, there is a higher chance of introducing unstable or low-quality code into the main branch. A lack of code reviews can lead to missed errors, poor code quality, and inconsistency in coding practices. In the absence of a systematic review process, developers may not receive feedback or validation on their changes, which can hinder the overall stability and maintainability of the main branch.
III. Solutions, But Not the Interesting Ones
There are traditional approaches to address these issues, such as:
1. ➡️ Branching Strategies
While branching strategies can be effective in managing concurrent development and minimizing conflicts, they often rely on manual processes for merging code changes. This manual merging process can be time-consuming and prone to human error. Additionally, as the number of branches increases, it becomes challenging to keep track of dependencies and ensure a smooth integration process.
2. ➡️ Code Freezes
Code freezes can be useful for stabilizing the main branch and addressing existing issues. However, they require halting new feature development, which can disrupt the development momentum and delay the delivery of new functionalities. Furthermore, code freezes rely on manual processes to address bugs and ensure stability, which can be time-consuming and prone to human error.
3. ➡️ Manual Code Reviews & Merge
Manual code reviews are valuable for ensuring code quality and knowledge sharing within a team. However, they can be a bottleneck in the development process, especially in larger teams or projects with high code change frequency. Manual reviews rely on individual availability and expertise, which can lead to delays in the code integration process.
4. ➡️ Continuous Integration
Continuous integration is a valuable practice for catching issues early and ensuring code stability. However, implementing continuous integration alone may not address the challenges of code integration, testing, and review in a controlled manner. While CI pipelines automate build, test, and integration processes, they do not provide a centralized and controlled environment for managing code changes and collaborations among developers.
5. ➡️ Coding Standards and Guidelines
Establishing coding standards and guidelines is essential for maintaining code consistency and readability. However, relying solely on coding standards may not address the challenges associated with merging code changes. Developers can still introduce bugs or conflicts even if they adhere to the coding standards.
While these traditional approaches can be effective to a certain extent, they often rely on manual processes, which can be time-consuming and prone to human error. Alternatively, automated tools like a merge queue can streamline and enhance these approaches by providing an automated and controlled environment for code integration, testing, and review.
IV. Introducing the Merge Queue
A merge queue is a powerful tool that helps streamline the process of merging changes into the main branch while ensuring the stability and safety of the codebase. It acts as a gatekeeper, allowing changes to be merged only after passing certain criteria, such as automated tests, code reviews, and build validations.
1. What is a Merge Queue
A merge queue prevents merging broken pull requests by serializing their merge and updating PRs with their base branch. Merging broken PRs can happen when outdated pull requests are being merged in their base branch.
Now you understand the whole concept, this is what it looks like:
A merge queue creates a queue based on every PRs that pass the CI to merge them automatically and sequentially, and it updates any outdated PR with its base branch before it is merged. It forces the CI to retest the PR with the new code from its base branch. All in an automated way, catching any potential regression.
Remember the first graphs explaining the problem companies are facing? The following one is the same thing but with a merge queue. It will automatically rebase the PR by merging the main branch into the feature branch.
Haim from Epsagon, a Mergify user, wrote an article called ''How Merge Queues Made My Life Easier''.
He also created a GitHub repository with built-in PR automation and merge queue configuration.
V. Why Is It Safer to Use a Merge Queue?
Using a merge queue provides several benefits that contribute to a safer main branch:
1. ✅ Controlled and Ordered Merges
One of the key advantages of using a merge queue is that it allows for controlled and ordered merges. Changes are queued up and merged one at a time, ensuring that each merge is carefully executed. This sequential approach prevents conflicting changes from being merged simultaneously, reducing the risk of code conflicts and instability in the main branch. By maintaining a structured and controlled merge process, a merge queue helps maintain the integrity of the codebase.
2. ✅ Automatic Rebase
With a merge queue, each of your PR embedded in the queue is automatically updated before being tested. It means that the merge queue will make sure that each PR in the queue is up-to-date by merging the main branch into the feature branch. Then the CI rerun to make sure the PR is mergeable, and it's automatically queued and merged. Amazing. You don't need to do anything; it will be handled automatically, allowing you to spend time on projects that matter.
3. ✅ Automated Tests
Integrating automated tests into the merge queue workflow adds an extra layer of safety. The merge queue can be configured to automatically run a suite of tests, including unit tests, integration tests, and any other relevant checks specific to the project. These tests ensure that the changes being merged do not introduce bugs or regressions that could compromise the stability of the main branch. Running these tests as part of the merge process can identify potential issues early on, allowing developers to address them before the changes are integrated into the main branch.
4. ✅ Build Validations
The merge queue can perform build validations to ensure that the merged code integrates smoothly with the existing codebase. This includes checking for compatibility issues, verifying that all dependencies are correctly resolved, and validating that the merged code compiles successfully. By running these build validations during the merge process, the merge queue helps identify any issues that may arise due to incompatible changes or missing dependencies. This ensures that the merged code is compatible with the main branch and reduces the chances of introducing instabilities or build failures.
VI. Some Specific Features To Keep your Main Branch Green
The merge queue is a powerful concept with key features that contribute to making your code safer:
The Queue Freeze feature allows you to temporarily pause the automatic merging of pull requests in the Merge Queue. This is particularly useful during critical periods, such as holidays or maintenance windows, when you want to ensure stability and avoid unexpected issues. By freezing the queue, you prevent any potential disruptions to your main branch, effectively making your codebase safer.
With Speculative Checks feature, you are able to update and test multiple pull requests, at the same time, in parallel. All of that following a speculative way.
Let's understand it with an example: with Spec Checks you would run a CI job on PR#1, a job on PR#1 + PR#2, a job on PR#2 + PR#3, and a final job on PR#1 + PR#3. The idea is to ensure their mergeability and compatibility.
The merge queue allows you to set priority levels for pull requests based on their importance or urgency. By assigning higher priority to critical bug fixes or security patches, you ensure that they get merged and deployed quickly, reducing the time to resolution. With priority management, you can prioritize safety-critical changes, making your codebase safer by addressing high-priority issues promptly.
The multiple queues feature allows you to organize and prioritize pull requests separately. For example, you can have separate queues for bug fixes, feature enhancements, and experimental changes. This segregation enables you to apply different merging strategies, quality checks, or approvals based on the nature of the changes. By maintaining distinct queues, you can mitigate the risk of unintended side effects and maintain a safer codebase.
Backports are a powerful feature that allows you to merge pull requests into multiple branches, such as backporting bug fixes to older versions of your code. By automatically backporting critical fixes to stable branches, you can ensure that all active versions of your software remain secure and reliable. Backports help maintain the safety of your codebase by keeping older versions protected from known issues.
Checks can be tailored to your project's needs and can include additional quality or security validations that go beyond standard automated tests. By leveraging custom checks, you can enforce additional safety measures and ensure that your codebase meets the specific standards and requirements of your project.
Mergify developed all these features with the aim of helping you to improve your code safety, saving you a lot of time to focus on your projects.
VII. Interesting Case Studies
Working with dev teams all around the world, we created resources to illustrate how Mergify can concretely help developers save time and be more efficient:
Implementing a merge queue in your development workflow can significantly improve the safety and stability of your main branch.
By automating tests, code reviews, and build validations, a merge queue provides a systematic and controlled approach to merging changes.
This not only reduces the risk of conflicts and bugs but also streamlines the development process, allowing teams to work more efficiently.
Consider adopting a merge queue to keep your main branch safer and your development workflow smoother.
➡️ Interesting in trying the most advanced merge queue for free? Check Mergify Merge Queue and ask for a demo.