When it comes to good software consulting, Entrance spends a lot of time on maintaining good best practices so that we can produce awesome custom software for our clients. To that end, I’d like to cover a few things that I’ve learned recently about code branching and merging. It should be helpful not only to technical leads on projects, but to all developers on teams as they seek to work together efficiently and seamlessly. The terminology used in this article is defined at the bottom.
Pros and Cons of Branching
As we consider branching and merging of code, we should note that these solutions are context-dependent. As noted in the TFS Branching and Merging guide, “there is ‘no one size fits all’ branching strategy.” Thus, it is helpful before creating branches to consider the inevitable costs, such as:
- Increased complexity.
- Possible loss of work and introduction of bugs through failed merges.
- Increased maintenance costs as:
-Someone needs to continuously Forward Integrate (FI) and Reverse Integrate (RI) change sets between the branches.
-Permissions need to be set properly for each branch.
-Merges between child branches become difficult.
For these reasons, one should carefully consider the possibility of a single code stream approach before creating branches within any given project. As noted in Professional Team Foundation Server 2012, “This should always be your default position. Do not branch unless you need to.” For small projects where there are only a few people working in any given area, a single code stream can reduce complexity and unintentional loss of work through merges.
Additionally, the use of shelve-sets can give developers a way to share/save changes without the creation of an additional branch. The ALM Rangers note in the below image (click to expand):
Of course, there are benefits to branching:
- Branching isolates code and creates stability within that branch. This is especially helpful for Release branches, as you can go back to the Release branch and make emergency fixes without being affected or affecting current development work.
- Branching allows multiple teams to develop in parallel. Although individual developers can use shelve-sets and local work-spaces to develop in parallel, if you plan to have multiple teams working on different work items in similar sections of code, giving each team a branch will speed the process and give that team more focus. This is helpful for major enhancements/feature adds.
For more from Entrance’s software consultants, check out our series on SQL server tuning.
Standard Branching Strategy
Currently, our standard branching structure revolves around three main branch types, as shown in the below image.
- Main – This is the main parent branch. No code changes should be made directly into this branch.
- Dev – This is the main development branch, and is a child of Main. All general development work happens in here. For smaller projects, the Main and Dev branches can be combined.
- Release1.0, Release 1.1, etc. – One branch is created from Main for each release of the product before QA, and QA fixes are made directly in this branch. This allows stability of the product and makes it easy to push out emergency fixes. Although these branches can be maintained indefinitely, it is recommended that only 2 (previous and current versions) are kept, and the others archived or deleted.
- Feature – This is a special kind of branch which is created from Dev in order to add major features/enhancements which would otherwise prevent other development from happening in Dev. These branches are temporary and should be removed as soon as the feature is completed and changes are RI to Dev. Note that branching from Dev allows it to serve as an integration branch for features. This way, when there are issues merging between random fixes in Dev and large features in our feature branches, those conflicts can be resolved and unit tested in Dev rather than in our Main branch.
One person should be assigned to oversee regular merging for each project – otherwise it will never happen until significant merge debt has accumulated. Emergency fixes made in a release branch should have RI done immediately after the fix by the developer.
Handling exceptions/baseless merges
Occasionally, there are situations where merges will need to happen between child branches. Some examples:
- An emergency fix is made in Release1.0, but Release1.1 has already been created and is in QA.
- A fix which was made in Dev is needed to fix an emergency issue in Release1.0.
These situations should be the exception rather than the rule. In both of the above cases, such issues might have been avoided with a shorter release cycle and increased code quality. The TFS Branching and Merging guide notes that “If there seems to be a need to do baseless merges regularly, it likely points to a flawed branching strategy.” However, when the need arises, the following should be noted:
- These merges need to be done manually and with caution. Do not blindly trust the merge tool.
- Think about how to merge this change back into the parent branch. For example, in case #1 above, the fix should first be merged from Release1.0 to Release1.1, and then RI from Release1.1 to Main.
Terminology
- Reverse Integration (RI) – Pushing a change-set from a child to a parent branch. This occurs in order to update the Main branch with changes from Dev or Release branches.
- Forward Integration (FI) – Pushing a change-set from a parent to a child branch. This occurs most often in Dev branches, which should be continually receiving changes from the Main branch.
- Baseless merge – A merge between two branches which do not have a parent/child relationship.
- Merge debt – A metric for understanding the amount of changes which have not been RI/FI between branches. The higher the amount, the more difficult it is to do the merge in the future. TFS has tools to calculate and report on this.
References
- More information about branching and merging best practices can be found in the Visual Studio Team Foundation Server Branching and Merging Guide.
- Professional Team Foundation Server 2012