Tuesday, 22 November 2016

trunk based development and the troubles it brings.

- or why isn't the github flow trunk based?

Abstract

I had worked with personal and feature branches for quite a time when I started to work in a new team. This team was blaming any kind of branching as the evil itself.
In the discussion about this topic I've tried to explain:
  1. Each local repository is a branch from the way git sees them anyway.
  2. Trunk based development hinders me in experimenting.
  3. Trunk based development leads to a messed up commit history.
  4. Trunk based development encourages developers to hold back their pushes until why are sure what nothing will break.
The teams view is:
  1. Anything can be solved by feature toggles - read Martin Fowler about feature toggles.
  2. As long as your'r cloning to the same branch name you don't need to know that your on a separate branch.
  3. A good/disciplined developer will never hold back anything. He will always build the feature toggle first and will often push.
  4. If you are working on a feature branch you will not be covered by the CI build.
  5. If two developers are working on different branches way will have a hard time to merge if they have finished the feature.
To get a better view on the arguments of the team I'v looked around for articles about the topic.
  1. They always merge if they should rebase (while discussing not trunk based development).
  2. They ignore the cleanliness of the commit history.

How merging instead of rebaseing has almost killed our repository even with trunk based development

Developers not knowing their tools are an accident waiting to happen.
We do have a large repository which is under heavy refactoring for more then 6 months now. The work of 4 developers over 3 weeks was removed from the HEAD by an wrong done merge.
What happen'd?
  • A fifth developer was on vacation for 3 weeks
  • On his first day back he has not pulled but started with his first task.
  • After he had finished his ui git tool has refused to push since he hadn't pulled first.
  • He pulled in merge mode since this is the default on his repositories.
  • He solved the merge conflict by clicking on 'take my changes'
  • He pushed without further checks.
OK - the accident was solved by a force push with the previous commit as HEAD. But you don't want to do that too often.
And guess - we had the same problem again on the next day with an other developer.

Now we have introduced the developers to setup 'git config --global branch.autoSetupRebase=true' but we should make sure they know their tools better.

How trunk based development messes up your commit history.

My main concern about trunk based development as it is described here is the messy commit history you'll get.
But the second thought is always: If developers don't know how to handle a simple rebase - do you really want them to do cherry picking?

Let's look how a trunk looks like if there are multiple developers working on multiple features.

You can do it with release cycles using release branches.


Or you can do it using continuous deployment where each commit leads to a potential release.



The resulting commit history of release v1.1.0 or its corresponding release from the continuous deployment repository will be a mixed up list of multiple features.
  • Feature-D commit message
  • Feature-C commit message
  • Feature-B bug fix commit message
  • Feature-D commit message
  • Feature-A bug fix commit message
  • Feature-C commit message
  • Feature-B commit message
  • Feature-A commit message
Is this really readable without filtering tools?
Let's imagine a bigger team and more features developed...



Feature toggles and their removal will not help but add additional commits to this mess.

How branched development dose help to create a cleaner history.

Let's start from a repository having two features finished, two features under development and two bugfix commits done to the two finished features.
For this demo it doesn't matter if you are using branches per developer or per feature. If there are more than one developer working on the same feature whey have to coordinate their rebasing but that should be possible.
But to keep it simple let's assume there is one developer per feature.



Both feature branches need to be rebased after the bugfixes took place to have them integrated with the actual work.



When the first feature is finished (Feature-C in this demo) it's branch will be merged into the master. This is the correct situation to use merge and not rebase.




The resulting potential release will contain Feature-A, Feature-B, the two bugfixes and Feature-C. But not the Feature-D which is still under development.

The branch used for Feature-D must now be rebased to include Feature-C and to make sure it'll not break any previous development.



When finally Feature-D is finished and merged into the trunk your repository is in the same state as it was with release v1.1.0 but with a much cleaner history.



In a direct comparison you'll see how the related commits are grouped in the branch based approach.
Trunk BasedBranch Based
  • Feature-D commit message
  • Feature-C commit message
  • Feature-B bug fix commit message
  • Feature-D commit message
  • Feature-A bug fix commit message
  • Feature-C commit message
  • Feature-B commit message
  • Feature-A commit message
  • Feature-D commit message
  • Feature-D commit message
  • Feature-C commit message
  • Feature-C commit message
  • Feature-B bug fix commit message
  • Feature-A bug fix commit message
  • Feature-B commit message
  • Feature-A commit message

Conclusions

I do agree that branches add extra effort to the CI build. But I'm sure it's worth the effort.
I'll do a future post on how to do CI builds on multiple branches.