WTP How to: Branching Policy and Practices
This page is to capture issues, best practices and pragmatic information on how to work with branches in WTP Development. This includes how and when developers should branch, and how other committers and members of the community can discover which branches they need load into their workspace so it matches a particular build or development stream.
Issues and Problems with WTP Branching
These are some of the main issues to consider.
- WTP Projects (and components) should have the flexibility to do branching as they decide, using what ever works best for them, their team's workflow, and habits.
- But, we need to make it easy for others to know what to load in their workspace, to match any particular stream or build.
- And, we need to avoid those silly bugs or build breaks where the wrong branch of code is released to the wrong branch of a map file.
There can be complicating factors
- Each team is usually doing something different from other teams; focusing on 2.0.x maintenance versus focusing mostly on 3.0.0 development.
- There are probably some bundles that will not change much in either stream, others may change a relatively large amount in both streams.
There are several ways to accomplish what we need, and the difference between them are how they balance the issues above. (That is, none are perfect).
On one extreme, we could just say we'll branch everything at once so it's clear what to get, and where to do work. The concern is that this will be more work for developers ... error prone work, at that. The extra work to ensure bugs fixed in 2.0.x get rolled up to the HEAD stream. Tools could help, but some have expressed less that stellar success with merge utilities.
On the other extreme each team could do branching on a plugin-by-plugin basis, as they found a need to. This would be easiest for those actively working on the code, but not easy for other committers from other WTP teams, and certainly not the community at large! Plus, this method would be prone to the error of releasing into the wrong map, since easy for mis-matched bundles to end up in the same workspace, in the same map.
So, I propose a compromise between the two extremes, something larger than a plugin, but smaller than everything. A "feature" might be one such branching unit, but there are no tools oriented towards CVS and features. Therefore, I suggest we use the map files as the operational "unit of work" when making or getting branches.
To give a concrete example, if someone was to make a 3.0-only change in the xml.core plugin, then at that point, besides just branching xml.core plugin, all the other bundles listed in wst-xml-core.map must be branched also, namely sse.core, xsd.core, and dtd.core. This would help make sure bundles of a map stayed together as a branch, making mis-released code more unlikely.
And, on the other hand, if not much new work was going on in, say, the xml-ui plugins, they would not have to be branched, so any bugs fixed there would be expected to be released twice, using exact same cvs tag version, into both branches of releng maps. The importance of using the same cvs tag version is that the cvs version tag becomes, or contributes to, the bundles qualifier field. Ideally, when two bundles are exactly the same, even though in different builds, then they have the exact same version number, down to the qualifier. This helps others (and automated tools) to know that they are the same code. [Note: we'll have to double check, but am fairly sure the releng tool still works as expected if you specify an existing cvs version ... it still updates the map files correctly and does not throw an error that "tag already exists". Please edit here if discovered to be true or not true].
In many cases, the map files correspond to the distinct build-component-features we use, so, conceptually this is the same as the branching feature by feature.
Of course, there is no need to specifically limit branching to only one-map-file-type of branching, that's just the "minimum unit" of bundles that should be branched together. Some teams, components, or projects may want to branch all their project code at once, for example, so as long as each map file, as a whole, has all it's bundles branched together, then that is fine.
- The releng project, for the map files, is always branched for maintenance, using conventions in the name such as
R1_5_maintenance, etc. The
HEADstream of releng is always used for the most forward looking release.
- A bundle should be branched for the maintenance release, as soon as the code that is going into the forward release is different from the code that is going into the maintenance release. These means that even though the version being built for maintenance does not change (yet) a branch should still be created once the builds contains different code. This helps avoid confusion, especially when people need to make make quick fixes to fix a build or something.
- The best way to create a branch is to first of all use the same naming convention used for the releng project: that is, for example, use the name
R2_0_maintenance. Second, as the "starting tag", ideally it is best to use the closest previous-release tag. For example, when you create
R2_0_maintenancefor a bundle, you should use
R2_0as the "starting version tag" (rather than the default of
Root_R2_0_maintenance). This uniformity in starting tag (which is created by releng team, right after a release) can make later merging/comparing easier, especially when the operation spans multiple bundles. Note: this assumes
R2_0at the time of branching. If that's not the case, it may still be feasible and desirable, but it may be more complicated, and likely handled on a case by case bases.
- The map file itself should identify, in file comments, the branch that the bundles in that map file come from. This way, when someone loads the releng project for a certain release, they can "drill down" in the map files to see what branch they should load from, for a particular area of code. For example:
!*************** wst-xml-core.map ! This map file is for ! WTP 2.0.x maintenance releases ! These bundles are currently being developed and released ! from the HEAD stream firstname.lastname@example.org=v200705302225,:pserver:email@example.com:/cvsroot/webtools,,wst/components/dtd/plugins/org.eclipse.wst.dtd.core firstname.lastname@example.org=v200706212223,:pserver:email@example.com:/cvsroot/webtools,,wst/components/sse/plugins/org.eclipse.wst.sse.core firstname.lastname@example.org=v200706120811,:pserver:email@example.com:/cvsroot/webtools,,wst/components/xml/plugins/org.eclipse.wst.xml.core firstname.lastname@example.org=v200707172046,:pserver:email@example.com:/cvsroot/webtools,,wst/components/xsd/plugins/org.eclipse.wst.xsd.core !***************
Or, for example,
!*************** wst-xml-core.map ! This map file is for ! WTP 2.0.x maintenance releases ! These bundles are currently being developed and released ! from the R2_0_maintenance branch firstname.lastname@example.org=v200705302225,:pserver:email@example.com:/cvsroot/webtools,,wst/components/dtd/plugins/org.eclipse.wst.dtd.core firstname.lastname@example.org=v200706212223,:pserver:email@example.com:/cvsroot/webtools,,wst/components/sse/plugins/org.eclipse.wst.sse.core firstname.lastname@example.org=v200706120811,:pserver:email@example.com:/cvsroot/webtools,,wst/components/xml/plugins/org.eclipse.wst.xml.core firstname.lastname@example.org=v200707172046,:pserver:email@example.com:/cvsroot/webtools,,wst/components/xsd/plugins/org.eclipse.wst.xsd.core !***************
- Normally, a project or component team will know when the bundles in a map file have been branched, through the wtp-releng mailing list, or hallway talk. Nevertheless, when releasing code, it's good practice to expand the changes to the map files, there you can double check that the branch you have been working with are still the same branch that is appropriate. If not, the release should be canceled until the branches in your workspace are synch'd up correctly.