February 14, 2015

BPGB: Feature Branch Fail

The past few generations of version control systems have really good support for branching. This feature allows someone to create a new line of development that is separate from the official main/master/trunk line of development. Changes made on a branch do not affect the main development until they are merged to the main branch.

Shortly after people become comfortable with branches, they notice that branches can solve the problem of big changes breaking the master branch.

Feature Branches, In Theory

One workflow used to keep the master branch clean is Feature Branches. The idea is to create a new branch for each bug fix, change, or new feature that you want to work on. As long as the change is not complete, you continue making changes on your feature branch. When everything is working satisfactorily, you merge the feature branch back into the master branch.

For small changes, this works incredibly well. Different people can work on their own tasks independently of each other until they are ready to merge. Nobody else's changes affect your work until you are ready to merge. Everything seems wonderful and bright.

The First Cracks

The first problems in this perfect workflow occur when two people make overlapping or conflicting changes. The second person to merge gets a merge conflict and/or failing tests. This is actually not that much different than the problem with doing all of the changes on the master branch. Modern DVCSs usually handle the textual conflict pretty well. A good test suite will usually uncover semantic conflicts pretty quickly.

This means that no one tends to see this as much of a problem.

Long-running Feature Branches

Feature branches work pretty well for the short term, but what happens as the branches live for longer?

The longer the feature branch stays disconnected from the master branch, the more potential conflicts build up. The advantage of having changes to the master branch not affect your feature branch comes at a cost of merge pain later. Doing regular merges from the master branch into the feature branch can mitigate this problem at the cost of more frequent, smaller potential pain points.

Just as importantly, the longer the feature branch runs, the more changes it collects relative to the master branch. This means that when the feature branch is finally merged, it will probably cause disruption to anyone else working on master or their own feature branches.

Positive Feedback

Probably the worst part of this problem is an annoying feedback loop caused by merging. As long as merges go well, people are willing to do them regularly. When a merge is conflicted, however, the developer may find they have an aversion to doing frequent merges. After all, if any merge could be painful, we probably want to reduce the number of opportunities for pain.

Unfortunately, the longer you go between merges, the more likely you are to have merge conflicts (all else being equal). This reinforces your idea that merges are painful and makes you more likely to put them off. This positive feedback loop can pretty rapidly create worst case feature branch merges.

Dependency on a Feature Branch

Another fun failure mode for feature branches is when someone creates a feature branch that depends on an unfinished feature branch. This shouldn't happen often, but it becomes more likely the longer a feature branch lives.

As an example, let's say that Bob is working on a long-running feature branch that replaces the logging system used by our server. Sue starts a new feature to add fail over capabilities to the server allowing us to have more than one server at a time. In working through the problem, Sue realizes that Bob's new logging would make some of her work simpler. She merges Bob's changes into her feature branch after talking with Bob to learn how the feature can help.

The problem occurs when Sue finishes before Bob. She merges her code into the master branch and suddenly Bob's unfinished code is part of the system. This partial code now ripples into every feature that is keeping up with master. If things go well, Bob can finish his feature soon and merge it in. If his code really isn't ready for general use, then everyone is at least partially broken for a while.

Conclusion

Short-lived feature branches are a good idea. The longer a feature branch lives, the more effort is needed to keep potential problems in check. People who are new to this workflow often get stuck on the idea of the independence of the branches and don't realize the problems lying under the surface.