From 7a0e4d6676962e090eeb0038462db3754092b310 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Sat, 17 Feb 2018 15:47:33 -0700 Subject: [PATCH] dgit-maint-debrebase(7): first draft Signed-off-by: Sean Whitton --- dgit-maint-debrebase.7.pod | 534 +++++++++++++++++++++++++++++++++++++ 1 file changed, 534 insertions(+) create mode 100644 dgit-maint-debrebase.7.pod diff --git a/dgit-maint-debrebase.7.pod b/dgit-maint-debrebase.7.pod new file mode 100644 index 00000000..0b4e7569 --- /dev/null +++ b/dgit-maint-debrebase.7.pod @@ -0,0 +1,534 @@ +=head1 NAME + +dgit - tutorial for package maintainers, using a workflow centered around git-debrebase(1) + +=head1 INTRODUCTION + +This document describes elements of a workflow for maintaining a +non-native Debian package using B. We maintain the Debian delta +as a series of git commits on our master branch. We use +git-debrebase(1) to shuffle our branch such that this series of git +commits appears at the end of the branch. This does not involve +rewriting any public git history. + +Some advantages of this workflow: + +=over 4 + +=item + +Manipulate the patch queue using the full power of git-rebase(1), +instead of relying on quilt(1), and without having to switch away to +another branch, as with gbp-pq(1). + +=item + +Avoid the git tree being dirtied by the application or unapplication +of patches, as they are always applied. + +=item + +Benefit from dgit's safety catches. In particular, ensure that your +upload always matches exactly your git HEAD. + +=item + +Provide your full git history in a standard format on B, +where it can benefit downstream dgit users, such as people using dgit +to do an NMU (see dgit-nmu-simple(7) and dgit-user(7)). + +=back + +This workflow is appropriate for packages where the Debian delta +contains multiple pieces which interact, or which you don't expect to +be able to upstream soon. For packages with simple and/or short-lived +Debian deltas, use of git-debrebase(1) might introduce unneeded +complexity. For such packages, consider the workflow described in +dgit-maint-merge(7). + +=head1 INITIAL DEBIANISATION + +=head2 When upstream tags releases in git + +This section explains how to start using this workflow with a new +package. It should be skipped when converting an existing package to +this workflow. + +Suppose that the latest stable upstream release is 1.2.2, and this has +been tagged '1.2.2' by upstream. + +=over 4 + + % git clone -oupstream https://some.upstream/foo.git + % cd foo + % git verify-tag 1.2.2 + % git reset --hard 1.2.2 + % git branch --unset-upstream + +=back + +The final command detaches your master branch from the upstream +remote, so that git doesn't try to push anything there, or merge +unreleased upstream commits. To maintain a copy of your packaging +branch on B in addition to B, you can do +something like this: + +=over 4 + + % git remote add -f origin salsa.debian.org:Debian/foo.git + % git push --follow-tags -u origin master + +=back + +Now go ahead and Debianise your package. Just make commits on the +master branch, adding things in the I directory. If you need +to patch the upstream source, see "EDITING THE PATCH QUEUE", below. +Note that there is no need to maintain a separate 'upstream' branch, +unless you also happen to be involved in upstream development. We +work with upstream tags rather than any branches, except when +forwarding patches (see FORWARDING PATCHES UPSTREAM, below). + +Finally, you need an orig tarball: + +=over 4 + + % git deborig + +=back + +See git-deborig(1) if this fails. + +This tarball is ephemeral and easily regenerated, so we don't commit +it anywhere (e.g. with tools like pristine-tar(1)). + +=head3 Verifying upstream's tarball releases + +=over 4 + +It can be a good idea to compare upstream's released tarballs with the +release tags, at least for the first upload of the package. If they +are different, you might need to add some additional steps to your +I, such as running autotools. + +A convenient way to perform this check is to import the tarball as +described in the following section, using a different value for +'upstream-tag', and then use git-diff(1) to compare the imported +tarball to the release tag. If they are the same, you can use +upstream's tarball instead of running git-deborig(1). + +=back + +=head2 When upstream releases only tarballs + +We need a virtual upstream branch with virtual release tags. +gbp-import-orig(1) can manage this for us. To begin + +=over 4 + + % mkdir foo + % cd foo + % git init + +=back + +Now create I: + +=over 4 + + [DEFAULT] + upstream-branch = upstream + debian-branch = master + upstream-tag = %(version)s + + sign-tags = True + pristine-tar = False + pristine-tar-commit = False + + [import-orig] + merge-mode = merge + +=back + +gbp-import-orig(1) requires a pre-existing upstream branch: + +=over 4 + + % git add debian/gbp.conf && git commit -m "create gbp.conf" + % git checkout --orphan upstream + % git rm -rf . + % git commit --allow-empty -m "initial, empty branch for upstream source" + % git checkout -f master + +=back + +Then we can import the upstream version: + +=over 4 + + % gbp import-orig --merge-mode=replace ../foo_1.2.2.orig.tar.xz + +=back + +Our upstream branch cannot be pushed to B, but since we +will need it whenever we import a new upstream version, we must push +it somewhere. The usual choice is B: + +=over 4 + + % git remote add -f origin salsa.debian.org:Debian/foo.git + % git push --follow-tags -u origin master upstream + +=back + +You are now ready to proceed as above, making commits to the +I directory. + +=head1 CONVERTING AN EXISTING PACKAGE + +This section explains how to convert an existing Debian package to +this workflow. It should be skipped when debianising a new package. + +=head2 No existing git history + +=over 4 + + % dgit clone foo + % cd foo + % git remote add -f upstream https://some.upstream/foo.git + +=back + +=head2 Existing git history using another workflow + +First, if you don't already have the git history locally, clone it, +and obtain the corresponding orig.tar from the archive: + +=over 4 + + % git clone salsa.debian.org:Debian/foo + % cd foo + % origtargz + +=back + +If your tree is patches-unapplied, you will need to make a commit +corresponding to each of the quilt patches. gbp-pq(1) can do this for +us: + +=over 4 + + % gbp pq import + % gbp pq switch + % git merge --ff-only patch-queue/master + % gbp pq drop + +=back + +Then make new upstream tags available: + +=over 4 + + % git remote add -f upstream https://some.upstream/foo.git + +=back + +=for dgit-test dpkg-source-ignores begin + +Now you simply need to ensure that your git HEAD is dgit-compatible, +i.e., it is exactly what you would get if you ran +B +and then unpacked the resultant source package. + +=for dgit-test dpkg-source-ignores end + +To achieve this, you might need to delete +I. One way to have dgit check your +progress is to run B. + +The first dgit push will require I<--overwrite>. If this is the first +ever dgit push of the package, consider passing +I<--deliberately-not-fast-forward> instead of I<--overwrite>. This +avoids introducing a new origin commit into your git history. (This +origin commit would represent the most recent non-dgit upload of the +package, but this should already be represented in your git history.) + +=head1 IMPORTING NEW UPSTREAM RELEASES + +=head2 Obtaining the release + +=head3 When upstream tags releases in git + +=over 4 + + % git remote update + +=back + +=head3 When upstream releases only tarballs + +You will need the I from "When upstream releases only +tarballs", above. You will also need your upstream branch. Above, we +pushed this to B. You will need to clone or fetch +from there, instead of relying on B/B alone. + +Then, either + +=over 4 + + % gbp import-orig --no-merge ../foo_1.2.3.orig.tar.xz + +=back + +or if you have a working watch file + +=over 4 + + % gbp import-orig --no-merge --uscan + +=back + +=head2 Importing the release + +=over 4 + + % git debrebase new-upstream-v0 1.2.3 + % dch -v1.2.3-1 New upstream release. + % git add debian/changelog && git commit -m changelog + +=back + +You can now review the merge of the new upstream release: + +=over 4 + + git diff debian/1.2.2-1..HEAD -- . ':!debian' + +=back + +Pass I<--stat> just to see the list of changed files, which is useful +to determine whether there are any new or deleted files to may need +accounting for in your copyright file. + +If you obtained a tarball from upstream, you are ready to try a build. +If you merged a git tag from upstream, you will first need to generate +a tarball: + +=over 4 + + % git deborig + +=back + +=head1 EDITING THE PATCH QUEUE + +=head2 Adding new patches + +Adding new patches is straightforward: just make commits touching only +files outside of the I directory. You can also use tools +like git-revert(1), git-am(1) and git-cherrypick(1). + +=head2 Editing patches: starting a debrebase + +git-debrebase(1) is a wrapper around git-rebase(1) which allows us to +edit, re-order and delete patches. Run + +=over 4 + + % git debrebase + +=back + +to start an interactive rebase. You can edit, re-order and delete +commits just as you would during B. Alternatively, you +can perform a non-interactive rebase like this: + +=over 4 + + % git debrebase -- [git-rebase options...] + +=back + +For example, + +=over 4 + + % git debrebase -- --autosquash + +=back + +A third alternative is to have git-debrebase(1) shuffle all the Debian +changes to the end of your branch, and then manipulate them yourself +using git-rebase(1). For example, + +=over 4 + + % git debrebase launder + % git rebase -i HEAD^5 # there are 4 Debian patches + +=back + +=head2 Editing patches: finishing a debrebase + +After completing the git rebase, your branch will not be a +fast-forward of the git HEAD you had before the rebase. This means +that we cannot push the branch anywhere. If you are ready to upload, +B or B will take care of fixing this up +for you. + +If you are not yet ready to upload, and want to push your branch to a +git remote such as B, + +=over 4 + + % git debrebase stitch + +=back + +Note that each time you stitch a debrebase you introduce a pseudomerge +into your git history, which may make it harder to read. Try to do +all of the editing of the patch queue that you think will be needed +for this upload in a single debrebase, so that there is a single +debrebase stitch. + +A strategy is to debrebase only right before you upload. Before that +point, instead of editing the existing patch series, you append fixup +commits (and reversions of commits) that alter the upstream source to +the required state. You can freely push and pull from +B during this. Just before uploading, you debrebase +to tidy everything up. + +=head1 BUILDING AND UPLOADING + +Use B, B, B and B as detailed in dgit(1). If any command fails, dgit will +provide a carefully-worded error message explaining what you should +do. If it's not clear, file a bug against dgit. Remember to pass +I<--new> for the first upload. + +After dgit pushing, be sure to git push to B, if +you're using that. + +As an alternative to B and friends, you can use a tool +like gitpkg(1). This works because like dgit, gitpkg(1) enforces that +HEAD has exactly the contents of the source package. gitpkg(1) is +highly configurable, and one dgit user reports using it to produce and +test multiple source packages, from different branches corresponding +to each of the current Debian suites. + +If you want to skip dgit's checks while iterating on a problem with +the package build (for example, you don't want to commit your changes +to git), you can just run dpkg-buildpackage(1) or debuild(1) instead. + +=head2 Laundering the patch queue before uploading + +Just before you B or B, you might want to +have git-debrebase(1) shuffle your branch such that the Debian patch +queue appears at the end: + +=over 4 + + % git debrebase launder + % dgit push-source + +=back + +Note that this will introduce a new pseudomerge. + +=head1 HANDLING DFSG-NON-FREE MATERIAL + +=head2 When upstream tags releases in git + +We create a DFSG-clean tag to import to master: + +=over 4 + + % git checkout -b pre-dfsg 1.2.3 + % git rm evil.bin + % git commit -m "upstream version 1.2.3 DFSG-cleaned" + % git tag -s 1.2.3+dfsg + % git checkout master + % git branch -D pre-dfsg + +=back + +Before invoking B, you should first +determine whether it would be legally dangerous for the non-free +material to be publicly accessible in the git history on +B. + +If it would be dangerous, there is a big problem; +in this case please consult your archive administrators +(for Debian this is the dgit administrator dgit-owner@debian.org +and the ftpmasters ftpmaster@ftp-master.debian.org). + +=head2 When upstream releases only tarballs + +The easiest way to handle this is to add a B field to +I, and a B setting in +I. See uscan(1). Alternatively, see the I<--filter> +option detailed in gbp-import-orig(1). + +=head1 FORWARDING PATCHES UPSTREAM + +The basic steps are: + +=over 4 + +=item 1. + +Create a new branch based off upstream's master branch. + +=item 2. + +git-cherry-pick(1) commits from your master branch onto your new +branch. + +=item 3. + +Push the branch somewhere and ask upstream to merge it, or use +git-format-patch(1) or git-request-pull(1). + +=back + +For example (and it is only an example): + +=over 4 + + % # fork foo.git on GitHub + % git remote add -f fork git@github.com:spwhitton/foo.git + % git checkout -b fix-error upstream/master + % git config branch.fix-error.pushRemote fork + % git cherry-pick master^2 + % git push + % # submit pull request on GitHub + +=back + +Note that when you merge an upstream release containing your forwarded +patches, a debrebase will transparently handle "dropping" the patches +that have been forwarded, "retaining" the ones that haven't. + +=head1 INCORPORATING NMUS + +=over 4 + + % dgit pull + +=back + +If the NMUer added new commits modifying the upstream source, you will +probably want to debrebase before your next upload to tidy those up. + +For example, the NMUer might have used git-revert(1) to unapply one of +your patches. A debrebase will strip both the patch and the reversion +from the patch series. + +=head1 SEE ALSO + +dgit(1), dgit(7) + +=head1 AUTHOR + +This tutorial was written and is maintained by Sean Whitton +. It contains contributions from other dgit +contributors too - see the dgit copyright file. -- 2.30.2