| < Debian Packaging Tools | Russ Allbery > Technical Notes > Debian | Packaging Scripts for Debian > |
Introduction
Getting Started with Git
Working with Someone Else's Package
Publishing a Repository
Debian Packaging
Debian and Upstream Combined
Converting to Git
This page duplicates a lot of other information out on the web, and I don't necessarily recommend it as a starting point. I maintain it largely for my own purposes, to remember the techniques that I've found that worked. However, it may be of interest if you are looking at moving from Subversion plus quilt to Git for maintaining Debian packages, since that's what I'm evaluating.
The Git version control system (VCS) is a distributed VCS originally written by Linus Torvalds for Linux kernel development after moving away from BitKeeper. "Distributed" means that it has strong support for branching, merging, and parallel lines of development and is designed for multiple people working on the same software in parallel and merging in complex ways between their separate trees.
Of the distributed version control systems, Git has the strongest following among free software developers at the moment and is increasingly popular in Debian. Before looking at Git, I'd used Arch (bazaar and tla), bazaar-ng (bzr), and svk before, but only briefly and mostly in the same way that I'd use Subversion. So I came to Git familiar with some of the distributed VCS basics but without a lot of practical experience.
When you have the opportunity, you should read the entire Git user manual.
First, install the git package. If you're going to do Debian
packaging, also install git-buildpackage and pristine-tar.
You probably want the current unstable (or at least testing) versions of
all of those; stable is rather old. You probably also want gitk
(or one of the other Git repository browsers like giggle or
tgit. I personally prefer gitk.
You should also tell Git your name and e-mail address with:
git config --global user.name '<name>'
git config --global user.email '<email>'
You can set these per-repository as well, once you have a repository, by
running the command within that repository and omitting the
--global flag.
The basic Git commands are very similar to the commands for Subversion;
git log and git status do what you'd expect, for example.
However, one thing to be aware of is the index, which you can think of as
your pending next commit. By default, git commit only commits
changes that have been added to the index with git add (unlike with
other revision control systems where the add command is only used
to add entirely new files). You can run git commit -a to add all
modifications to the index and then commit them in one step, but it's
worth getting in the habit of doing explicit git add commands to
cut down on committing unintended changes.
To revert changes in your working copy, use git reset --hard. This
is equivalent to svn revert. (git revert does something
completely different, namely revert a specific change.)
git branch will show you a list of branches. git tag will
show you a list of tags. To switch between branches (something that you
do a lot of in Git), use git checkout <branch>. To create a new
branch based on an existing one, use:
git checkout -b <new-branch> <old-branch>
To tag the current branch with some tag name, use git tag <tag>.
One neat Git trick that isn't present in other revision control systems is
that if you flub a commit, you can fix it after the fact. Add whatever
additional modifications you need to make (if any) with git add and
then run git commit --amend. You'll get the opportunity to re-edit
the commit message as well. Note that you should not do this if you've
already run git push.
My first experience with Git was working with logcheck and submitting patches back, following the guide available on logcheck.org. Briefly, the steps to get started with someone else's repository are:
git clone <url> <directory>
cd <directory>
where <url> is the upstream Git repository, and <directory> is your working directory. This gives you a checked out working copy. Before doing any work, refresh from upstream and then create a local branch for that work:
git pull
git checkout -b <branch>
Now, you can work in that branch and make commits as you go, using either
git add and git commit or just git commit -a.
The later step of sending patches is simplified if you keep to one commit per separate patch, which may or may not be realistic depending on what sort of things you're working on. If you can't do that, don't worry a lot about it.
If upstream does additional work before you're ready to submit patches, you resynchronize with upstream by doing:
git checkout master
git pull
git checkout <branch>
git rebase master
git rebase essentially reworks your branch so that it looks as if
you'd started with the current upstream master branch instead of an older
version, thus eliminating merge noise. You should not use git
rebase on public branches that you're publishing, but it's great for this
sort of private working branch where you don't want to carry around the
merges from new upstream work as additional commits in your branch. If
for some reason you have published this branch, use git merge
instead.
When you're ready to submit the patches upstream, if each commit is a separate upstream patch, you can just do:
git format-patch -M -s master
which will write the patches into the current directory for you to look
over. You can submit them via whatever means upstream prefers. Often
git send-mail is useful (try it with --to pointing to your
own address first).
If you need to collapse your commits down further to generate patches, you
can either do a git merge --squash to collapse all your changes
into a single commit or do more complicated things with git rebase
-i or git cherry-pick -n. You'll want to do this on a separate
working branch. One work-flow option is to do all of your changes in a
sloppy branch with repeated commits, then use one of those techniques to
pull them onto a real feature branch and delete the sloppy branch.
To get a list of current branches, run git branch. You can delete
branches with git branch -d (safe — only deletes
merged branches) or git branch -D (will lose any work on that
branch that hasn't been merged) so you don't have to carry your
experiments around forever.
To publish your Git repository, just follow the instructions in the Git manual. I usually use HTTP since it's nice and easy, but the native Git protocol offers significant improvements. The Git server is purely anonymous and doesn't allow writes, so you don't have to worry much about running it for repositories that are public anyway.
To set up the remote name, rather than using the instructions given in the manual, try:
git remote add --mirror public <url>
I prefer mirror, since then all new branches are automatically pushed to
the public repository and it's treated by Git as a copy of your local
repository rather than a possibly independent repository with which you're
merging. However, this only works if it's just for your personal use; if
you're sharing with others, such as for Debian packaging, you don't want
to use --mirror.
If you're setting up Git for Debian packaging, you probably want to put your repository on git.debian.org instead. This is done via Alioth. You can use the collab-maint project for individual packages or request a new group for a larger set of packages that needs its own infrastructure. Once you've decided, one way or the other, follow the instructions and the repository will show up on the web browser in six hours or so.
The Alioth instructions create a remote name of alioth. If I'm
primarily going to be synchronizing with other work on Alioth, I prefer to
use a remote name of origin since other Git commands use that as a
default. When I create my own public repository, I use a remote name of
public. If you're using a shared repository that's already set up,
you can use git clone as described above, which will set up your
repository with a remote name of origin.
After making changes that you want to publish, run:
git push public <branch>
or alioth or origin instead of public as needed.
<branch> is the name of the branch whose details you want to publish. You
can use --all instead to push all branches. Once you do this, you
shouldn't amend or rebase commits, so I usually only do this after I'm
done with a chunk of work and have tested it. If you've cloned from a
remote repository, or branched from a remote branch, that remote and
branch will be the default push target if you just run git push.
Pushing branches will not push tags. To push tags to a remote repository,
you have to explicitly pass --tags to the git push command
and you can't push branches and tags at the same time for some reason.
One special note: if you delete a branch locally, that doesn't delete the
branch on the remote repository. If you want to do that, you have to do
it as as special git push command with a weird syntax:
git push origin :<branch>
where origin is the name of your remote. The colon there is a
literal colon. This will delete the branch named <branch> in the remote
repository. Be warned that it will be difficult to recover that branch if
you make a mistake and don't realize it immediately.
Also, branches deleted from remote repositories can still linger as tracking branches in your local repository. You can clean them up with:
git remote prune origin
None of this is necessary if you use a mirror remote, since it will always force the remote repository to look exactly like your local repository and won't retain tracking branches. But mirror remotes only work when you're publishing your own personal repository and no one else will be pushing to the same repository.
First, configure git-buildpackage to use pristine-tar. pristine-tar
allows you to store the upstream tarball directly in Git in an extremely
space-efficient way, which means that the Git repository is then all you
need to build a Debian package. You don't have to separately keep track
of the upstream tarball. I use the following ~/.gbp.conf:
[DEFAULT]
builder = git-pbuilder
cleaner = fakeroot debian/rules clean
pristine-tar = True
[git-buildpackage]
export-dir = ../build-area/
tarball-dir = ../tarballs/
[git-import-orig]
dch = False
This uses the svn-buildpackage convention of a directory full of
directories for each Debian package and a directory named
build-area that holds the most recent builds. If you use
pristine-tar, the tarball-dir key isn't used. The git-pbuilder
script is the required wrapper to get git-buildpackage to use pbuilder
(via cowbuilder). It comes with current versions of git-buildpackage, or
you can get it from my miscellaneous
scripts page.
For Debian packages, I use a layout similar to the git-buildpackage
recommendation but with an (almost) pure feature branch setup. This means
that every feature or bug that could be pushed upstream is developed on a
separate branch for that particular feature or bug, and the main branch
(by Git convention master) is a combination of a merge branch and
the branch for Debian-specific changes like the debian directory.
The upstream source (after any necessary repackaging to remove
non-DFSG-free files) is imported into the upstream branch and that
branch, along with the others, is merged into the master branch.
All Debian packaging and any Debian-specific upstream modifications that
aren't large enough to warrant a separate development branch and which
can't be usefully sent upstream go directly on the master branch.
This includes the entire debian/* directory, upstream modifications
to remove references to non-DFSG-free material, minor path changes, and
the like. (I previously tried making master a merge-only branch
and developed Debian-specific changes on a separate debian branch
that I merged into master like every other feature branch, but this
ended up being too confusing without much practical purpose.)
Bug fixes to the upstream source go on branches named bug/<name>
where <name> is some short term for the bug being fixed. New
upstream features go on branches named feature/<name>. These
patches should be sent upstream.
It's worth frequently doing a git diff between master and
the upstream branch to be sure you know what changes you've made.
Piping it through filterdiff -x '*/debian/*' will show you only the
changes to the upstream sources. (filterdiff is an extremely
useful program from the patchutils package.)
git-buildpackage can do most of the work of managing the upstream
branch. To start a new Git repository from an existing package without
caring about the history, just run:
git-import-dsc /path/to/dsc
You'll get a subdirectory of your current directory named after the
package and containing an initialized Git repository with an
upstream and master branch and with (if you use the above
configuration) a pristine-tar branch that holds the metadata used
by pristine-tar. git-import-dsc will also create an upstream/* tag
for the upstream version and a debian/* tag for the Debian version
of the package.
If you're instead starting from scratch with packaging a new package,
create an empty directory, cd into it, and run git init to create
an empty repository. With older versions of git-buildpackage, such as the
version in squeeze, you may have also to pre-create an empty upstream
branch with:
git init
git commit --allow-empty -m 'Initial repository'
git branch upstream
Then rename the upstream tarball to <package>_<version>.orig.tar.gz (don't repack it unless you have to, just rename it) and run:
git-import-orig /path/to/upstream/tarball
This will create an upstream branch and load the upstream source
and then merge that onto your master branch.
If you're importing an existing package that has upstream patches that
should go on bug and feature branches mingled with Debian changes, you may
need to shuffle things around a bit. I generally do that by saving off
the upstream patches that should get their own branches, reverting all
those changes on the master, creating new bug or feature branches
based off upstream (not master), reapplying the relevant
patch and committing it, and then merging that branch back into
master.
Further Debian-specific work can then be done on the master branch
by switching to it with git checkout, modifying and committing
things.
New bug or feature branches should be based on upstream but are
otherwise handled in the same way. When ready for a release (or even a
test build), merge everything into master, switch to that branch if
you aren't already, and then run git-buildpackage. If all goes
well, the built packages will be in ../build-area/.
After uploading a release, tag the master branch with the release
version. I use an annotated tag with the contents of the *.changes file
as the tag message, an idea that I got from Sam Hartman. To avoid having
multiple GPG signatures on the tag, I strip the signature off the
*.changes file and then do:
git checkout master
git tag -s debian/<version>
In the editor, I put "Debian release <version>" as the first line, add a
blank line, and then include the ../build-area/*.changes file.
(The wildcard only works if you only have one built package in your
../build-area/ directory.) Don't forget to push to a remote
repository, following the instructions above, if you're using one.
When there's a new upstream release, first checkout the master
branch and then run:
git-import-orig /path/to/upstream/tarball
You shouldn't have to rename the upstream tarball first to
<package>_<version>.orig.tar.gz; git-import-orig will take care of that
for you. git-import-orig will import and tag upstream and handle
the pristine-tar work, and will then try to merge upstream onto
master. If this works, great. If it doesn't and you have merge
work to do, it's usually easier to run git reset --hard and then go
find the bug or feature branch with the problems and merge upstream
into that so that you can deal with one set of conflicts at once and you
don't have to deal with the merge into that branch later. (git
rerere is often useful here. See the man page.)
If upstream has incorporated the changes in a bug or feature branch, I
merge upstream into that branch, merge the branch one last time
into master, and then delete it with git branch -d. Using
that procedure ensures that you really did get everything left on that
branch.
If you have conflicts on multiple branches, merge upstream into
each one and resolve the conflicts one-by-one. Then, create a
tmp-merge branch cloned off of upstream, merge each feature and bug
branch onto it (including debian), merge tmp-merge into
master, and then delete tmp-merge. This serializes all the
merges and avoids problems with merges conflicting with each other.
(Alternately, you can use rebasing of your bug and feature branches, but I
prefer the merge workflow to the rebase workflow most of the time, even
when I'm not publishing repositories.)
Conflict resolution is similar to Subversion. Search for the
<<<<< string for each conflict, figure out which version is
correct (or some merger of both), delete the conflict markers, and repeat
as necessary. When done with a file, use git add to mark it as
resolved. Then run git commit to commit the merge with its
conflicts. Usually you want to leave the commit message unchanged.
If the upstream source has to be repackaged for DFSG reasons, you can just generate a new *.orig.tar.gz file outside of Git and then import it as described above. However, Git and git-buildpackage have some additional features that may make this easier if you're just excluding certain files from the upstream source.
You can import the upstream distribution selectively using:
git-import-orig --filter='rfc*' /path/to/upstream/tarball
for example, adding --filter options for every file in the upstream
source that you need to exclude. (These options can be recorded in
debian/gbp.conf for others working on the package rather than
giving them directly on the command line.) Then, you can generate the
DFSG-free version of the upstream tarball with:
git archive --prefix=<package>_<version>.orig/ upstream/<version> \
| gzip -9 > <package>_<version>.orig.tar.gz
pristine-tar commit <package>_<version>.orig.tar.gz
rm <package>_<version>.orig.tar.gz
Whether to use this approach or the more traditional approach of
generating the *.orig.tar.gz file separately and then using
git-import-orig as always is up to you and depends on which
approach you find simpler.
For my Debian packages maintained in Git, I do use the 3.0 (quilt) source package version, but I don't attempt to maintain separate patches. I've experimented with some of the systems for extracting individual patches from Git, but they have all seemed clunky or involve too much make-work. Instead, I configure the Debian build system to create a single Debian patch with all divergences from upstream.
To do this, create debian/source/format with its normal contents of
3.0 (quilt) and then debian/source/options containing
single-debian-patch. I then create
debian/source/patch-header with contents like:
Subject: Collected Debian patches for <package>
Author: Russ Allbery <rra@debian.org>
The <package> package is maintained in Git rather than maintaining
patches as separate files, and separating the patches doesn't seem to
be worth the effort. They are therefore all included in this single
Debian patch.
For full commit history and separated commits, see the packaging Git
repository.
For packages where I'm also upstream, I only cherry-pick changes into the debian branch and instead use a patch header of:
Subject: Collected Debian patches for <package>
Author: Russ Allbery <rra@debian.org>
Since I am also upstream for this package, there will normally not be
any patches to apply to the upstream source. However, occasionally
I'll pull up specific upstream commits prior to making an upstream
release. When this happens, this patch will collect all of those
modifications.
I use Git to maintain both the upstream source and the Debian
packages, and generating individual patches rather than using git
cherry-pick takes extra work for no gain. Since I'm also upstream,
there's no need to separate the patches for later upstream submission.
Hence, I take this approach with a unified patch when it's necessary.
For full commit history and separated commits, see the upstream Git
repository.
Of course, if you use these as templates for your own packages, don't forget to change the Author line.
Eventually, I'll change this to use debian/source/local-options or
something similar so that any NMU patches will end up as separate patches
from my normal packaging patch.
I still commit debian/changelog entries along with the
corresponding change and just resolve the conflicts when I cherry-pick or
merge. This doesn't really bother me, but it is some additional work.
Some people instead leave the Debian changelog file alone until the
release and then use git-dch or some similar tool to generate it and then
edit it. At some point, I'd like to play with that idea.
debcommit's support for determining the commit message from my changelog entry doesn't do what I want, so I write the commit message separately. Your mileage may vary.
I don't commit changes to Autotools files (config.guess,
regeneration of configure, regeneration of Automake makefiles,
Libtool updates, etc.) to the repository. Instead, I build-depend on the
appropriate packages and do this at build time, and then delete all
modified files in the clean target of debian/rules. I think this
is simpler. Be sure to delete all the modified files, though, or you can
have trouble when building twice in a row or end up with spurious
modifications in your diffs. You can check this by running
debian/rules build and then fakeroot debian/rules clean and
make sure that no added or modified files show up in the git status
output, only deleted files. (Take a look at the dh-autoreconf package for
a helper program to make this easier.)
gitk is incredibly useful for performing any sort of archaeology. I've
gotten to the point where I often turn to it instead of git log.
It's particularly useful if you forget to tag uploads and need to figure
out what specific revision corresponded to a Debian package upload.
Often backporting a package to stable is as simple as just adding a new changelog entry for the backport and then rebuilding it in a stable chroot instead of an unstable chroot. This document doesn't cover that case, since it can be done without any representation in the version control repository (and normally there's no point in committing such backports anywhere).
If backporting requires more work, such as changing build dependencies or
adjusting the packaging for tools that aren't present in stable, the
easiest way to do this using Git is to create a new branch off of
master and make the necessary changes there. For example, for an
squeeze backport:
git checkout -b squeeze master
# edit debian/control and other files as needed
# edit debian/changelog to add backport log entry
git-buildpackage --git-debian-branch=squeeze -v<last-version>
git tag debian/<version>
The -v option should specify the last version of the package
available in stable, if it was previously in stable, so that the *.changes
file will include all changes since that date. The version of the
backport should follow the conventions of whatever repository for which it
is being prepared; for the backports.debian.org repository, see the
documentation for
contributing.
For later backports, you normally will be able to merge the new master branch into the backport branch with:
git checkout squeeze
git merge master
The debian/changelog file may have conflicts that have to be
resolved, normally by removing the old backport log entry and adding a new
one for the new backport.
For many of my packages, I'm both the Debian packager and the upstream maintainer. In those cases, I want a combined repository that I can use for both upstream maintenance and for Debian packaging.
Before using Git, I used to do this by maintaining the debian
directory in with the upstream code like any other part of the code, on
the main development branch, and just excluding it from releases. Then,
to build Debian packages, I'd unpack the latest tarball, export the
debian directory from the repository into the unpacked working
tree, and build the result. I had a script that automated much of this
process.
This works, but it has a few drawbacks:
It requires automation and pieces external to the repository, such as the latest upstream tarball. Without my script to automate the builds, setting up the build directory is somewhat tedious and requires explanation. Someone can't just check out the repository and build new Debian packages based on the current version without some extra effort.
It requires that the only changes for Debian packaging be isolated to the Debian directory. If I use a patch system, this is okay, but it limits the possibilities.
After switching to Git, I wanted a more general solution without these limitations that could also leverage pristine-tar so that all the information required to build the package was within the repository.
The two things that make this tricky are that pristine-tar, to be space-efficient, requires a complete import of the upstream source in a branch in the repository, and the Debian packaging should be based off the source tarball as released. My main upstream maintenance branch of course doesn't include generated files such as configure or files that are installed by Automake such as config.sub, nor do I want to check those files into my working repository and have to keep updating them. However, I do want to check the tarball releases into the repository and base the Debian packaging off that.
I therefore keep the upstream maintenance and the Debian packaging on
independent sets of branches without common ancestors. I work on the
master branch and, when I'm ready to release, tag the released
state of that branch with a release/<version> tag. Then, I use
git-import-orig to import that released tarball, generally
constructed with make dist or an equivalent thereof, into an
upstream branch and merge it into a debian branch based off
of that. This lets me still cherry-pick commits from upstream development
if I need them in a Debian package before the next upstream release, but
the Debian packaging is properly based on the released tarballs and
there's a branch holding the full tarball contents for pristine-tar to
work with.
If you use this configuration, you'll want to add a .git/gbp.conf
file in the repository containing:
[DEFAULT]
debian-branch = debian
so that git-buildpackage and git-import-orig won't try to
operate on the master branch.
Converting an existing repository that combines Debian packaging and the
upstream development is a bit tricky, since you want to create a new
debian branch that shares the history of the current master
and an upstream branch that can be merged into debian and
used by git-import-orig, but you also want to remove the
debian/* directory from the master branch. The first time I
tried this, I ended up merging the removal of the debian/*
directory into my debian branch and having to back out of that.
After some experimentation, the following approach seems to work the best:
Before removing debian/* from master, create the
debian branch with git branch debian master.
git rm -r debian on the master branch and commit it.
git branch upstream master. Now you have an upstream branch
with the right history and without the debian/* directory,
although it doesn't match the upstream tarball release (it's missing
generated files).
Record in Git that the debian branch is already a correct
reflection of the changes relative to the upstream branch by
adding a merge commit. git checkout debian and then git
merge -s ours upstream. The -s ours is the key trick; it
records the merge commit without deleting debian/* as part of
the merge.
Now you can run git-import-orig on the current upstream release
tarball, let it fix up the upstream branch to match the release
tarball by adding all the generated files, and then merge them into
the debian branch. You can do this now if you haven't made any
changes since the previous release. If you have made changes, the
easiest thing to do is to wait until you do another release and then
have that be the first true imported release.
I don't bother to go back and try to reconstruct history and put previous
releases in the upstream branch. It's a lot of work and doesn't
seem worth the effort.
An even better approach than exporting a tarball and importing it with
git-import-orig is to commit the upstream tarball release as a
merge commit between the upstream release tag and the upstream
branch used for the Debian packaging workflow. I'm currently doing this
for the Debian openafs source package and will hopefully find time
to write this up in more detail and convert my other packages to it. In
the meantime, see the debian/README.source file in the
openafs package for more details.
I have a bunch of old Debian packaging repositories in Subversion that I'm converting to Git. There are a lot of different ways to do this, but here's the one that works for me. This technique is heavily based on a blog entry from Martin Krafft.
First, install git-svn if it's not already installed.
My packages all use an svn-buildpackage layout, which means there's an
upstream directory under branches that has the imports of
the upstream source. I'm usually willing to throw away any other
branches, so I start with:
git svn clone --stdlayout --branches=branches/upstream --no-metadata \
-A /path/to/authors/file <svn-url>
This will create a new subdirectory named after the last component of the
<svn-url> with a new Git repository. This command treats all the upstream
tags and current as branches and ignores the other branches; if you want
to keep all the branches, svn mv the contents of branches/upstream
into branches first and then point git svn at the whole branches
directory.
Note the -A option; use that to specify the path to a mapping from
usernames in the Subversion commits to full names and e-mail addresses for
Git. Without this, your old commits will have ugly identification. See
the git-svn man page for the details on the format.
--no-metadata means that we're doing a one-way conversion and
git svn shouldn't keep the data required to support commits back to
the Subversion repository.
git svn will leave your Subversion trunk and branches as remote
branches in your repository and will create all of your tags as more
remote branches. The first step is to clean that up. Get a full branch
list with git branch -r. Then, create new local branches for the
remote branches that are really branches; at the least, you'll probably
want:
git branch upstream branches/current
git branch -r -d branches/current
Note the removal of the remote tracking branch using git branch -r
-d; that's how you get rid of those. Next, convert each tag into a real
tag. The revision to which the tag should apply will be the revision
prior to the one recorded in the repository, so take advantage of Git's
^ shortcut for previous revision with commands like:
git tag debian/<version> tags/<version>^
git branch -r -d tags/<version>
Similarly for all the tags of the upstream imports, do:
git tag upstream/<version> branches/<version>^
git branch -r -d branches/<version>
Once you finish this, git branch -r should show no remote tracking
branches and only your regular upstream and master branches.
If you used the svn-buildpackage mergeWithUpstream feature to not
store the upstream source in your Git repository, the conversion has a few
more steps. You need to import the upstream source into the repository to
use Git the way that I outline in this document. Ideally, you should be
able to do that by just importing the most recent upstream tarball from
Debian with git-import-orig, but it currently cannot handle
creating the upstream branch from scratch. Instead, be sure you
have no uncommitted changes and then first create an empty upstream
branch:
git symbolic-ref HEAD refs/heads/upstream
git rm --cached -r .
git commit --allow-empty -m'Initial upstream branch'
git checkout -f master
and then you can import the latest upstream source:
git-import-orig /path/to/orig.tar.gz
This will commit and tag the upstream source and merge it into your
master branch, fleshing out your repository. All of your old tags
will still have only modified files, but normally that's not a serious
problem.
If you had to do git-import-orig as described above, it will take
care of committing the pristine-tar metadata. Otherwise, grab the last
upstream orig.tar.gz (and make sure that it's named properly), put it
somewhere not in the current directory, and run:
pristine-tar commit /path/to/orig.tar.gz
to load it into the repository. If you want, you can also load older upstream tar.gz files, but I never bother.
You can now delete some additional junk left over from the git svn
conversion process. Edit .git/config and remove the information
about the remote tracking branches for the Subversion repository, and
delete all of .git/svn.
If you're like me, you weren't very good about always tagging releases in
Subversion. You can now much more easily fix this by browsing the
repository using gitk and finding the release points for each
Debian package. When you do, paste the hash (shown nicely in gitk for
you) into a git tag command like:
git tag debian/<version> <hash>
When you select a revision in gitk, it copies the hash of that
revision into the X cut buffer for you, so you can paste it into a command
without selecting it.
Finally, do the same things as noted above under setting up a Debian
packaging repository (clone master to debian, move things to
feature or bug branches, and so forth).
My old CVS repositories don't use branches or tags, so importing them was much easier and essentially follows the git-cvsimport man page.
First, install the git-cvs package if you haven't already.
Now, run git cvsimport. Since I'm doing one-way conversions and
plan on discarding all the old CVS information afterwards, I use options
like:
git cvsimport -d <cvs-repository> -o master -k -A <authors-file> \
-a -C <project> <module>
where <project> is the name of the new directory you want to create with the imported repository. As with Subversion, you'll need an authors file that maps the usernames stored in CVS commit messages to identities in the new Git repository.
If you're like me, you'll then want to go back through the history with
gitk and tag all the past releases with git tag.
When I did a Google search on migrating a bzr repository to Git, most of
the documentation said to use tailor. However, it didn't work; it got as
far as a changeset that renamed ChangeLog to CHANGES.old and then bailed
because it claimed the git add command on CHANGES.old failed. When
I ran exactly the command that it claimed to have ran by hand, it worked
fine, but I couldn't figure out how to convince tailor of that.
Thankfully, there's a better alternative, although it's not well-documented yet. Git and bzr both have support for the fast-import repository serialization format, although the bzr support is somewhat hidden away if you're using Debian. Here are the instructions that I used back when I did this; now, it looks like bzr-fastimport is a regular Debian package and installs a plugin, so I suspect that just installing it and using the commands it provides will work.
First, get the bzr-fastimport source tree from Launchpad:
bzr branch lp:bzr-fastimport
Then, create a new directory and empty Git repository for your project:
mkdir <project>
cd <project>
git init
Now, you can import your old bzr repository by serializing it using the
bzr-fast-export.py script that comes with bzr-fastimport:
/path/to/bzr-fastimport/exporters/bzr-fast-export.py \
/path/to/bzr-repository | git fast-import
git checkout master
This will even preserve tags in your bzr repository.
| < Debian Packaging Tools | Russ Allbery > Technical Notes > Debian | Packaging Scripts for Debian > |