Title: Debian Packaging Using Git Workshop Author: Per Andersson Given at: FSCONS, 2009 Copyright © 2009 Per Andersson This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . THANKS ------ Henner, corrections and improvements. USING GIT FOR DEBIAN PACKAGING ------------------------------ Using a version control system (VCS) for packaging work and maintanence pretty much have the same motivation as using one for software development. It is possible to restore your work, go back and forth in history, simpler collaboration. This document will give a short, short introduction to git and then race through a hands-on example of importing upstream sources, maintaining the debian work, building the package, tagging for release. The tools which will be used will be build-essential, debhelper, quilt, git, gitk, git-buildpackage, pristine-tar, and topgit aptitude install build-essential debhelper quilt git-core gitk git-build \ pristine-tar topgit Hey, Ho: Let's Go! CONTENTS -------- Git crash course Repository layout Import sources to Git Debian packaging (single binary) Building Upstream from Git Debian packaging (multi binary) Patches More topics References and more information GIT CRASH COURSE ---------------- Know Git already? Skip this section! Git is a VCS that tracks content, it does not track files. Git has Initialize a directory as a Git repository with git init . Add some content echo "hello" > hellofile Add that file and commit git add hellofile git commit # or git commit -m "initial commit." Git has a strict commit philosophy. You should only commit related changes in the same commit. Also the format of the Git commits are similar to e-mail: Subject of the commit message, keep it short. Body of the commit message: arbitrary length. The above shows the standard format for Git commit messages. Now, add some more content to the file and commit (all tracked files) echo "oh, hai!" >> hellofile git commit -a -m "added to hellofile." Check your history git log Create a topic branch, check it out to the working directory, add some content and commit it to the branch git branch bye git checkout bye echo "nice meeting you, see you!" > byefile git add byefile git commit -m "added byefile" Check which branches you have and check history git branch git log gitk Merge the changes in byebranch to master branch like so: git checkout master git merge bye You could also have done a git rebase, which, instead of merging two history points, will put your changes on top of the new changes from which you are rebasing. (Hence the name, re-base.) Check the history again and see what happened. git log gitk You may tag this commit in your history with git tag -a hello-tag The above command creates an unsigned tag named hello-tag with the comment that you entered when you were prompted. There, now you now the very, very basics of git. For online help use git --help where command is a git command: add, commit, log, rebase, merge, cherry-pick, etc. For further reading check out http://git-scm.com/documentation. REPOSITORY LAYOUT ----------------- The only requirement on repository layout for using git-buildpackage is that you have the debian work is done on a separate branch from the branch where the upstream sources are maintained. In shourt, you need at least, but are not restricted to, two branches: debian and upstream. The default names of these branches are master and upstream, respectively. The requirement exists because the necessity to build upstream tarballs and merge in new upstream versions. IMPORT SOURCES TO GIT --------------------- Download hello-0.2.1.tar.gz and import with git-import-orig. mkdir hello cd hello git init . git-import-orig path/to/hello-0.2.1.tar.gz We now have the upstream source in Git. DEBIAN PACKAGING (SINGLE BINARY) -------------------------------- Since this is more about Git than basic packaging I have a debian directory prepared for your needs. Normally you would do something like git checkout master dh_make ... ... git add . git commit -m "Initial debianization." Now, though, I have prepared a debian directory so the dh_make ... ... steps are already taken care of. So, now create a debian branch, put the debian directory in it (copy debian-example from the workshop directory) and commit it. git checkout master cp -a path/to/debian-example . git add debian git commit -m "Initial debianization." Add a changelog entry either by manually editing debian/changelog, using dch. If you want to automatically build a changelog from the Git commits you can do so by using git-dch. You now have a Debian package in Git!! (If you want to dig deeper in how a Debian package is actually built checkout the debian-basic-packaging-workshop or New Maintainers Guide.) BUILDING -------- Build the package, but, we don't want to sign the package with our GPG key. Hence, use another package builder (actually just some more options). git-buildpackage --git-builder="debuild -i.git -I.git -us -uc" Now tag the package build. With the tag you will get a pointer to your history which you can always go back to. git-buildpackage --git-tag-only The above steps could have been done in one go like so: git-buildpackage --git-builder="debuild -i.git -I.git -us -uc" \ --git-tag Now, you should have a package in the previous directory. You can check package contents by running debc from the package dir. UPSTREAM FROM GIT ----------------- Let's assume that the upstream author has code in a git repository. We clone this and call the branch upstream, since this is the branch where we will maintain the upstream sources. git remote add upstream git://git.debian.org/users/avtobiff-guest/hello.git Pull the master branch from the upstream Git repo to a new upstream-git branch git branch upstream-git git checkout upstream-git git pull upstream master You may get a conflict, current content in your working directory might not merge cleanly with the upstream content. You will have to solve this. First check which file it is (if you followed the instructions it is Makefile). Check the status and then edit that file git status vim Makefile (or whatever editor you love or hate) and look for lines starting with <<<<<<< HEAD ... ======= ... >>>>>>> 7b7ec335102dc7181fef0ce87428622481b61eaf This marks the conflict. The content in the current working directory is between HEAD and =======, while the new content (which is to be merged in) is below. Resolve the conflift by selecting the new content: Removing everything but the new content. When that is done, check the status and then commit the resolved conflict git status git commit -a -v The last commit command has the verbose flag on, this means that you will see what changes have been done when you are prompted for the commit message. Check the commit history with git log and gitk again if you wish. You have now successfully added source from an upstream Git repository to your package repository! DEBIAN PACKAGING (MULTI BINARY) ------------------------------- Now let's do some changes in the packaging. Merge with the new upstream release and create a multibinary package from this single source package. Are you following? OK, Good. Let's get to it! Update debian branch (remember, this is master by default) with sources from upstream-git. Let's try a rebase, which will put your changes on top of the changes from upstream Git source (in this case). git rebase upstream-git See, that went a lot smoother than the git merge we did before. Since the changes from which you are rebasing are just put on top the current content. Now, you have all the source from upstream-git in master. Let's do a multi binary package and then build it. We will in the debian directory do the following: move dirs and install to hello.dirs and hello.install, create new hithere.dirs and hithere.install, and, finally, add an entry in the control file. cd debian mv dirs hello.dirs mv install hello.install echo "usr/bin" > hithere.dirs echo "bin/hithere usr/bin" > hithere.install vim control When editing the control file create a similar entry as hello but name it hithere instead, update description as well. Now, update changelog and say it is a snapshot git-dch --snapshot --auto the auto flag avtomagically infers which commit messages should go in the new changelog, usually it takes since last build the snapshot Build the packages git-buildpackage --git-builder="debuild -i.git -I.git -us -uc" \ --git-ignore-new Since before you know that we use a custom builder command because we don't want to sign the resulting packages. The --git-ignore-new flag let's you build even with uncommitted changes in your working directory. Finally! You have updated the package source as well as the packaging and built new packages. STORING ORIG TARBALLS --------------------- It is possible to store the orig tarballs in Git, this will add just a small binary delta file to the repo. With this you don't need to store orig tarballs manually, you can keep everything in Git and build orig tarballs as needed. The tool for this functionality is named pristine-tar. Let's have a look. Import an orig tarball to Git pristine-tar -m "hello 0.1 orig tarball." commit ../hello-0.2.1.tar.gz This will commit the tarball delta file to the pristine-tar branch. Check it out and check the history. git checkout pristine-tar git log You will find the commit message you specified there. In order to build an orig tarball from the committed delta file in the repo, invoke pristine-tar checkout pristine_hello-0.2.1.tar.gz No need to keep those tarballs any more! PATCHES ------- Maintaining a Debian package often means receiving patches and keeping track of those. Sometimes you might also do your own patches (to make the package following Debian standards for instance). This can be done really smooth with topgit. With topgit all patches are kept in separate branches, and when you build you export all the topgit branches to a quilt series. When doing Debian packaging quilt should be configured to put patches in debian/patches. You also need a debian/patches/series file which contains which patches will be included and in what order. TopGit has default branches upstream - for upstream Git source fixes/* - patches fixing problems with upstream features/* - patches providing new features, targetted upstream master - main Debianization branch debian/* - Debian specific branches To create a new topgit branch (which will later be one patch in our series) tg create feature/ohhai Now you have a ohhai branch which git will checkout directly. TopGit will give an informative message on what happened and how to continue or abort. Let's continue by vim .topmsg vim src/hello.c git commit Firstly, you will create a description for this patch. Secondly, you will modify hello.c to print something more than "Hello!" (for instance). Thirdly, you commit the changes to the topgit branch. Now, we configure the package for building with TopGit. We will create a build branch and then do some configuration for building like so: git checkout master git branch build vim debian/control # add quilt to Build-Depencies git merge master # not needed now since we just branched, but later it is vim debian/rules # add include /usr/share/topgit/tg2quilt.mk before %: debian/rules tg-cleanexport # export the topgit branches to a quilt series git add debian/patches git commit -m "preparing $VERSION" git-buildpackage --git-builder="debuild -i.git -I.git -us -uc" \ --git-ignore-new Optionally tag with topgit-$VERSION, where $VERSION is some version number or string. Try installing the package now and see if your changes followed along. :-) MORE TOPICS ----------- Debian has a Git repository which can be used for packages, collaborative package management, and even private repos. Check it out at http://git.debian.org There is a special group on Alioth (a Debian project machine used for software and package development) which is called collab-maint. Members in this group have write/commit access to every package in the collab-maint directory. Collaboration made easy enough! The debian/control file have optional tags for pointing to the VCS and VCS browser. These tags are Vcs-Git and Vcs-Browser and can look something like this: Vcs-Git: git://git.debian.org/git/users/maint/hello.git Vcs-Browser: http://git.debian.org/?p=users/avtobiff-guest/hello.git For instance these tags are useful for the script debcheckout in the devscripts package. This script can do a checkout (clone) of the source package's vcs repository. debcheckout uboot-envtools REFERENCES AND MORE INFORMATION ------------------------------- http://debian.org/ git-buildpackage manual http://honk.sigxcpu.org/projects/git-buildpackage/manual-html/gbp.html http://wiki.debian.org/Alioth/Git http://repo.or.cz/w/topgit.git