How I Used Basic Debian Packaging with Git
I was recently looking for a way to support building a basic Debian package for email2pdf - a fairly simple Python program I maintain. In particular, I wanted to:
-
Keep the Debian build process simple - its packaging has always been a bit of a mystery to me.
-
Ensure that the git revision was in some way reflected in the Debian version number in a mostly monotonic way, which solely the git revision would not, since it’s merely a SHA1 hash.
The first bit turned out to be easier than I thought, since it turns out all you really need for a basic Debian package is a control
file that looks a bit like this (for the moment, this assumes a version number hardcoded in this file):
Package: my_package_name
Version: 1.0.0
Section: base
Priority: optional
Architecture: all
Depends: some, other, debian-packages
Recommends: yet-another-package
Maintainer: Andrew Ferrier <andrew.ferrier@example.com>
Description: Some short description
A much longer description that goes on for ages and ages and ages.
Once you have that, you put it in a directory tree called DEBIAN/
, together with any files you want to put in the package, and run dpkg-deb --build
at the root of it. For example:
mkdir -p DEBIAN/
mkdir -p DEBIAN/usr/bin
cp control/file/above DEBIAN/control
cp some/other/location/myprogram DEBIAN/usr/bin
dpkg-deb --build . .
(You can see a fuller example here in the builddeb_real
target here).
However, the second part - to determine an appropriate version string for the Debian package - was fiddlier. Eventually, I settled on a similar technique to the one described here.
However, rather than git describe --tags --long
, as recommended in the answer, I instead use git describe --dirty
. This has the following advantages:
-
It ensures that if a Debian package is produced during development, when the git tree might be dirty, that
-dirty
is appended to the package version to distinguish it from a non-dirty one. -
Not using
--tags
means that lightweight (non-annotated tags) are not used, which means we can use lightweight tags for miscellaneous purposes, and use annotated tags only for “released” versions of the software. In general, I only push annotated tags up to github.com repositories (this then integrates nicely with GitHub’s “Releases” concept). -
Not using
--long
means that ‘released’ versions (where the current commit exactly matches an annotated tag) have a clean and well-defined version string, like ‘0.9’. Commits that don’t have an associated annotated tag have a commit string like ‘0.9-12-gf385006’, so the second number (‘12’ in this case) is the number of commits since ‘0.9’, and hence monotonically increases. The short commit ID (‘gf385006’) makes it easier to locate the exact version from the Debian package in git.
Once we have a way to determine the version string (git describe --dirty
), now we need a way to get this into the Debian package control file. This can be done with a simple sed script:
sed 's/Version: .*/Version: $(GITDESCRIBE)/' debian/DEBIAN/control_template > debian/DEBIAN/control
control_template
is basically a template-ized version of control
, where the Version field contains a placeholder (see the real version from email2pdf as an example).
Once the above sed
command has been executed, the dpkg-deb --build
command can be executed as above.