Five kinds of branches
Monday, May 7th, 2012I do not like the Launchpad branch page. It is rarely informative and I would like to ignore it, but there are a few tasks that I can only perform form that page. I think the page could be better if it were possible for me to state the branches’s purpose.
I sat down the Huw, the Launchpad team’s designer to discuss the page almost two years. He was struggling to make sense of the the branch page from a developer’s perspective. At that time I concluded that I disliked the page because it treats all branches as if they have the same needs, which ignores the fact that every branch has a purpose. A branch’s purpose determines what I need to know and what actions I can take. I saw two purposes at the time, but I recently concluded in a sleepless state that there are five purposes. Maybe this was a delusion created by the fever. Let’s see if I still think that at the end of this post.
The branch page is missing:
- A statement of intent
What is the branch’s purpose? This determines the action I can perform and the information I need to see. Is this branch trunk, a supported series, for packaging, a feature, or a fix? - A record of content
I want to browse the files of some branches, while other branches I only care about the diff. - A testament of accomplishment
A branch’s purpose determines its goal. The goal of most branches is to merge with another branch. Some branched though must create releases or packages.
The features a branch needs are mostly determined by the how long the branch is expected to live:
- Short-lived branches
The branch is often based on trunk, its purpose is to fix or add a feature (Bug or blueprints), and it goal it is to merge into its base branch. - Long-lived branches
The branch is often the basis of other work. It is the sum of many merges, often summarised as milestones. The goal of the branch is to create releases.
Trunk branch
The most important branch to every project is the one designated to be trunk. This branch will live for months, or years. This is the branch I use as the basis for my changes. It is the goal of most derived branches to merge with this branch. The goal of trunk is to make releases.
There is no need to show me which bugs are fixed or blueprints (features) are implemented in trunk. Trunk is everything to the project. When we say there is a bug in a project, we really know that bug is in trunk. Launchpad could change how it models bugs to make this case clear. The bug tracker or specification tracker are the only tools that can adequately explain which bugs and blueprints were closed. I might be interested in which bugs and blueprints were recently fixed in trunk though.
The merge action does not make sense. It is the goal of other branches to merge with trunk…trunk does not merge with other branches! Well this is not entirely true in the packaging case, which I will explain shortly. I am interested is seeing the list of recently proposed merges into this branch. The branch log shows me which branches were merged.
I want Launchpad to shown me the bugs and blueprints that the project drivers plan to fix. Will my bugs be solved soon? Can I contribute? Launchpad actually can show me this on the series page. Launchpad separates the concept of planning changes (feature and fixes) from branch. There is good reason for this, but the separation of information creates a chasm that many developers fail to cross.
We commonly organise change into milestones, and each milestone may culminate in a release. A series of milestones represent continuity and compatibility. Distributions have a series without having a trunk branch. There are also projects that do not produce code, but have bugs and blueprints. Launchpad is also a registry of projects and releases that are packaged in Ubuntu.
Launchpad creates a trunk series for every registered project because we believe all projects should state their intent and distinguish between different bases of code. But where is the code? Where is my branch? I commonly see projects with series information without a branch, and I commonly see projects without series information, with tremendous branch activity. It is difficult to contribute when you cannot see what is happening and what needs to happen. Project maintainers are equally frustrated; Launchpad is not helping them to create releases from their trunk branch.
Launchpad asks me to link a branch to a series, but I think most developers want to state that their branch is the trunk series, or is a supported series. The branch is elevated to a new role and it gets the features that the role needs. I want one page about the trunk branch, not a page about planning and a page about branch metadata.
Supported series branch
A supported branch represents a previous project release. It is a historic version of trunk with its own bugs and features. Like trunk, the linked bugs and branches do not make sense, nor do I want to merge a supported branch into another branch. A supported branch can live for months or years. Some fixes (branches) will be merged into the support branch. Feature branches are never merged into supported branches.
In the case of a supported branch, I most want to know the milestones/releases that represent the life of support. I want to know which fixes in trunk will be backported to the supported branch. I might be interested in knowing the fixes (branches) that were recently merged.
Packaging release branch
A packaging branch contains additional files needed to create an installable package from a project’s release. A packaging branch often has counter-part branch, usually a supported branch, but sometimes trunk. Thus the packaging branch lives for months or years. The packaging branch may only contain the extra files to create a package using a nesting recipe, or it contains repeated merges of the counter-part branch. I am only interested is seeing the differences from the counter-part branch. I do not want to browse all files in the branch.
Packaging branches have their own set of bugs — the files introduce bugs and yet some of the patch files fix bugs in the counter-part branch. Thus we might image that the packaging branch is the sum of the bugs in the supported and packaging branch, minus the fixes provided by patches.
Packaging branches are often managed by different people from the project’s developers. Their skills and permissions are often different too. A patch to expediently fix a bug in the packaging branch might take much longer merge into the supporting branch where the bug originates.
Feature (blueprint) branch
A feature branch adds new functions to the code. It is short-lived, measured in days or weeks. The branch is based on trunk and is goal is to merge with trunk.
Feature branches need all the features that the current branch page provides. The feature branches has blueprints that specify what functions are being added and the criteria to know when the feature is done. They may also fix bugs. A recipe can be used to build an unstable package for testing.
Merges are far more complex for feature branches than is implied by the Launchpad’s UI. There are many workflows where a feature branch is actually composed of several branches that might be merged with trunk individually, or they are merged as a whole when the feature us deemed stable. Launchpad should encourage me to merge the branch into trunk, merging into another kind of branch doesn’t make sense. The UI does not properly show that I may merge my feature branch into trunk several times, or that several branches might merge into my feature branch.
I am only interested in seeing the changes from trunk. I do not want to browse all the files in the branch. Since a feature branch can be composed of many branches, I want to see the difference between the merges to understand the revision changes.
Fix (bug) branch
A Fix branch exists to close a bug. The branch is short lived, measure in hours or days. Its goal is to merge with its base branch. The older the branch gets, the more likely that it has failed.
It does not have related blueprints or recipes. I am not interest on seeing all the files and code in the branch; I only care about the changes from base.
A fix branch needs to tell me which bugs it fixes. It must encourage me to merge the fix back into the base branch.
Most fixes are based on trunk and will merge with trunk, but when a bug also affects a supported branch, Launchpad might want to encourage me to propose a backport. Launchpad currently allows me to nominate/target a bug to a series (which is ultimately a branch) when there is no fix. I think this is odd. Project development is focused on trunk, fixes are almost always made in trunk first. Once trunk has the fix, it is possible to determine the effort needed to backport it to a supported branch. If a bug is only in a supported branch, then I think it is fine for Launchpad to allow me to nominate it to be fixed, which implies the fix is already in trunk.
Conclusion
Hurray! I still think there are five kinds of branches which different needs. This issue is like a bad word processor which treats a letter, a report, and a novel the same. A good word processor knows the document’s intent and changes the UI and available features so that I can complete my task without distraction. The current branch page emphasizes what all branches have in common, but it needs to emphasise the differences so that I know what I need to do. There are no plans to change the branch UI, but contributors are welcome to improve Lp. I hope my thoughts will contribute to a proper analysis of features the branch page must support.