Trust the merge and branch simplification musings
Branching workflows go from bare and simple, to complex, robust, and defensive. What is the level of complexity and safeguard needed by your organization? This post covers the compromise between nimbleness and robustness, with some guidelines to choose your own
git adventure and lessons learned inside Atlassian.
The aim of this article is to give you the insight and tools you can use to decide how to choose the most effective branching model for your team.
- Trust the merge
- Stay away from branching model extremes.
- Simplify and flatten branch hierarchies when possible
- Consider how your development process and your tooling impact the branching model decisions
Trust the merge
The first step in choosing the optimal branching model is to trust the merge. I mention this for teams that have only recently adopted
git;If you've passed this step and have embraced the
merge, skip this paragraph.
While in older systems you could be brought to extreme measures – like avoiding merges at all costs or hire a special team to take care of the merge hell – turns out merges are a non-event in git. This is due to several key things:
- Because branches are very cheap and fast,
gitencourages short-lived branches and fast integration.
- Merges are local in
git, hence the result of a merge is often immediate.
gitknows the ancestry of your branches and only merges the commits that are relevant instead than the entire work-tree flat. This generally results in less conflicts.
- You have a plethora of merge strategies at your disposal. Because of this you will love to merge and by converse you will also love branching. Branching and merging become so easy that some teams end up with the opposite problem, they go overboard with them. So as with all in life, maintain a balance and don't overdo it.
Stay away from branching extremes
If you look at branching models at large – pre- and post-
git advent – you see they sit on a spectrum that goes from simple to layered. Extremes can be problematic. Let me show you a few stops on the branching continuum and why you might want them or not.
Single branch extreme
Memory of subversion past: one branch to rule them all. For years softwareteams (myself included) worked with just one branch, the
trunk, in good or bad weather, with finished on unfinished features, with working or broken builds. This process used to work and it works still today. But it's not the most efficient anymore.
The one branch world we loved to hate and we grew up with and some of us still use, looks like this:
Teams fresh on git adoption or teams that want to retain their workflow might try to reproduce the same feel. Even though the
git-speak is now called
main you can work with a single branch in
git, it looks like this:
Everyone works on
main, nobody works on branches and every single developer uses rebase to keep up-to-date with the latest changes. This is very close to an old style trunk-only subversion branching model.
It's not uncommon for me to hear modern teams that - yes - have embraced some level of branching but are nostalgic and enforce a squash on commit rule that flattens history and makes main look exactly as the picture above.
What do they miss? Context and traceability. For more read my piece on the merge vs rebase debate.
What is the major drawback of a single branch? When
main is broken the work of everyone is disrupted. It's true that with
gitdevelopers have the entire history of the project at their disposal. It is easy to go back in time to before the breakage and keep working until the problem is resolved. But it's true also that if a developer knows how to do this time travel smoothly, he is also using his own local branches to park his work.
Too many layers of integration branches
At the other end of the spectrum is an organization that likes to formalize processes too much and embraces branches in a way that complicates lives instead than simplifying them.
For example have a look at the following branching model:
In this example the team creates a branch for each user story, from each user story in turn a branch is created for each issue and from each issue branch a branch is created for each sub-task. Then it all goes into their
next branch from which they release to
I said it earlier and it's true: branching and merging is painless in
git but complicating your process will affect the velocity of your team regardless.
Simplify and flatten branch hierarchies when possible
At least now we know we should avoid the extremes. What is then a good compromise between structure and flexibility? It's easy to pin point your team's sweet spot by answering a few critical questions:
- What is the minimum number of long running branches I need to support my project?
- Do I need to maintain older versions of my software or not? In general you should try to flatten branch hierarchies as much as possible, compatibly with how strong is your test suite, the trust and level of responsibility you place in your team, your tolerance to production issues.
At Atlassian we use a relatively flat branching model in several of our teams, both for our BTF(behind the firewall) products and our On Demand offering(Cloud).
One branch per user-story or one branch per issue (Jira issue) ?
The granularity of branches matters. If they are too coarse and force many people working together you run into the single branch problems I highlighted before, if you create (and publish) too many branches, your review process and the overall picture can get confusing and bloated.
We've found that a good granularity in choosing the scope of branches is "One branch per issue".
Sane Workflow #1: Single stable main, leverage branches but keep it simple
My recent article on simple git workflows showed a simple branching model for continuous delivery. Which is centered around the notion that
main is the production branch. Any commit to
main is a tagged production release. It's a great workflow for example for web applications, store fronts, Saas and in general for situations when you don't have to maintain older historical versions.
Sane Workflow #2: Keep it simple but maintain older releases
When you have to maintain and support older versions of your products a single stable
main is not enough. The solution is to have a long running release branches for each version your team needs to support. Changes flow always from the older branches to the more recent ones, never in the opposite direction. For reason why see post on the essence of branch based workflows.
Extra integration branches when needed
Provided you know exactly why you can't do without it can be helpful to isolate the work of a small team of developers for longer than a single iteration. To accomplish this you can setup an integration branch. The branch should be updated with the latest from
main as often as possible, to simplify the final merge.
For example inside the Bitbucket Server team additional integration branches happen 1-2 times per release cycle - which in their case is around six weeks. Those are needed when the team has multiple streams of work that they need to keep isolated for a bit.
Development process and tooling has impact on branching model
Your team's development process and tooling have powerful impact on branching model decisions and the agility and effectiveness of the team.
And finally the more insight you have in the status and the deliverables of your teams, the more freely you can let everyone work in parallel.
Imagine if you could - at a glance - have a sense of the status of all builds, pull requests, branches, commits of a given feature. The great news is that this utopia is here today. Marvel at this beauty:
*This development panel is available with Jira 6.2, Bitbucket Server 2.10+, Bamboo 5.4.
What you see above is the 'Development' panel in Jira. When combined with Bitbucket and Bamboo, you have a single place you can go for all your development updates. This panel, available in all your Jira issues and rapid boards, allows everyone in the development cycle to be in sync. Stay on top of the status of your branches, identify the ones with broken builds and monitor their deployments without ever have to dig for information again. Spend time building and releasing great code, instead of tracking it.
This piece went longer than I anticipated but I hope it gives you a good set of guidelines on how to choose an effective and lean branching model for your teams. Follow me @durdn and the awesome @Bitbucket team for more DVCS rocking.