Where we have multiple derivative kernels in an Ubuntu series we represent those as separate topic branches in the series git repository. These topic branches represent the patch delta for that kernel from the master distro kernel (on the master branch). As the master branch is updated and released these derivative branches are rebased onto the updated master branch carrying those changes forward while still getting the fixes applied to the master branch.
Each topic branch also carries changes to the debian packaging, including naming changes to avoid collisions with the master kernels. Many topic branches are also limited to a subset of the architectures and/or flavours. For example the Karmic fsl-imx51 branch is only built on the armel architecture and introduces a flavour which is not present in the main distro branch. These type of differences necessitate significant modification of the contents of the debian directory. Modification to the debian directory lead to major conficts during rebases and significantly complicate the process of keeping these branches up to date.
The Debian Directory
Debian packaging and build operations require that certain files are present in the debian directory to drive and control the build and packaging process. Specifically the debian/rules, debian/control, and debian/changelog files are required to be present and in the correct format. The rest of the contents of the debian directory is free format, referenced only by our packaging machinary. We can use this property to split out the majority of the branch specific data into a branch specific location preventing modifications to the master branch affecting the branch.
In repositories with an abstracted debian directory you will find that there are two debian directories, debian/ which contains a skeleton rules file, and a branch specific debian.<branch>/ containing branch specific rules, configuration, and scripts. For example on the master branch you will find debian.master/ containing the classic contents of the debian directory. Debian build and other functionality operates as normal through debian/rules. For example, cleaning the tree is performed using the regular fakeroot debian/rules clean command.
The debian abstraction branch name should match the branch name in the repository (for sanity). It is set within the debian/rules file (see the DEBIAN= setting). This is typically set by a patch in the branch which should be the only change to the main packaging.
What is Abstracted
The majority of the build machinary and configuration files are abstracted. This includes all of the architecture and flavour configuration allowing a branch to apply to any architectures and generate any flavours required. It also includes all of the kernel configuration and ABI information allowing the kernels to have different options enabled.
What is not Abstracted
Some elements are not abstracted, elements which should be common to all branches. This includes the commmit templates guarenteeing consistancy across the all branches in a series.
Branch Specific ABI
In order to allow multiple source packages to be uploaded to the archive and to prevent the generated binary packages from ever colliding we allocate a separate ABI number range for each branch. These are series specific and allocations are recorded in the topic branches page.
By allowing each branch to have its own debian configuration we prevent changes in the master branch from conflicting with those in the derivative branches. This makes the act of rebasing these branches much simpler because they cannot cause a conflict during the rebase operation, making the chances of a totally automated rebase much higher.
The main disadvantage of the split is that any changes and improvements in the master debian machinary branch will not automatically propogate into these derivative branches. This implies if you are making an improvement on the master branch you should consider whether this should also be applied to all derivative branches.
How to Make a New Branch
Creating a new branch should be as simple as creating a git branch from the master branch in the appropriate git repository. You would then copy the debian.master directory over to the appropriate debian.<branch> directory, and commit it. Next modify debian/rules to record the name of the branch and commit that. Finally create a debian.<branch>/changlog entry for the new branch using the appropriate ABI number (see above), and commit it.
git checkout -b mybranch master cp -rp debian.master debian.mybranch git add debian.mybranch git commit -s -m 'UBUNTU: create abstracted debian.mybranch' sed -i -e 's/debian.master/debian.mybranch/' debian/rules git add debian/rules git commit -s -m 'UBUNTU: select abstracted debian.mybranch' fakeroot debian/rules clean startnewrelease <edit debian.mybranch/changelog selecting appropriate ABI and upload #> git add debian.mybranch/changelog git commit -s -F debian/commit-temples/newrelease
Now you are ready to make any branch specific modifications, apply patches etc.
How to rebase to a newer version of master
In order to keep the branch specific changes on top of the topic branch, it is necessary to rebase on top of the master branch. As both branches use different debian specific directories this should be relatively simple.
In the checked out topic branch the following call will do the rebase
git rebase --onto <new base> <old base>
where new base is a tag or sha1 which should be made the new base for the branch patches and old base is the tag or sha1 which currently is the base.
- When the rebase is done, its is time to start a new release with the usual magic. Getting the new ABI files might be a bit of a problem (if getabis is not adapted). In a nutshell it is always a possibility to build the previous version(s) and copy the generated abi directories.
After committing the new release it is best to add the changes that came from the master into the changelog. There is a script called insert-ubuntu-changes in the debian.master/scripts/misc directory, which will help to do this. The only thing to note is that the help text uses start and and rather in a top down, than in a numeric sense. So in order to fill in the changes between a 15.50 and a 15.52 (given that is the old and new base) one would call
./debian.master/scripts/misc/insert-ubuntu-changes <branch changelog> 15.50 15.52
- Now either this change is committed and further branch specific patches might be added, or (if nothing helse is to be done) the changelog might be finalized by setting the release pocket and deleting the CHANGELOG: lines and committing the final changelog. When only doing a rebase, it actually can be done with the commit of the previous step.