bos@1: \chapter{Managing change with Mercurial Queues} bos@1: \label{chap:mq} bos@1: bos@1: \section{The patch management problem} bos@1: \label{sec:mq:patch-mgmt} bos@1: bos@1: Here is a common scenario: you need to install a software package from bos@1: source, but you find a bug that you must fix in the source before you bos@1: can start using the package. You make your changes, forget about the bos@1: package for a while, and a few months later you need to upgrade to a bos@1: newer version of the package. If the newer version of the package bos@1: still has the bug, you must extract your fix from the older source bos@1: tree and apply it against the newer version. This is a tedious task, bos@1: and it's easy to make mistakes. bos@1: bos@1: This is a simple case of the ``patch management'' problem. You have bos@1: an ``upstream'' source tree that you can't change; you need to make bos@1: some local changes on top of the upstream tree; and you'd like to be bos@1: able to keep those changes separate, so that you can apply them to bos@1: newer versions of the upstream source. bos@1: bos@1: The patch management problem arises in many situations. Probably the bos@1: most visible is that a user of an open source software project will bos@1: contribute a bugfix or new feature to the project's maintainers in the bos@1: form of a patch. bos@1: bos@1: Distributors of operating systems that include open source software bos@1: often need to make changes to the packages they distribute so that bos@1: they will build properly in their environments. bos@1: bos@1: When you have few changes to maintain, it is easy to manage a single bos@1: patch using the standard \texttt{diff} and \texttt{patch} programs. bos@1: Once the number of changes grows, it starts to makes sense to maintain bos@1: patches as discrete ``chunks of work,'' so that for example a single bos@1: patch will contain only one bug fix (the patch might modify several bos@1: files, but it's doing ``only one thing''), and you may have a number bos@1: of such patches for different bugs you need fixed and local changes bos@1: you require. In this situation, if you submit a bugfix patch to the bos@1: upstream maintainers of a package and they include your fix in a bos@1: subsequent release, you can simply drop that single patch when you're bos@1: updating to the newer release. bos@1: bos@1: Maintaining a single patch against an upstream tree is a little bos@1: tedious and error-prone, but not difficult. However, the complexity bos@1: of the problem grows rapidly as the number of patches you have to bos@1: maintain increases. With more than a tiny number of patches in hand, bos@1: understanding which ones you have applied and maintaining them moves bos@1: from messy to overwhelming. bos@1: bos@1: Fortunately, Mercurial includes a powerful extension, Mercurial Queues bos@1: (or simply ``MQ''), that massively simplifies the patch management bos@1: problem. bos@1: bos@1: \section{The prehistory of Mercurial Queues} bos@1: \label{sec:mq:history} bos@1: bos@1: During the late 1990s, several Linux kernel developers started to bos@1: maintain ``patch series'' that modified the behaviour of the Linux bos@1: kernel. Some of these series were focused on stability, some on bos@1: feature coverage, and others were more speculative. bos@1: bos@1: The sizes of these patch series grew rapidly. In 2002, Andrew Morton bos@1: published some shell scripts he had been using to automate the task of bos@1: managing his patch queues. Andrew was successfully using these bos@1: scripts to manage hundreds (sometimes thousands) of patches on top of bos@1: the Linux kernel. bos@1: bos@1: \subsection{A patchwork quilt} bos@1: \label{sec:mq:quilt} bos@1: bos@1: bos@1: In early 2003, Andreas Gruenbacher and Martin Quinson borrowed the bos@1: approach of Andrew's scripts and published a tool called bos@1: \href{http://savannah.nongnu.org/projects/quilt}{``patchwork quilt''}, bos@1: or simply ``quilt''. Because quilt substantially automated patch bos@1: management, it rapidly gained a large following among open source bos@1: software developers. bos@1: bos@1: Quilt manages a \emph{stack of patches} on top of a directory tree. bos@1: To begin, you tell quilt to manage a directory tree; it stores away bos@1: the names and contents of all files in the tree. To fix a bug, you bos@1: create a new patch (using a single command), edit the files you need bos@1: to fix, then ``refresh'' the patch. bos@1: bos@1: The refresh step causes quilt to scan the directory tree; it updates bos@1: the patch with all of the changes you have made. You can create bos@1: another patch on top of the first, which will track the changes bos@1: required to modify the tree from ``tree with one patch applied'' to bos@1: ``tree with two patches applied''. bos@1: bos@1: You can \emph{change} which patches are applied to the tree. If you bos@1: ``pop'' a patch, the changes made by that patch will vanish from the bos@1: directory tree. Quilt remembers which patches you have popped, bos@1: though, so you can ``push'' a popped patch again, and the directory bos@1: tree will be restored to contain the modifications in the patch. Most bos@1: importantly, you can run the ``refresh'' command at any time, and the bos@1: topmost applied patch will be updated. This means that you can, at bos@1: any time, change both which patches are applied and what bos@1: modifications those patches make. bos@1: bos@1: Quilt knows nothing about revision control tools, so it works equally bos@1: well on top of an unpacked tarball or a Suversion repository. bos@1: bos@1: \subsection{From patchwork quilt to Mercurial Queues} bos@1: \label{sec:mq:quilt-mq} bos@1: bos@1: In mid-2005, Chris Mason took the features of quilt and wrote an bos@1: extension that he called Mercurial Queues, which added quilt-like bos@1: behaviour to Mercurial. bos@1: bos@1: The key difference between quilt and MQ is that quilt knows nothing bos@1: about revision control systems, while MQ is \emph{integrated} into bos@1: Mercurial. Each patch that you push is represented as a Mercurial bos@1: changeset. Pop a patch, and the changeset goes away. bos@1: bos@1: This integration makes understanding patches and debugging their bos@1: effects \emph{enormously} easier. Since every applied patch has an bos@1: associated changeset, you can use \hgcmdargs{log}{\emph{filename}} to bos@1: see which changesets and patches affected a file. You can use the bos@1: \hgext{bisect} extension to binary-search through all changesets and bos@1: applied patches to see where a bug got introduced or fixed. You can bos@1: use the \hgcmd{annotate} command to see which changeset or patch bos@1: modified a particular line of a source file. And so on. bos@1: bos@1: Because quilt does not care about revision control tools, it is still bos@1: a tremendously useful piece of software to know about for situations bos@1: where you cannot use Mercurial and MQ. bos@1: \section{Section!} bos@1: \label{sec:sec} bos@1: bos@1: Section! bos@1: bos@1: %%% Local Variables: bos@1: %%% mode: latex bos@1: %%% TeX-master: "00book" bos@1: %%% End: