Branches to patches

Teemu Ikonen tpikonen at gmail.com
Thu Apr 3 08:58:47 UTC 2008


Stefano Zacchiroli wrote:
> However in general it is not possible to
> require that all patches apply properly to pristine source. In some
> (rare fortunately) cases two patches will conflict with each other on
> the pristine source and you need to make one depend on the other or the
> other way round.

I recently started to use git in some of my Debian packages and
thought about this issue a bit.

When maintaining packages with a version control system, having each
"feature" in a separate branch (branched from the upstream version) is
clearly superior to a stack of patches. You retain separate history
for every branch and can easily develop features independently,
without having to worry about conflicts.

When making a release, all the feature branches are merged to an
integration branch. The end product of the packaging should be this
well-integrated source, but it would be nice to also have the separate
features easily extractable from the source package as well. Usually
this is achieved by having the package contain a quilt patch series or
similar. Converting a set of branches to a stack of patches is easy if
there are no conflicts, but of course this is not always the case.

A brute force method of making a patch stack which has all the feature
patches applicable to pristine source and ends up with the complete
integrated source would be to apply feature patch #1, revert it with
the same patch reversed, apply feature patch #2, revert it, etc. and
finally to apply a patch containing all the features, plus additional
integration changes. The patch stack would then contain every change
three times.

However, conflicts between feature patches are usually small (and if
they're not, maybe the features should be combined anyway), so
reverting only those hunks in the previously applied patches which
conflict with the new patch would not result in large reverting
patches. If the patches do not conflict the revert patches would be
empty. The final integration patch can be formed by diffing the
upstream source with all the feature patches applied to the
integration branch stored in the VCS.

The end result is a patch series containing the separate feature
patches, which are all guaranteed to apply to the pristine source,
some small revert patches applied between them and a final patch
containing real resolutions to the conflicts between the feature
patches and additional integration changes.

I've made a python program (actually a rather thin wrapper around git
and various tools from patchutils) which makes this transformation
from an upstream branch, a set of feature branches and an integration
branch stored in git to a series of patch files. It's called
git-genpatches and is attached to this mail. The revert patches
between feature patches are made by python program minrevert (also
attached) which takes patches A and B and outputs a patch reverting
those hunks in patch A which overlap with hunks in patch B.

Integrating git-genpatches to debian/rules is straightforward. Below
are excerpts from the rules file of an unreleased package of mine. A
convenience target genpatches recreates patches under debian/patches
(which should be ignored by git) by applying changes in branches
matching the glob 'patches/*' to a temporary branch starting from
branch 'upstream' and ending with an exact copy of the integration
branch called 'debian'. Directories 'contrib' and 'debian' are ignored
when generating the patches:

genpatches:
       dh_testdir
       -rm -rf debian/patches
       mkdir -p debian/patches
       git-genpatches -s -p debian/patches -x '*/contrib/*' -x '*/debian/*' \
       -b upstream -i debian 'patches/*'

Since wig and pen is not implemented in dpkg yet, there needs to be
patch and unpatch targets calling quilt (or dpatch). When building in
a git working tree, it is assumed that it already contains all the
changes and the patches do not need to be applied:

patch: stamps/patch
stamps/patch:
       dh_testdir
       # Don't patch when in git tree
       [ -d .git ] || quilt push -a
       mkdir -p stamps
       touch $@

unpatch:
       dh_testdir
       -[ -d .git ] || quilt pop -a
       -rm stamps/patch

The programs are still somewhat of a proof of concept quality and
probably contain bugs, but I think they are useful in combining the
good sides of preparing source packages with branches in version
control and separating features in the final source package with a
patch series.

Best,

Teemu
-------------- next part --------------
A non-text attachment was scrubbed...
Name: git-genpatches
Type: application/octet-stream
Size: 6364 bytes
Desc: not available
Url : http://lists.alioth.debian.org/pipermail/vcs-pkg-discuss/attachments/20080403/bab4581b/attachment.obj 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: minrevert
Type: application/octet-stream
Size: 3495 bytes
Desc: not available
Url : http://lists.alioth.debian.org/pipermail/vcs-pkg-discuss/attachments/20080403/bab4581b/attachment-0001.obj 


More information about the vcs-pkg-discuss mailing list