How to avoid the dreaded merge conflict hell?
At one point or the other, we have all found ourselves guilty of trying to merge our changes before everyone else’ to avoid bearing the pain of resolving the infamous merge conflict hell.
Often resolving merge conflicts takes up a huge chunk of the development time and is sometimes even accepted as a norm.
Is it possible to reclaim this time and go faster?
Let us start by understanding a few of the most popular and adopted development strategies when working in teams.
Trunk based development
It is a development strategy where developers work on the main/trunk/master branch. Branches are only created when it is absolutely necessary.
These branches are short-lived and merged into the main branch frequently so as to keep the main branch updated.
The idea is that since only one long-lived branch is present which is frequently merged into, there will be very least or zero conflicts at any given time. The basis of TBD is to merge as frequently as possible irrespective of that fact the feature is complete or not.
This usually works with feature toggles, flags, dark launches etc. It means to be comfortable with partially complete features to be a part of the production.
Keep CI green.
It is absolutely critical in this type of development that the CI pipeline is kept green almost all the time so that no one else is blocked. One way to do that is to use pre-commit hooks etc and only allow commits to go to remote when all checks pass.
- The branch is always ready to be delivered irrespective of the point of time.
- Development is fast as small features and fixes are immediately merged to the main branch
- Merge conflicts are very less as changes are integrated continuously.
- Works well for small to medium-sized teams
- Managing feature toggles and flags can be cumbersome
- All developers must have good knowledge of feature toggles, dark launches etc to collaborate well.
- Possibility of stepping on each other's toes.
This type of development is the polar opposite of trunk-based development.
In this approach, branches are created for each feature and they are only integrated to master when the feature is complete and has been tested in isolation.
These branches are long-lived depending upon the size of the feature allowing developers to work in parallel without worrying about stepping upon each other's toes.
This means fewer broken builds.
- Developers can work in parallel
- Features can be tested easily and in isolation without worrying about how it affects the entire project.
- Works great for the open-sourced projects where you don’t want all changes to be merged to master without proper review and testing.
- Works well for huge teams
- Feature branch if lives long enough can cause a huge amount of merge conflicts with other branches.
- Might slow you down initially as reviewing and merging takes time.
Stage based development model
One other popular development model is the stage-based development model. The idea here is to maintain different branches for different stages. These can be
- Nightly builds
- And so on
The benefit is the separation of concern here. The developers can build and push features to the dev branch and while completed features can be tested on the QA branch in parallel.
The backbone of this approach is a strong pipeline to promote code from one branch to other.
In real-world teams use a mixture of these development models to meet their requirements.
For eg., feature-based development can be used with stage-based development to get the benefit of working parallel along with separation of concerns with environments.
A team can also start with TBD and end up using feature-based development or vice versa.
While there are a lot of developments practices with their own benefits and cons, a team can choose any one of them or even a hybrid approach to make the overall development process faster, smoother and efficient.
The decision can be based upon the team size, repo size, frequency, delivery, and other such aspects.
I have had an opportunity to be a part of various kinds of development strategies. In my experience in small teams, TBD is the right choice as frequent commits on master increase speed with no hassles of creating and managing PRs.
On the other hand in medium to large-sized teams feature branches help way more as everyone gets to concentrate on their own feature parallelly without worrying about stepping over each other toes, also PRs and code reviews help in maintaining the overall code quality.
Generally, teams use a hybrid approach like:
- Trunk based development + Stage based development
- Feature-based development + Stage based development
Remember, none of the approaches is forever a silver bullet so it is absolutely critical that whatever you choose, make sure that your team evaluates it every once in a while and adjusts the approach accordingly.
The hope is eventually we won’t be dreaded by the merge hell ever again 😛.
I hope you enjoyed :)