Git in der Debian-Paketpflege

Die Pflege von Debian-Paketen kommt eigentlich auch vollkommen ohne eine Versionsverwaltung wie Git aus. Wenn Änderungen anstehen wie zum Beispiel ein Update auf ein neues Release mit einem neuen Ursprungs-Tarball (upstream tarball), oder wenn etwas zu verbessern oder ein Patch einzuspielen ist, dann kann ein Paketbetreuer zunächst einfach das entsprechende Quellpaket1 mit apt-get source aus dem offiziellen Paketarchiv auf seinen Arbeitsrechner herunter laden. Dort werden dann die gewünschten bzw. notwendigen Änderungen vorgenommen, dann die Debian-Version in debian/changelog um einen Zähler erhöht bzw. auf die Versionsnummer des neuen Releases gestellt, das Quellpaket und das oder die aus dem Quellpaket baubaren Binärpakete neu “gebaut”. Dann wird ganze Sammlung mittels der dabei generierten .changes-Datei von einem offiziellen Paketbetreuer (Debian Maintainer, DM) oder einem Debian-Entwickler (Debian Developer, DD) mit ihren Uploading-Rechten wieder ins Archiv eingespielt, wobei die alte Version damit ersetzt wird2. Die Änderungen an dem Debian-Paket, also an den Steuerdateien in debian/, müssen dabei ausführlich im Protokoll debian/changelog festgehalten werden, während die Veränderungen an der Ursprungs-Software aus der mit ausgelieferten CHANGES-Datei ersichtlich sind – wenn die Entwickler nicht zu faul sind und überhaupt gar keine pflegen. So weit, so gut.

Versionsverwaltungen bzw. Versionskontrollsysteme (VCS) für Paketquellen einzusetzen kommt bei der kollaborativen Paketpflege ins Spiel, der bei diesem gemeinschaftlich entwickeltem Betriebssystem eine große Rolle zukommt. Viele Pakete haben mehr als einen festen Paketbetreuer, aber ein erheblicher Teil der einzelnen Softwarepakete im Debian-Paketarchiv werden innerhalb von festen Gruppen betreut. In diesem Gruppen finden sich thematisch zusammengefasste Pakete, so sind zum Beispiel viele Python-Applikationen unter dem Schirm bzw. in der Klammer des Python Applikation Packaging Team (PAPT), Python-Bibliotheken oftmals beim Debian Python Modules Team (DPMT), naturwissenschaftliche Software bei Debian Science, Google Go-Pakete in der pkg-go-Gruppe, usw. Ein Sinn dieser Gruppen ist es zum Beispiel einheitliche Standards und Konventionen für unter der Gruppe stehenden Pakete zu vereinbaren (die eigene Policy für Python-Pakete kommt von der Gruppe), und Gruppenmitglieder können auch mal einspringen, wenn der feste Paketbetreuer eine Zeit lang – etwa aus Zeitknappheit – nichts für Debian machen kann. Diesen Gruppen nutzen verteilte (wie Git) und strikt zentralisierte Versionskontrollsysteme (wie Subversion) für den Austausch von Änderungen an den Quellpaketen: Gruppenmitglieder checken einzelne Änderungen in einem eigenen zentralen Gruppen-Repositorium ein, dort können dann andere Mitglieder diese herunterladen, begutachten, weiter entwickeln und wieder zurück verteilen bis eine neue Paketversion so weit ist, ins Archiv hochgeladen zu werden. Für die kollaborative Paketpflege unter Paketbetreuern außerhalb von einer bestimmten Gruppe können auch Repositorien im -Bereich auf dem Alioth-Server von Debian angelegt werden, darüber hinaus haben die einzelnen Gruppen ihre eigenen Bereiche für zentrale Repositorien, die nur Gruppenmitgliedern nach Anmeldung mit Schreibrechten zugänglich sind.

Die Methode, einzelne Änderungen an Debian-Paketquellen über ein Versionskontrollsystem zu verteilen bevor ein Paket in Archiv geladen wird kommt zum Beispiel auch beim Sponsoring zum tragen. Das ist der Vorgang bei dem sich ein DM- bzw. DD-Anwärter noch ohne Upload-Rechte für seine neuen Pakete zunächst einen Developer suchen muss um seine Arbeit überprüfen und ins Archiv einspielen zu lassen – die Gruppen spielen dabei wieder eine wichtige Rolle. Für den Sponsoren, der angehalten ist diese Pakete minutiös zu untersuchen und den Sponsoree auf etwaige Fehler und “best practice”-Mängel hinzuweisen ist es wesentlich angenehmer, wenn er einzelne Änderungs-Sets isoliert als separate VCS-Commits begutachten kann, als dabei allein von debian/changelog ausgehen zu müssen (wo die Änderungen lediglich beschrieben sind). VCS-Systeme eignen sich hervorragend für ein Hin-und-her: ob angemerkte Verbesserungshinweise auch richtig umgesetzt worden sind lässt sich dann genauso gut an der Commit-Historie nachverfolgen, wenn der Sponsor dann sein lokales Repositorium wieder auf den neuesten Stand gebracht hat. Und dabei können dann immer einzelne Commits gezielt thematisiert werden3.

Subversion (SVN) gilt gemeinhin als nicht so weit entwickelt wie Git4, trotzdem haben es einige Debian-Gruppen nicht besonders eilig damit, ihre Gruppen-Repositorien auf Git zu migrieren (SVN-Repositorien können mit einem Skript migriert werden, wobei die Commit-Historie erhalten werden kann). Git-Kritiker stören sich oftmals an der Staging-Area von Git, bei der ein Checkin bzw. Commit grundsätzlich nur möglich ist für veränderte Dateien, die mit git add zunächst erst wieder getrackt werden, obwohl das wie viele andere Neuerungen für den eigenen Workflow mehr Möglichkeiten bietet. Subversion erfüllt seinen Zweck für den kollaborativen Debian-Paketbau bereits vorzüglich, ein Repositorium enthält den trunk, mit dem der Debian-Patch verteilt wird, und ein Archiv-Verzeichnis tags, in welchem die bisher hochgeladenen Paketversionen zu finden sind. Man kann sich zum Beispiel mit svn checkout svn://svn.debian.org/svn/python-apps/packages ganz einfach alle Pakete der PAPT-Gruppe herunter laden, während sich bestimmte Pakete unter python-apps/packages/foo bzw. foo/trunk finden lassen (Schreibrechte haben aber wie gesagt nur Gruppenmitglieder). Klar: hat ein Partner oder irgendwo ein Gruppenmitglied Änderungen an der Paketquelle vorgenommen, sind zum Beispiel mal gruppenweite Standards über alle Pakete hinweg aktualisiert worden, kann man sich diese ganz einfach mit svn update auf den eigenen Rechner bekommen. Das Paket kann jederzeit aus dem lokalen Repositorium neu gebaut werden und dafür gibt es den Builder , der als ein Wrapper dafür sorgt, dass die Standard-Builder wie debuild mit der speziellen Umgebung zurechtkommen. Wenn ein neues Paket fertig und hochgeladen ist taggt der Uploader die aktuelle Revision einfach mit svn-buildpackage --svn-tag-only oder debcommit -r, und der SVN-Tag mit der aktuellen Paketversion wird automatisch in foo/tags angelegt. Klein, stark, läuft!

Es gibt dabei, wie SVN im Debian-Paketbau verwendet wird, allerdings einen ganz entscheidenden Nachteil: der Upstream-Code bzw. Tarball wird hierbei nicht mit verteilt, sondern der Trunk enthält lediglich das Verzeichnis debian/. Deshalb ist man in Gruppen mit Subversion immer besonders darauf angewiesen, dass debian/watch im Zusammenspiel mit uscan einwandfrei funktioniert, und mit diesem Befehl der für das Debian-Paket vorgesehene Upstream-Tarball – mit dem das Paket auch einwandfrei baut – jederzeit reproduzierbar automatisch bezogen werden kann5. Diese Tatsache zieht auch Einschränkungen für den Workflow nach sich, denn schreibt oder passt der Maintainer zum Beispiel einen Patch an, so muss er dafür den Upstream-Tarball zunächst immer irgendwo in einem temporären Verzeichnis manuell auspacken und das aktuelle Debian-Verzeichnis dort rein kopieren (es mag irgendwo ein Werkzeug geben, welches das vereinfacht), um eine Arbeitsumgebung zu bekommen die prinzipiell dem Ergebnis von einem apt-get source entspricht, und in der auch das Patching-Werkzeug Quilt funktioniert. Und die bearbeiteten Dateien müssen am Ende für einen Commit wieder in den Trunk zurück kopiert werden – das ist nicht sehr komfortabel und vor allem beim manuellen Rumkopieren wird ja auch so selten etwas übersehen. Der fortschrittliche Branching-and-Merging-Mechanismus von Git hat generell einige Vorteile für einen eigenen experimentellen Workflow, dieses “power feature” wird bei Debian aber darüber hinaus auch eingesetzt, um diese Beschränkungen beim der gemeinschaftlichen Paketentwicklung mit Subversion zu überwinden.

Bei den Debian-Gruppen, die Git als Versionskontrolle und Verteilsystem benutzen bekommt man das ausgepackte Quellverzeichnis inklusive dem Debian-Patch auf seinen Rechner, wenn man das öffentliche Repositorium kopiert, und die Tarbälle sind auch gleich mit dabei. Daraus kann das Paket dann sofort mit dem Werkzeug gebaut werden6 – man bekommt damit also sozusagen anstatt einer Tüte Gewürzmischung wie bei Subversion direkt ein Fertiggericht für die Mikrowelle7. Ein Repositorium-Zuschnitt mit debian/ in einem separaten Git-Zweig gab es vor einiger Zeit immer mal wieder8, mittlerweile finden sich gemeinhin allerdings der ausgepackte Tarball mit debian/ im Zweig master, der ausgepackt Tarball ohne Debian-Patch im Zweig upstream, und der Tarball im Zweig pristine-tar. Alle Zweige sind nicht unmittelbar verfügbar, wenn man mit git clone arbeitet um sich ein Repositorium zu beschaffen, aber Git-buildpackge bietet hierfür den eigenen Befehl gbp clone, der zum Beispiel für anonyme Checkouts (ohne Schreibrechte zu bekommen) von Collab-Maint-Repos angewendet werden kann: gbp clone git://anonscm.debian.org/collab-maint/foo.git. Der Zweig pristine-tar wird dabei als Tarball-Archiv verwendet, und mit dem gleichnamigen Werkzeug können mit pristine-tar checkout beliebige ältere Fassungen aus dem Repositorium gewonnen werden, die aus dem offiziellen Debian-Archiv eventuell schon längst verschwunden sind. So können auch ältere Pakete reproduziert werden, wenn man den Git-Header auf einen älteren Tag zurücksetzt, zu dem sich ein entsprechender Tarball in pristine-tar finden lässt, und dann mit Sbuild gegen ältere Debian-Zweige wie Oldstable baut.

In master läßt sich dann bequem an dem Quellpaket arbeiten: der Upstream-Code liegt unmittelbar vor, Patching mit Quilt (push and pull) funktioniert einwandfrei (Achtung: keine angewendeten Patches einchecken!), und ein experimenteller Workflow wird voll unterstützt bei dem “Baustellen” in rein lokal gepflegten oder nur mit bestimmten Partnern ausgetauschten Separatzweigen möglich sind. Änderungen auch über viele Dateien hinweg können mit einem einzigen Befehl komplett auch wieder verworfen werden, wenn man nur mal was ausprobieren wollte. Git-Ninjas haben lokal bei sich das Upstream-Repositorium der Entwickler in einem eigenen Zweig und beziehen dann Patches via der “cherry picking”-Methode direkt daraus, ohne irgendwelchen Code ausschneiden und einbauen zu müssen, und sogar ohne irgendwelche Dateien zu kopieren9. Die volle Bandbreite der Funktionalität von Git steht dabei für die Debian-Paketpflege zur Verfügung10, und es gibt eine ganze Reihe von nützlichen Helfern. So kann man zum Beispiel mit gbp dch die Einträge in debian/changelog automatisch aus den Commit-Messages erzeugen, wobei auch – sehr edel! – die Commit-IDs dort aufgenommen werden können. Das erspart eventuell noch extra herausarbeiten zu müssen welcher Commit mit einer bestimmten Infozeile dort gemeint ist, was die ganze Sache übersichtlicher macht.

Aber die “Giterei” in der Debian-Paketpflege wird auch noch weiter getrieben. Das Debian Enhancement Proposal Nr.14 (DEP-1411) schlägt einen Standard für Git-Repositorien von Debian-Quellpaketen vor, der auch Zweige von “Nebenveröffentlichungen” von Paketen (any release that is not one of the usual development releases) wie zum Beispiel debian/jessie und debian/wheezy beinhaltet. Damit hat man wirklich alles, was von einem Paket irgendwo in Debian ist wie etwa Security-Updates im Stable-Archivzweig auch im Git-Repositorium verfügbar, und es gibt keine “wilden” Paketversionen mehr (wie etwa “9.99-1+7u1”), die sich dort nicht finden lassen sondern für die Weiterentwicklung noch anderweitig beschafft werden müssen, weil sie von der Hauptentwicklungslinie abgewichen sind bzw. abweichen mussten. Das meint nicht nur Einträge im Changelog, die eventuell einfach irgendwann nachgetragen werden können, sondern immer gerade eben auch die Quellen eines Debian-Paketes. Der Vorschlag umfasst sogar auch andere Distributionen wie die Entwicklung Ubuntu, für das nach DEP-14 auch ein eigener Zweig angelegt werden kann (Stichwort: “vendor”). Die in dem Vorschlagspapier beschriebenen Konventionen für die Tags debian/* und upstream/* werden bereits breitflächig verwendet. Der Befehl debcommit -r kann auch auf unter der Obhut von Git-buildpackage stehende Repositorien angewendet werden, das Werkzeug taggt dann den aktuellen Commit bzw. den Git-Header mit der aktuellen Debian-Paketversion, die aus dem aktuellen Paragraph in deb/changelog gewonnen wird. Mit git push --tags aktualisiert der Paket-Uploader dann die Tags im öffentlichen Git-Repositorium seiner Gruppe.

Jenseits von Git-buildpackage gibt es darüber hinaus Repo-Manager, die auch noch die Kontrolle über die Patches übernehmen (Stichwort: “patch regime”). Dazu gehört zum Beispiel , das zur Zeit zum Beispiel von der DPMT-Gruppe verwendet wird, Git-buildpackage kommt mit entsprechenden Werkzeuge, und es gibt eine Reihe von anderen Lösungen in dieser Art. Es fließen nicht selten Patches von Debian zurück zu den Softwareentwicklern, die zum Beispiel nicht immer alle die Architekturen zum Testen zu Verfügung haben, für die Debian-Paketen entwickelt werden und die im Baunetzwerk Buildd betrieben werden. Die Patches finden sich dann oftmals bereits in neuen Paketversionen im Testing-Zweig, sind eventuell bereits zu Ubuntu und in andere Derivate rüber gelaufen, wenn sie dann auch irgendwann in einem neuen Upstream-Release erscheinen. Soll dieser neue Release dann in das Debian-Paket eingepflegt werden gibt es eine Fehlermeldung, dass der entsprechende Debian-Patch nicht angewendet werden kann, weil der Code sich an der entsprechenden Stelle verändert hat: die Änderungen befinden sich bereits darin. Dieser Patch kann dann also als “applied upstream” ganz verworfen werden. Git-dpm und vergleichbare Werkzeuge arbeiten mit einem eigenen Zweig für die Patches12, der bei einem neu eingespielten Upstream-Tarball automatisch abgeglichen wird. Das hat den Effekt, dass überflüssige Patches bei diesem Vorgang automatisch rausgeschmissen werden, während Unstimmigkeiten als Merge-Konflikte abgearbeitet werden können. Darum muss man sich also auch nicht mehr kümmern, das ist schon nicht schlecht! Quilt lässt sich bei Git-dpm gar nicht mehr anwenden, denn der Master-Zweig enthält im Gegensatz zu Git-buildpackage immer den Upstream-Code mit bereits angewendeten Patches – der veröffentlichte Code findet sich ja bei Bedarf im Upstream-Zweig. Sollen Patches verändert bzw. angepasst werden dann geschieht das bei dieser Werkzeugklasse nicht durch einfaches (aber oftmals nerviges) Umschreiben der Dateien in debian/patches, sondern es wird mit git-dpm checkout-patched auf den Patch-Zweig gewechselt und der entsprechende Commit dort wird mit der Rebase-Funktion von Git mit git commit --amend nachträglich verändert. Dieses Verfahren, bei dem das gesamte Patching zusätzlich vollständig in den Git-Workflow integriert wird gilt aber nicht zu unrecht als recht unflexibel und es gibt eine ganze Reihe von Kritikpunkten an dieser Lösung – so kreiert git-dpm zum Beispiel eigene Patch-Header unter Einbeziehung der Commit-Message, die nicht unbedingt konform mit den DEP-3-Richtlinien (Patch Tagging Guidelines) sind. Ich denke, dass man hier teilweise schon im reinen Fetisch-Bereich angelangt ist, und das man vorsichtig sein muss mit der verpflichtenden Benutzung dieser komplizierten Werkzeuge die sowieso schon sehr steile Lernkurve für Einsteiger beim Debian-Paketbau nicht eventuell um ein paar entscheidende Grade zu schwierig zu machen.

Bei “Git in der Debian-Paketpflege” handelt es sich also um ein recht breit gefächertes Spezialthema, dem man als Administrator von Linux- bzw. Debian-Systemen bestimmt, spätestens aber wenn man zur offiziellen Paketpflege beitragen möchte mit Sicherheit stellen muss. Während Subversion immer mehr an Bedeutung verliert spielt Git eine immer größere Rolle in der kollaborativen Paketpflege, wo Git-buildpackage und noch weiter entwickelte Lösungen wie Git-dpm auf breiter Front eingesetzt werden. Aber auch andere Git-basierte Werkzeuge wie Dgit kommen zum tragen, das sich sehr gut für die gelegentliche Paketarbeit auch außerhalb von Debian-Gruppen eignet13.


  1. Bestehend aus dem Upstream-Tarball im Archiv (etwa endend auf *.orig.tar.gz), dem sogenannten “Debian-Patch” mit den Steuerdateien im Verzeichnis debian/ (*.debian.tar.gz), und einem Register (*.dsc), der das Quellpaket zusammenhält. Siehe: Martin Loschwitz: . In: Linux-Magazin 06/2011, S. 32-35 [return]
  2. Heike Jurzik: Sauber eingepackt – Debian-Pakete bauen. In: IT-Administrator 05/2016, S. 96-101 [return]
  3. Manche Pakete finden sich sogar bei Collab-Maint, auch wenn es nur einen einzigen festen Paketbetreuer gibt; für Leute, welche die Entwicklung eines Paketes verfolgen wie zum Beispiel Downstream-Entwickler (etwa für Ubuntu) hat das genau denselben Vorteil, einzelne Commits inkl. der eigentlichen Änderungen auf einen Blick verfügbar zu haben. [return]
  4. Ausführlich runtergemacht in: . Vortrag beim Google Tech Talk in 2007 [return]
  5. Der Tarball im Debian-Archiv weicht nicht selten ein wenig von dem von den Entwicklern veröffentlichten Release-Tarball ab. So sind manchmal Bestandteile, die nicht die DFSG-Vorgaben (Debian Free Software Guidelines) erfüllen entfernt worden, oder die sogenannten “convenience packages” (für den Bau benötigte Software, die durch andere Pakete im Archiv bereits zur Verfügung steht) werden beim Herunterladen mit uscan aus dem Tarball herausgelöscht (“gestrippt”). [return]
  6. Guido Günther: Building packages with Git-buildpackage. Offizielle Anleitung, zuletzt besucht am 28.1.2017 [return]
  7. Guido Günther: What Git-buildpackage (hopefully) can do for you – maintaining Debian packages in Git. Präsentation auf der DebConf 10 [return]
  8. David Bremner: Debian packaging wit Git – workflows and tools. Präsentation auf der DebConf 11 (Diskussion darüber ab 17:40) [return]
  9. . Technical Note auf der Seite von Russ Allbery, zuletzt besucht am 28.1.2017 [return]
  10. Git-buildpackage skillshare. BOF-Panel von Daniel Gillmor auf der Debconf 15 [return]
  11. Raphaël Hertzog: Debian Enhancement Proposal 14: Recommended layout for Git packaging directories. DRAFT. Fassung vom 9.11.2016 [return]
  12. Bernhard R. Link: Git is the better Quilt – Managing Debian packages in Git with Git-dpm. Präsentation auf der DebConf 13 [return]
  13. Daniel Stender: . In: Linux-Magazin 02/2016, S. 50-54 [return]