Friday, October 7, 2011

Trunk based development

In our team, we’ve recently changed our source control strategy to what’s now being called ‘trunk based development’. This has reduced the amount of merge-headaches we were having.

In the past, we used a form of branch-per-feature with only one branch. We would have a trunk and a development branch (we’re using Subversion). Coding would be done on the development branch, and when a story/feature was finished, it would be merged to the trunk. After the merge, a new development branch was made. The trunk was, in effect, always releaseable.

At least, that was the theory. This didn’t really work in practice:

  • sometimes a feature can’t really be released without the next story
  • bits and pieces of the next story would have been implemented before the previous story had been finished (otherwise developers would be sitting around, waiting for the merge before committing)

More importantly, this slowed us down because:

  • there were conflicts when merging (when a fixes branch touching the same code had been merged in the trunk)
  • it takes some time to merge, build, commit, delete the old branch and make a new branch (meanwhile, teammembers can’t commit code to the old branch)
  • this is inherently error-prone, as conflicts could be resolved wrongly, (re-)introducing bugs, often only discovered when the code was already in production

Finally, there was no need for our trunk to always be releasable, because we know when we’re going to release and with any modern source control system, you can jump back to certain revisions.

Curing headaches

Switching to trunk-based development is easy and we haven’t looked back since. The point is:

  • Develop and commit to the trunk
  • Make tags from the trunk
  • Bugfix branches are made from the tag, but are merged to the trunk again of course

The only problem you can have, is at that moment just before a release. There are two smaller tasks that need to be finished for the tag, but other developers want to start with the next story. This next story is not allowed to be included in the tag.

The solution is simple: make a branch to finish the work for the tag. Finish the job, make the tag from this branch en merge the changes back into the trunk. No need to remove this branch as it can serve as a bugfix branch.

Here’s a colorful diagram to make this post look professional:

Trunk based development

In the end, this makes our development track more fluent, less stressful, less complicated, and hasn’t given us any problems.

At the moment we researched this, there wasn’t very many information to be found. But these are the articles we based our decision on:


Dwight said...

Hej Peter, have you checked out this article, this is the model we're using for our private projects:

Madhav Deverkonda said...
This comment has been removed by the author.
Madhav Deverkonda said...

Your idea seems to be great for one application..
And I think we had ideas to follow this pattern but execution was bad.. so never really worked for us..
But i see value in it..

But I have a different problem domain..

We have huge dependency chain..
For our App to be deployed into a stage.. so many other apps (built from different jobs on Jenkins) need to be deployed and working properly. So we spend lot of time on building a stable state than testing some module functionality for a given app.

will 'Trunk based development' solve this problem.. i mean all apps if they checkin to same trunk.. every app is built of the trunk and deployed... do you think 'our time spent on bringing stage to a stable state' pain-point will be reduced .. even a little bit ?

Peter said...

We had one application indeed, but it integrated with several others. But every application had their own repository. Integration was done by referencing the dll's of certain revisions. This requires some coordination effort so the applications are release in correct order, etc. But it worked.

Every team must take responsibility to have a stable working version in the necessary stage. If your app needs another app, you need to be able to trust the other app in being stable, finished, working properly.

Combine this with regular (or continuous) deployments and any unstable parts can be quickly resolved.

If your team has no problems with merging, this approach may not be necessary. But it seems to me that putting your time in getting a stable branch will amount to the same effort as getting a stable trunk, no? But with the branch-approach, you still need to merge, which is extra time lost.

So yeah, I think you can win time, but I don't think you will solve the 'time spent on bringing stage to a stable state' pain-point will disappear this way. You'll have to identify the real causes of that pain-point in order to mitigate them (not enough tests? not enough communication between teams? not enough responsibility/code-ownership? no clear definition of stories? etc.)