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@3: contribute a bug fix 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@15: patch using the standard \texttt{diff} and \texttt{patch} programs bos@15: (see section~\ref{sec:mq:patch} for a discussion of these tools). 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@3: you require. In this situation, if you submit a bug fix 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@2: approach of Andrew's scripts and published a tool called ``patchwork bos@2: quilt''~\cite{web:quilt}, or simply ``quilt'' bos@2: (see~\cite{gruenbacher:2005} for a paper describing it). Because bos@2: quilt substantially automated patch management, it rapidly gained a bos@2: large following among open source software developers. bos@1: bos@1: Quilt manages a \emph{stack of patches} on top of a directory tree. bos@28: To begin, you tell quilt to manage a directory tree, and tell it which bos@28: files you want to manage; it stores away the names and contents of bos@28: those files. To fix a bug, you create a new patch (using a single bos@28: command), edit the files you need 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@3: well on top of an unpacked tarball or a Subversion 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@19: bos@19: \section{Understanding patches} bos@26: \label{sec:mq:patch} bos@19: bos@19: Because MQ doesn't hide its patch-oriented nature, it is helpful to bos@19: understand what patches are, and a little about the tools that work bos@19: with them. bos@19: bos@19: The traditional Unix \command{diff} command compares two files, and bos@19: prints a list of differences between them. The \command{patch} command bos@19: understands these differences as \emph{modifications} to make to a bos@19: file. Take a look at figure~\ref{ex:mq:diff} for a simple example of bos@19: these commands in action. bos@19: bos@19: \begin{figure}[ht] bos@19: \interaction{mq.diff.diff} bos@19: \caption{Simple uses of the \command{diff} and \command{patch} commands} bos@19: \label{ex:mq:diff} bos@19: \end{figure} bos@19: bos@19: The type of file that \command{diff} generates (and \command{patch} bos@19: takes as input) is called a ``patch'' or a ``diff''; there is no bos@19: difference between a patch and a diff. (We'll use the term ``patch'', bos@19: since it's more commonly used.) bos@19: bos@19: A patch file can start with arbitrary text; the \command{patch} bos@19: command ignores this text, but MQ uses it as the commit message when bos@19: creating changesets. To find the beginning of the patch content, bos@19: \command{patch} searches for the first line that starts with the bos@19: string ``\texttt{diff~-}''. bos@19: bos@19: MQ works with \emph{unified} diffs (\command{patch} can accept several bos@19: other diff formats, but MQ doesn't). A unified diff contains two bos@19: kinds of header. The \emph{file header} describes the file being bos@19: modified; it contains the name of the file to modify. When bos@19: \command{patch} sees a new file header, it looks for a file with that bos@19: name to start modifying. bos@19: bos@19: After the file header comes a series of \emph{hunks}. Each hunk bos@19: starts with a header; this identifies the range of line numbers within bos@19: the file that the hunk should modify. Following the header, a hunk bos@19: starts and ends with a few (usually three) lines of text from the bos@19: unmodified file; these are called the \emph{context} for the hunk. If bos@19: there's only a small amount of context between successive hunks, bos@19: \command{diff} doesn't print a new hunk header; it just runs the hunks bos@19: together, with a few lines of context between modifications. bos@19: bos@19: Each line of context begins with a space character. Within the hunk, bos@19: a line that begins with ``\texttt{-}'' means ``remove this line,'' bos@19: while a line that begins with ``\texttt{+}'' means ``insert this bos@19: line.'' For example, a line that is modified is represented by one bos@19: deletion and one insertion. bos@19: bos@19: We will return to ome of the more subtle aspects of patches later (in bos@26: section~\ref{sec:mq:adv-patch}), but you should have enough information bos@19: now to use MQ. bos@19: bos@2: \section{Getting started with Mercurial Queues} bos@2: \label{sec:mq:start} bos@1: bos@3: Because MQ is implemented as an extension, you must explicitly enable bos@3: before you can use it. (You don't need to download anything; MQ ships bos@3: with the standard Mercurial distribution.) To enable MQ, edit your bos@4: \tildefile{.hgrc} file, and add the lines in figure~\ref{ex:mq:config}. bos@2: bos@12: \begin{figure}[ht] bos@4: \begin{codesample4} bos@4: [extensions] bos@4: hgext.mq = bos@4: \end{codesample4} bos@4: \label{ex:mq:config} bos@4: \caption{Contents to add to \tildefile{.hgrc} to enable the MQ extension} bos@4: \end{figure} bos@3: bos@3: Once the extension is enabled, it will make a number of new commands bos@7: available. To verify that the extension is working, you can use bos@7: \hgcmd{help} to see if the \hgcmd{qinit} command is now available; see bos@7: the example in figure~\ref{ex:mq:enabled}. bos@3: bos@12: \begin{figure}[ht] bos@4: \interaction{mq.qinit-help.help} bos@4: \caption{How to verify that MQ is enabled} bos@4: \label{ex:mq:enabled} bos@4: \end{figure} bos@1: bos@8: You can use MQ with \emph{any} Mercurial repository, and its commands bos@8: only operate within that repository. To get started, simply prepare bos@8: the repository using the \hgcmd{qinit} command (see bos@7: figure~\ref{ex:mq:qinit}). This command creates an empty directory bos@16: called \sdirname{.hg/patches}, where MQ will keep its metadata. As bos@7: with many Mercurial commands, the \hgcmd{qinit} command prints nothing bos@7: if it succeeds. bos@7: bos@12: \begin{figure}[ht] bos@7: \interaction{mq.tutorial.qinit} bos@7: \caption{Preparing a repository for use with MQ} bos@7: \label{ex:mq:qinit} bos@7: \end{figure} bos@7: bos@12: \begin{figure}[ht] bos@7: \interaction{mq.tutorial.qnew} bos@7: \caption{Creating a new patch} bos@7: \label{ex:mq:qnew} bos@7: \end{figure} bos@7: bos@8: \subsection{Creating a new patch} bos@8: bos@8: To begin work on a new patch, use the \hgcmd{qnew} command. This bos@7: command takes one argument, the name of the patch to create. MQ will bos@16: use this as the name of an actual file in the \sdirname{.hg/patches} bos@7: directory, as you can see in figure~\ref{ex:mq:qnew}. bos@7: bos@16: Also newly present in the \sdirname{.hg/patches} directory are two bos@16: other files, \sfilename{series} and \sfilename{status}. The bos@16: \sfilename{series} file lists all of the patches that MQ knows about bos@8: for this repository, with one patch per line. Mercurial uses the bos@16: \sfilename{status} file for internal book-keeping; it tracks all of the bos@7: patches that MQ has \emph{applied} in this repository. bos@7: bos@7: \begin{note} bos@16: You may sometimes want to edit the \sfilename{series} file by hand; bos@7: for example, to change the sequence in which some patches are bos@16: applied. However, manually editing the \sfilename{status} file is bos@7: almost always a bad idea, as it's easy to corrupt MQ's idea of what bos@7: is happening. bos@7: \end{note} bos@7: bos@8: Once you have created your new patch, you can edit files in the bos@8: working directory as you usually would. All of the normal Mercurial bos@8: commands, such as \hgcmd{diff} and \hgcmd{annotate}, work exactly as bos@8: they did before. bos@19: bos@8: \subsection{Refreshing a patch} bos@8: bos@8: When you reach a point where you want to save your work, use the bos@8: \hgcmd{qrefresh} command (figure~\ref{ex:mq:qnew}) to update the patch bos@8: you are working on. This command folds the changes you have made in bos@8: the working directory into your patch, and updates its corresponding bos@8: changeset to contain those changes. bos@8: bos@12: \begin{figure}[ht] bos@8: \interaction{mq.tutorial.qrefresh} bos@8: \caption{Refreshing a patch} bos@8: \label{ex:mq:qrefresh} bos@8: \end{figure} bos@8: bos@8: You can run \hgcmd{qrefresh} as often as you like, so it's a good way bos@13: to ``checkpoint'' your work. Refresh your patch at an opportune bos@8: time; try an experiment; and if the experiment doesn't work out, bos@8: \hgcmd{revert} your modifications back to the last time you refreshed. bos@8: bos@12: \begin{figure}[ht] bos@8: \interaction{mq.tutorial.qrefresh2} bos@8: \caption{Refresh a patch many times to accumulate changes} bos@8: \label{ex:mq:qrefresh2} bos@8: \end{figure} bos@8: bos@8: \subsection{Stacking and tracking patches} bos@8: bos@8: Once you have finished working on a patch, or need to work on another, bos@8: you can use the \hgcmd{qnew} command again to create a new patch. bos@8: Mercurial will apply this patch on top of your existing patch. See bos@8: figure~\ref{ex:mq:qnew2} for an example. Notice that the patch bos@8: contains the changes in our prior patch as part of its context (you bos@8: can see this more clearly in the output of \hgcmd{annotate}). bos@8: bos@12: \begin{figure}[ht] bos@8: \interaction{mq.tutorial.qnew2} bos@8: \caption{Stacking a second patch on top of the first} bos@8: \label{ex:mq:qnew2} bos@8: \end{figure} bos@8: bos@8: So far, with the exception of \hgcmd{qnew} and \hgcmd{qrefresh}, we've bos@27: been careful to only use regular Mercurial commands. However, MQ bos@27: provides many commands that are easier to use when you are thinking bos@27: about patches, as illustrated in figure~\ref{ex:mq:qseries}: bos@8: bos@8: \begin{itemize} bos@8: \item The \hgcmd{qseries} command lists every patch that MQ knows bos@8: about in this repository, from oldest to newest (most recently bos@8: \emph{created}). bos@8: \item The \hgcmd{qapplied} command lists every patch that MQ has bos@8: \emph{applied} in this repository, again from oldest to newest (most bos@8: recently applied). bos@8: \end{itemize} bos@8: bos@12: \begin{figure}[ht] bos@8: \interaction{mq.tutorial.qseries} bos@8: \caption{Understanding the patch stack with \hgcmd{qseries} and bos@8: \hgcmd{qapplied}} bos@8: \label{ex:mq:qseries} bos@8: \end{figure} bos@8: bos@8: \subsection{Manipulating the patch stack} bos@8: bos@8: The previous discussion implied that there must be a difference bos@11: between ``known'' and ``applied'' patches, and there is. MQ can bos@11: manage a patch without it being applied in the repository. bos@8: bos@8: An \emph{applied} patch has a corresponding changeset in the bos@8: repository, and the effects of the patch and changeset are visible in bos@8: the working directory. You can undo the application of a patch using bos@12: the \hgcmd{qpop} command. MQ still \emph{knows about}, or manages, a bos@12: popped patch, but the patch no longer has a corresponding changeset in bos@12: the repository, and the working directory does not contain the changes bos@12: made by the patch. Figure~\ref{fig:mq:stack} illustrates the bos@12: difference between applied and tracked patches. bos@12: bos@12: \begin{figure}[ht] bos@12: \centering jeffpc@35: \grafix{mq-stack} bos@12: \caption{Applied and unapplied patches in the MQ patch stack} bos@12: \label{fig:mq:stack} bos@8: \end{figure} bos@8: bos@8: You can reapply an unapplied, or popped, patch using the \hgcmd{qpush} bos@8: command. This creates a new changeset to correspond to the patch, and bos@8: the patch's changes once again become present in the working bos@8: directory. See figure~\ref{ex:mq:qpop} for examples of \hgcmd{qpop} bos@8: and \hgcmd{qpush} in action. Notice that once we have popped a patch bos@8: or two patches, the output of \hgcmd{qseries} remains the same, while bos@8: that of \hgcmd{qapplied} has changed. bos@8: bos@12: \begin{figure}[ht] bos@12: \interaction{mq.tutorial.qpop} bos@12: \caption{Modifying the stack of applied patches} bos@12: \label{ex:mq:qpop} bos@11: \end{figure} bos@11: bos@27: \subsection{Pushing and popping many patches} bos@27: bos@27: While \hgcmd{qpush} and \hgcmd{qpop} each operate on a single patch at bos@27: a time by default, you can push and pop many patches in one go. The bos@27: \hgopt{qpush}{-a} option to \hgcmd{qpush} causes it to push all bos@27: unapplied patches, while the \hgopt{qpop}{-a} option to \hgcmd{qpop} bos@27: causes it to pop all applied patches. (For some more ways to push and bos@27: pop many patches, see section~\ref{sec:mq:perf} below.) bos@27: bos@27: \begin{figure}[ht] bos@27: \interaction{mq.tutorial.qpush-a} bos@27: \caption{Pushing all unapplied patches} bos@27: \label{ex:mq:qpush-a} bos@27: \end{figure} bos@27: bos@27: \subsection{Safety checks, and overriding them} bos@27: bos@27: Several MQ commands check the working directory before they do bos@27: anything, and fail if they find any modifications. They do this to bos@27: ensure that you won't lose any changes that you have made, but not yet bos@27: incorporated into a patch. Figure~\ref{ex:mq:add} illustrates this; bos@27: the \hgcmd{qnew} command will not create a new patch if there are bos@27: outstanding changes, caused in this case by the \hgcmd{add} of bos@27: \filename{file3}. bos@27: bos@27: \begin{figure}[ht] bos@27: \interaction{mq.tutorial.add} bos@27: \caption{Forcibly creating a patch} bos@27: \label{ex:mq:add} bos@27: \end{figure} bos@27: bos@27: Commands that check the working directory all take an ``I know what bos@27: I'm doing'' option, which is always named \option{-f}. The exact bos@27: meaning of \option{-f} depends on the command. For example, bos@27: \hgcmdargs{qnew}{\hgopt{qnew}{-f}} will incorporate any outstanding bos@27: changes into the new patch it creates, but bos@27: \hgcmdargs{qpop}{\hgopt{qpop}{-f}} will revert modifications to any bos@27: files affected by the patch that it is popping. Be sure to read the bos@27: documentation for a command's \option{-f} option before you use it! bos@8: bos@13: \subsection{Working on several patches at once} bos@13: bos@13: The \hgcmd{qrefresh} command always refreshes the \emph{topmost} bos@13: applied patch. This means that you can suspend work on one patch (by bos@13: refreshing it), pop or push to make a different patch the top, and bos@13: work on \emph{that} patch for a while. bos@13: bos@13: Here's an example that illustrates how you can use this ability. bos@13: Let's say you're developing a new feature as two patches. The first bos@18: is a change to the core of your software, and the second---layered on bos@18: top of the first---changes the user interface to use the code you just bos@13: added to the core. If you notice a bug in the core while you're bos@13: working on the UI patch, it's easy to fix the core. Simply bos@13: \hgcmd{qrefresh} the UI patch to save your in-progress changes, and bos@13: \hgcmd{qpop} down to the core patch. Fix the core bug, bos@13: \hgcmd{qrefresh} the core patch, and \hgcmd{qpush} back to the UI bos@13: patch to continue where you left off. bos@13: bos@19: \section{More about patches} bos@19: \label{sec:mq:adv-patch} bos@19: bos@19: MQ uses the GNU \command{patch} command to apply patches, so it's bos@26: helpful to know a few more detailed aspects of how \command{patch} bos@26: works, and about patches themselves. bos@26: bos@26: \subsection{The strip count} bos@26: bos@26: If you look at the file headers in a patch, you will notice that the bos@26: pathnames usually have an extra component on the front that isn't bos@26: present in the actual path name. This is a holdover from the way that bos@26: people used to generate patches (people still do this, but it's bos@26: somewhat rare with modern revision control tools). bos@26: bos@26: Alice would unpack a tarball, edit her files, then decide that she bos@26: wanted to create a patch. So she'd rename her working directory, bos@26: unpack the tarball again (hence the need for the rename), and use the bos@26: \cmdopt{diff}{-r} and \cmdopt{diff}{-N} options to \command{diff} to bos@26: recursively generate a patch between the unmodified directory and the bos@26: modified one. The result would be that the name of the unmodified bos@26: directory would be at the front of the left-hand path in every file bos@26: header, and the name of the modified directory would be at the front bos@26: of the right-hand path. bos@26: bos@26: Since someone receiving a patch from the Alices of the net would be bos@26: unlikely to have unmodified and modified directories with exactly the bos@26: same names, the \command{patch} command has a \cmdopt{patch}{-p} bos@26: option that indicates the number of leading path name components to bos@26: strip when trying to apply a patch. This number is called the bos@26: \emph{strip count}. bos@26: bos@26: An option of ``\texttt{-p1}'' means ``use a strip count of one''. If bos@26: \command{patch} sees a file name \filename{foo/bar/baz} in a file bos@26: header, it will strip \filename{foo} and try to patch a file named bos@26: \filename{bar/baz}. (Strictly speaking, the strip count refers to the bos@26: number of \emph{path separators} (and the components that go with them bos@26: ) to strip. A strip count of one will turn \filename{foo/bar} into bos@26: \filename{bar}, but \filename{/foo/bar} (notice the extra leading bos@26: slash) into \filename{foo/bar}.) bos@26: bos@26: The ``standard'' strip count for patches is one; almost all patches bos@26: contain one leading path name component that needs to be stripped. bos@26: Mercurial's \hgcmd{diff} command generates path names in this form, bos@26: and the \hgcmd{import} command and MQ expect patches to have a strip bos@26: count of one. bos@26: bos@26: If you receive a patch from someone that you want to add to your patch bos@26: queue, and the patch needs a strip count other than one, you cannot bos@26: just \hgcmd{qimport} the patch, because \hgcmd{qimport} does not yet bos@26: have a \texttt{-p} option (see~\bug{311}). Your best bet is to bos@26: \hgcmd{qnew} a patch of your own, then use \cmdargs{patch}{-p\emph{N}} bos@26: to apply their patch, followed by \hgcmd{addremove} to pick up any bos@26: files added or removed by the patch, followed by \hgcmd{qrefresh}. bos@26: This complexity may become unnecessary; see~\bug{311} for details. bos@26: \subsection{Strategies for applying a patch} bos@14: bos@14: When \command{patch} applies a hunk, it tries a handful of bos@14: successively less accurate strategies to try to make the hunk apply. bos@14: This falling-back technique often makes it possible to take a patch bos@14: that was generated against an old version of a file, and apply it bos@14: against a newer version of that file. bos@14: bos@14: First, \command{patch} tries an exact match, where the line numbers, bos@14: the context, and the text to be modified must apply exactly. If it bos@14: cannot make an exact match, it tries to find an exact match for the bos@14: context, without honouring the line numbering information. If this bos@14: succeeds, it prints a line of output saying that the hunk was applied, bos@14: but at some \emph{offset} from the original line number. bos@14: bos@14: If a context-only match fails, \command{patch} removes the first and bos@14: last lines of the context, and tries a \emph{reduced} context-only bos@14: match. If the hunk with reduced context succeeds, it prints a message bos@14: saying that it applied the hunk with a \emph{fuzz factor} (the number bos@14: after the fuzz factor indicates how many lines of context bos@14: \command{patch} had to trim before the patch applied). bos@14: bos@14: When neither of these techniques works, \command{patch} prints a bos@14: message saying that the hunk in question was rejected. It saves bos@17: rejected hunks (also simply called ``rejects'') to a file with the bos@17: same name, and an added \sfilename{.rej} extension. It also saves an bos@17: unmodified copy of the file with a \sfilename{.orig} extension; the bos@17: copy of the file without any extensions will contain any changes made bos@17: by hunks that \emph{did} apply cleanly. If you have a patch that bos@17: modifies \filename{foo} with six hunks, and one of them fails to bos@17: apply, you will have: an unmodified \filename{foo.orig}, a bos@17: \filename{foo.rej} containing one hunk, and \filename{foo}, containing bos@17: the changes made by the five successful five hunks. bos@14: bos@25: \subsection{Some quirks of patch representation} bos@25: bos@25: There are a few useful things to know about how \command{patch} works bos@25: with files. bos@25: \begin{itemize} bos@25: \item This should already be obvious, but \command{patch} cannot bos@25: handle binary files. bos@25: \item Neither does it care about the executable bit; it creates new bos@25: files as readable, but not executable. bos@25: \item \command{patch} treats the removal of a file as a diff between bos@25: the file to be removed and the empty file. So your idea of ``I bos@25: deleted this file'' looks like ``every line of this file was bos@25: deleted'' in a patch. bos@25: \item It treats the addition of a file as a diff between the empty bos@25: file and the file to be added. So in a patch, your idea of ``I bos@25: added this file'' looks like ``every line of this file was added''. bos@25: \item It treats a renamed file as the removal of the old name, and the bos@25: addition of the new name. This means that renamed files have a big bos@25: footprint in patches. (Note also that Mercurial does not currently bos@25: try to infer when files have been renamed or copied in a patch.) bos@25: \item \command{patch} cannot represent empty files, so you cannot use bos@25: a patch to represent the notion ``I added this empty file to the bos@25: tree''. bos@25: \end{itemize} bos@14: \subsection{Beware the fuzz} bos@14: bos@14: While applying a hunk at an offset, or with a fuzz factor, will often bos@14: be completely successful, these inexact techniques naturally leave bos@14: open the possibility of corrupting the patched file. The most common bos@14: cases typically involve applying a patch twice, or at an incorrect bos@14: location in the file. If \command{patch} or \hgcmd{qpush} ever bos@14: mentions an offset or fuzz factor, you should make sure that the bos@14: modified files are correct afterwards. bos@14: bos@14: It's often a good idea to refresh a patch that has applied with an bos@14: offset or fuzz factor; refreshing the patch generates new context bos@14: information that will make it apply cleanly. I say ``often,'' not bos@14: ``always,'' because sometimes refreshing a patch will make it fail to bos@14: apply against a different revision of the underlying files. In some bos@14: cases, such as when you're maintaining a patch that must sit on top of bos@14: multiple versions of a source tree, it's acceptable to have a patch bos@14: apply with some fuzz, provided you've verified the results of the bos@14: patching process in such cases. bos@14: bos@15: \subsection{Handling rejection} bos@15: bos@15: If \hgcmd{qpush} fails to apply a patch, it will print an error bos@16: message and exit. If it has left \sfilename{.rej} files behind, it is bos@15: usually best to fix up the rejected hunks before you push more patches bos@15: or do any further work. bos@15: bos@15: If your patch \emph{used to} apply cleanly, and no longer does because bos@15: you've changed the underlying code that your patches are based on, bos@17: Mercurial Queues can help; see section~\ref{sec:mq:merge} for details. bos@15: bos@15: Unfortunately, there aren't any great techniques for dealing with bos@16: rejected hunks. Most often, you'll need to view the \sfilename{.rej} bos@15: file and edit the target file, applying the rejected hunks by hand. bos@15: bos@16: If you're feeling adventurous, Neil Brown, a Linux kernel hacker, bos@16: wrote a tool called \command{wiggle}~\cite{web:wiggle}, which is more bos@16: vigorous than \command{patch} in its attempts to make a patch apply. bos@15: bos@15: Another Linux kernel hacker, Chris Mason (the author of Mercurial bos@15: Queues), wrote a similar tool called \command{rej}~\cite{web:rej}, bos@15: which takes a simple approach to automating the application of hunks bos@15: rejected by \command{patch}. \command{rej} can help with four common bos@15: reasons that a hunk may be rejected: bos@15: bos@15: \begin{itemize} bos@15: \item The context in the middle of a hunk has changed. bos@15: \item A hunk is missing some context at the beginning or end. bos@18: \item A large hunk might apply better---either entirely or in bos@18: part---if it was broken up into smaller hunks. bos@15: \item A hunk removes lines with slightly different content than those bos@15: currently present in the file. bos@15: \end{itemize} bos@15: bos@15: If you use \command{wiggle} or \command{rej}, you should be doubly bos@15: careful to check your results when you're done. bos@15: bos@17: \section{Getting the best performance out of MQ} bos@27: \label{sec:mq:perf} bos@17: bos@17: MQ is very efficient at handling a large number of patches. I ran bos@17: some performance experiments in mid-2006 for a talk that I gave at the bos@17: 2006 EuroPython conference~\cite{web:europython}. I used as my data bos@17: set the Linux 2.6.17-mm1 patch series, which consists of 1,738 bos@17: patches. I applied thes on top of a Linux kernel repository bos@17: containing all 27,472 revisions between Linux 2.6.12-rc2 and Linux bos@17: 2.6.17. bos@17: bos@17: On my old, slow laptop, I was able to bos@17: \hgcmdargs{qpush}{\hgopt{qpush}{-a}} all 1,738 patches in 3.5 minutes, bos@17: and \hgcmdargs{qpop}{\hgopt{qpop}{-a}} them all in 30 seconds. I bos@17: could \hgcmd{qrefresh} one of the biggest patches (which made 22,779 bos@17: lines of changes to 287 files) in 6.6 seconds. bos@17: bos@17: Clearly, MQ is well suited to working in large trees, but there are a bos@17: few tricks you can use to get the best performance of it. bos@17: bos@17: First of all, try to ``batch'' operations together. Every time you bos@17: run \hgcmd{qpush} or \hgcmd{qpop}, these commands scan the working bos@17: directory once to make sure you haven't made some changes and then bos@17: forgotten to run \hgcmd{qrefresh}. On a small tree, the time that bos@17: this scan takes is unnoticeable. However, on a medium-sized tree bos@17: (containing tens of thousands of files), it can take a second or more. bos@17: bos@17: The \hgcmd{qpush} and \hgcmd{qpop} commands allow you to push and pop bos@17: multiple patches at a time. You can identify the ``destination bos@17: patch'' that you want to end up at. When you \hgcmd{qpush} with a bos@17: destination specified, it will push patches until that patch is at the bos@17: top of the applied stack. When you \hgcmd{qpop} to a destination, MQ bos@17: will pop patches until the destination patch \emph{is no longer} bos@17: applied. bos@17: bos@17: You can identify a destination patch using either the name of the bos@17: patch, or by number. If you use numeric addressing, patches are bos@17: counted from zero; this means that the first patch is zero, the second bos@17: is one, and so on. bos@17: bos@15: \section{Updating your patches when the underlying code changes} bos@15: \label{sec:mq:merge} bos@15: bos@17: It's common to have a stack of patches on top of an underlying bos@17: repository that you don't modify directly. If you're working on bos@17: changes to third-party code, or on a feature that is taking longer to bos@17: develop than the rate of change of the code beneath, you will often bos@17: need to sync up with the underlying code, and fix up any hunks in your bos@17: patches that no longer apply. This is called \emph{rebasing} your bos@17: patch series. bos@17: bos@17: The simplest way to do this is to \hgcmdargs{qpop}{\hgopt{qpop}{-a}} bos@17: your patches, then \hgcmd{pull} changes into the underlying bos@17: repository, and finally \hgcmdargs{qpush}{\hgopt{qpop}{-a}} your bos@17: patches again. MQ will stop pushing any time it runs across a patch bos@17: that fails to apply during conflicts, allowing you to fix your bos@17: conflicts, \hgcmd{qrefresh} the affected patch, and continue pushing bos@17: until you have fixed your entire stack. bos@17: bos@17: This approach is easy to use and works well if you don't expect bos@17: changes to the underlying code to affect how well your patches apply. bos@17: If your patch stack touches code that is modified frequently or bos@17: invasively in the underlying repository, however, fixing up rejected bos@17: hunks by hand quickly becomes tiresome. bos@17: bos@17: It's possible to partially automate the rebasing process. If your bos@17: patches apply cleanly against some revision of the underlying repo, MQ bos@17: can use this information to help you to resolve conflicts between your bos@17: patches and a different revision. bos@17: bos@17: The process is a little involved. bos@17: \begin{enumerate} bos@17: \item To begin, \hgcmdargs{qpush}{-a} all of your patches on top of bos@17: the revision where you know that they apply cleanly. bos@17: \item Save a backup copy of your patch directory using bos@17: \hgcmdargs{qsave}{\hgopt{qsave}{-e} \hgopt{qsave}{-c}}. This prints bos@17: the name of the directory that it has saved the patches in. It will bos@17: save the patches to a directory called bos@17: \sdirname{.hg/patches.\emph{N}}, where \texttt{\emph{N}} is a small bos@17: integer. It also commits a ``save changeset'' on top of your bos@17: applied patches; this is for internal book-keeping, and records the bos@17: states of the \sfilename{series} and \sfilename{status} files. bos@17: \item Use \hgcmd{pull} to bring new changes into the underlying bos@17: repository. (Don't run \hgcmdargs{pull}{-u}; see below for why.) bos@17: \item Update to the new tip revision, using bos@17: \hgcmdargs{update}{\hgopt{update}{-C}} to override the patches you bos@17: have pushed. bos@17: \item Merge all patches using \hgcmdargs{qpush}{\hgopt{qpush}{-m} bos@17: \hgopt{qpush}{-a}}. The \hgopt{qpush}{-m} option to \hgcmd{qpush} bos@17: tells MQ to perform a three-way merge if the patch fails to apply. bos@17: \end{enumerate} bos@17: bos@17: During the \hgcmdargs{qpush}{\hgopt{qpush}{-m}}, each patch in the bos@17: \sfilename{series} file is applied normally. If a patch applies with bos@17: fuzz or rejects, MQ looks at the queue you \hgcmd{qsave}d, and bos@17: performs a three-way merge with the corresponding changeset. This bos@17: merge uses Mercurial's normal merge machinery, so it may pop up a GUI bos@17: merge tool to help you to resolve problems. bos@17: bos@17: When you finish resolving the effects of a patch, MQ refreshes your bos@17: patch based on the result of the merge. bos@17: bos@17: At the end of this process, your repository will have one extra head bos@17: from the old patch queue, and a copy of the old patch queue will be in bos@17: \sdirname{.hg/patches.\emph{N}}. You can remove the extra head using bos@17: \hgcmdargs{qpop}{\hgopt{qpop}{-a} \hgopt{qpop}{-n} patches.\emph{N}} bos@17: or \hgcmd{strip}. You can delete \sdirname{.hg/patches.\emph{N}} once bos@17: you are sure that you no longer need it as a backup. bos@13: bos@26: \section{Useful things to know about} bos@26: bos@26: There are a number of aspects of MQ usage that don't fit tidily into bos@26: sections of their own, but that are good to know. Here they are, in bos@26: one place. bos@26: bos@26: \begin{itemize} bos@26: \item Normally, when you \hgcmd{qpop} a patch and \hgcmd{qpush} it bos@26: again, the changeset that represents the patch after the pop/push bos@26: will have a \emph{different identity} than the changeset that bos@26: represented the hash beforehand. See section~\ref{sec:mq:cmd:qpush} bos@26: for information as to why this is. bos@26: \item It's not a good idea to \hgcmd{merge} changes from another bos@26: branch with a patch changeset, at least if you want to maintain the bos@26: ``patchiness'' of that changeset and changesets below it on the bos@26: patch stack. If you try to do this, it will appear to succeed, but bos@26: MQ will become confused. bos@26: \end{itemize} bos@16: \section{Managing patches in a repository} bos@16: bos@16: Because MQ's \sdirname{.hg/patches} directory resides outside a bos@16: Mercurial repository's working directory, the ``underlying'' Mercurial bos@16: repository knows nothing about the management or presence of patches. bos@16: bos@16: This presents the interesting possibility of managing the contents of bos@16: the patch directory as a Mercurial repository in its own right. This bos@16: can be a useful way to work. For example, you can work on a patch for bos@16: a while, \hgcmd{qrefresh} it, then \hgcmd{commit} the current state of bos@16: the patch. This lets you ``roll back'' to that version of the patch bos@16: later on. bos@16: bos@26: You can then share different versions of the same patch stack among bos@26: multiple underlying repositories. I use this when I am developing a bos@26: Linux kernel feature. I have a pristine copy of my kernel sources for bos@26: each of several CPU architectures, and a cloned repository under each bos@26: that contains the patches I am working on. When I want to test a bos@26: change on a different architecture, I push my current patches to the bos@26: patch repository associated with that kernel tree, pop and push all of bos@26: my patches, and build and test that kernel. bos@16: bos@16: Managing patches in a repository makes it possible for multiple bos@16: developers to work on the same patch series without colliding with bos@16: each other, all on top of an underlying source base that they may or bos@16: may not control. bos@16: bos@17: \subsection{MQ support for patch repositories} bos@16: bos@16: MQ helps you to work with the \sdirname{.hg/patches} directory as a bos@16: repository; when you prepare a repository for working with patches bos@17: using \hgcmd{qinit}, you can pass the \hgopt{qinit}{-c} option to bos@16: create the \sdirname{.hg/patches} directory as a Mercurial repository. bos@16: bos@16: \begin{note} bos@16: If you forget to use the \hgopt{qinit}{-c} option, you can simply go bos@16: into the \sdirname{.hg/patches} directory at any time and run bos@16: \hgcmd{init}. Don't forget to add an entry for the bos@17: \sfilename{status} file to the \sfilename{.hgignore} file, though bos@17: (\hgcmdargs{qinit}{\hgopt{qinit}{-c}} does this for you bos@17: automatically); you \emph{really} don't want to manage the bos@17: \sfilename{status} file. bos@16: \end{note} bos@16: bos@16: As a convenience, if MQ notices that the \dirname{.hg/patches} bos@16: directory is a repository, it will automatically \hgcmd{add} every bos@16: patch that you create and import. bos@16: bos@16: Finally, MQ provides a shortcut command, \hgcmd{qcommit}, that runs bos@16: \hgcmd{commit} in the \sdirname{.hg/patches} directory. This saves bos@16: some cumbersome typing. bos@16: bos@16: \subsection{A few things to watch out for} bos@16: bos@16: MQ's support for working with a repository full of patches is limited bos@16: in a few small respects. bos@16: bos@16: MQ cannot automatically detect changes that you make to the patch bos@16: directory. If you \hgcmd{pull}, manually edit, or \hgcmd{update} bos@16: changes to patches or the \sfilename{series} file, you will have to bos@17: \hgcmdargs{qpop}{\hgopt{qpop}{-a}} and then bos@17: \hgcmdargs{qpush}{\hgopt{qpush}{-a}} in the underlying repository to bos@17: see those changes show up there. If you forget to do this, you can bos@17: confuse MQ's idea of which patches are applied. bos@16: bos@26: \section{Third party tools for working with patches} bos@19: \label{sec:mq:tools} bos@16: bos@16: Once you've been working with patches for a while, you'll find bos@16: yourself hungry for tools that will help you to understand and bos@16: manipulate the patches you're dealing with. bos@16: bos@16: The \command{diffstat} command~\cite{web:diffstat} generates a bos@16: histogram of the modifications made to each file in a patch. It bos@18: provides a good way to ``get a sense of'' a patch---which files it bos@16: affects, and how much change it introduces to each file and as a bos@16: whole. (I find that it's a good idea to use \command{diffstat}'s bos@16: \texttt{-p} option as a matter of course, as otherwise it will try to bos@16: do clever things with prefixes of file names that inevitably confuse bos@16: at least me.) bos@16: bos@19: \begin{figure}[ht] bos@19: \interaction{mq.tools.tools} bos@19: \caption{The \command{diffstat}, \command{filterdiff}, and \command{lsdiff} commands} bos@19: \label{ex:mq:tools} bos@19: \end{figure} bos@19: bos@16: The \package{patchutils} package~\cite{web:patchutils} is invaluable. bos@16: It provides a set of small utilities that follow the ``Unix bos@16: philosophy;'' each does one useful thing with a patch. The bos@16: \package{patchutils} command I use most is \command{filterdiff}, which bos@16: extracts subsets from a patch file. For example, given a patch that bos@16: modifies hundreds of files across dozens of directories, a single bos@16: invocation of \command{filterdiff} can generate a smaller patch that bos@16: only touches files whose names match a particular glob pattern. bos@16: bos@19: \section{Good ways to work with patches} bos@19: bos@19: Whether you are working on a patch series to submit to a free software bos@19: or open source project, or a series that you intend to treat as a bos@19: sequence of regular changesets when you're done, you can use some bos@19: simple techniques to keep your work well organised. bos@19: bos@19: Give your patches descriptive names. A good name for a patch might be bos@19: \filename{rework-device-alloc.patch}, because it will immediately give bos@19: you a hint what the purpose of the patch is. Long names shouldn't be bos@19: a problem; you won't be typing the names often, but you \emph{will} be bos@19: running commands like \hgcmd{qapplied} and \hgcmd{qtop} over and over. bos@19: Good naming becomes especially important when you have a number of bos@19: patches to work with, or if you are juggling a number of different bos@19: tasks and your patches only get a fraction of your attention. bos@19: bos@19: Be aware of what patch you're working on. Use the \hgcmd{qtop} bos@19: command and skim over the text of your patches frequently---for bos@19: example, using \hgcmdargs{tip}{\hgopt{tip}{-p}})---to be sure of where bos@19: you stand. I have several times worked on and \hgcmd{qrefresh}ed a bos@19: patch other than the one I intended, and it's often tricky to migrate bos@19: changes into the right patch after making them in the wrong one. bos@19: bos@19: For this reason, it is very much worth investing a little time to bos@19: learn how to use some of the third-party tools I described in bos@19: section~\ref{sec:mq:tools}, particularly \command{diffstat} and bos@19: \command{filterdiff}. The former will give you a quick idea of what bos@19: changes your patch is making, while the latter makes it easy to splice bos@19: hunks selectively out of one patch and into another. bos@19: bos@19: \section{MQ cookbook} bos@19: bos@19: \subsection{Manage ``trivial'' patches} bos@19: bos@19: Because the overhead of dropping files into a new Mercurial repository bos@19: is so low, it makes a lot of sense to manage patches this way even if bos@19: you simply want to make a few changes to a source tarball that you bos@19: downloaded. bos@19: bos@19: Begin by downloading and unpacking the source tarball, bos@19: and turning it into a Mercurial repository. bos@19: \interaction{mq.tarball.download} bos@19: bos@19: Continue by creating a patch stack and making your changes. bos@19: \interaction{mq.tarball.qinit} bos@19: bos@19: Let's say a few weeks or months pass, and your package author releases bos@19: a new version. First, bring their changes into the repository. bos@19: \interaction{mq.tarball.newsource} bos@19: The pipeline starting with \hgcmd{locate} above deletes all files in bos@19: the working directory, so that \hgcmd{commit}'s bos@19: \hgopt{commit}{--addremove} option can actually tell which files have bos@19: really been removed in the newer version of the source. bos@19: bos@19: Finally, you can apply your patches on top of the new tree. bos@19: \interaction{mq.tarball.repush} bos@19: bos@19: \subsection{Combining entire patches} bos@19: \label{sec:mq:combine} bos@19: bos@19: It's easy to combine entire patches. bos@19: bos@19: \begin{enumerate} bos@19: \item \hgcmd{qpop} your applied patches until neither patch is bos@19: applied. bos@19: \item Concatenate the patches that you want to combine together: bos@19: \begin{codesample4} bos@19: cat patch-to-drop.patch >> patch-to-augment.patch bos@19: \end{codesample4} bos@19: The description from the first patch (if you have one) will be used bos@19: as the commit comment when you \hgcmd{qpush} the combined patch. bos@19: Edit the patch description if you need to. bos@19: \item Use the \hgcmd{qdel} command to delete the patch you're dropping bos@19: from the \sfilename{series} file. bos@19: \item \hgcmd{qpush} the combined patch. Fix up any rejects. bos@19: \item \hgcmd{qrefresh} the combined patch to tidy it up. bos@19: \end{enumerate} bos@19: bos@19: \subsection{Merging part of one patch into another} bos@19: bos@19: Merging \emph{part} of one patch into another is more difficult than bos@19: combining entire patches. bos@19: bos@19: If you want to move changes to entire files, you can use bos@19: \command{filterdiff}'s \cmdopt{filterdiff}{-i} and bos@19: \cmdopt{filterdiff}{-x} options to choose the modifications to snip bos@19: out of one patch, concatenating its output onto the end of the patch bos@19: you want to merge into. You usually won't need to modify the patch bos@19: you've merged the changes from. Instead, MQ will report some rejected bos@19: hunks when you \hgcmd{qpush} it (from the hunks you moved into the bos@19: other patch), and you can simply \hgcmd{qrefresh} the patch to drop bos@19: the duplicate hunks. bos@19: bos@19: If you have a patch that has multiple hunks modifying a file, and you bos@19: only want to move a few of those hunks, the job becomes more messy, bos@19: but you can still partly automate it. Use \cmdargs{lsdiff}{-nvv} to bos@19: print some metadata about the patch. bos@19: \interaction{mq.tools.lsdiff} bos@19: bos@19: This command prints three different kinds of number: bos@19: \begin{itemize} bos@26: \item (in the first column) a \emph{file number} to identify each file bos@26: modified in the patch; bos@26: \item (on the next line, indented) the line number within a modified bos@26: file where a hunk starts; and bos@26: \item (on the same line) a \emph{hunk number} to identify that hunk. bos@19: \end{itemize} bos@19: bos@19: You'll have to use some visual inspection, and reading of the patch, bos@19: to identify the file and hunk numbers you'll want, but you can then bos@19: pass them to to \command{filterdiff}'s \cmdopt{filterdiff}{--files} bos@19: and \cmdopt{filterdiff}{--hunks} options, to select exactly the file bos@19: and hunk you want to extract. bos@19: bos@19: Once you have this hunk, you can concatenate it onto the end of your bos@19: destination patch and continue with the remainder of bos@19: section~\ref{sec:mq:combine}. bos@26: bos@26: \section{Differences between quilt and MQ} bos@26: bos@26: If you are already familiar with quilt, MQ provides a similar command bos@26: set. There are a few differences in the way that it works. bos@26: bos@26: You will already have noticed that most quilt commands have MQ bos@26: counterparts that simply begin with a ``\texttt{q}''. The exceptions bos@26: are quilt's \texttt{add} and \texttt{remove} commands, the bos@26: counterparts for which are the normal Mercurial \hgcmd{add} and bos@26: \hgcmd{remove} commands. There is no MQ equivalent of the quilt bos@26: \texttt{edit} command. bos@25: \section{MQ command reference} bos@25: \label{sec:mq:cmdref} bos@25: bos@25: For an overview of the commands provided by MQ, use the command bos@25: \hgcmdargs{help}{mq}. bos@25: bos@25: \subsection{\hgcmd{qapplied}---print applied patches} bos@25: bos@25: The \hgcmd{qapplied} command prints the current stack of applied bos@25: patches. Patches are printed in oldest-to-newest order, so the last bos@25: patch in the list is the ``top'' patch. bos@25: bos@25: \subsection{\hgcmd{qcommit}---commit changes in the queue repository} bos@25: bos@25: The \hgcmd{qcommit} command commits any outstanding changes in the bos@25: \sdirname{.hg/patches} repository. This command only works if the bos@25: \sdirname{.hg/patches} directory is a repository, i.e.~you created the bos@25: directory using \hgcmdargs{qinit}{\hgopt{qinit}{-c}} or ran bos@25: \hgcmd{init} in the directory after running \hgcmd{qinit}. bos@25: bos@25: This command is shorthand for \hgcmdargs{commit}{--cwd .hg/patches}. bos@25: bos@25: \subsection{\hgcmd{qdelete}---delete a patch from the bos@25: \sfilename{series} file} bos@25: bos@25: The \hgcmd{qdelete} command removes the entry for a patch from the bos@25: \sfilename{series} file in the \sdirname{.hg/patches} directory. It bos@25: does not delete the patch file, nor does it pop the patch if the patch bos@25: is already applied. bos@25: bos@25: \subsection{\hgcmd{qdiff}---print a diff of the topmost applied patch} bos@25: bos@25: The \hgcmd{qdiff} command prints a diff of the topmost applied patch. bos@25: It is equivalent to \hgcmdargs{diff}{-r-2:-1}. bos@25: bos@25: \subsection{\hgcmd{qimport}---import a third-party patch into the queue} bos@25: bos@25: The \hgcmd{qimport} command adds an entry for an external patch to the bos@25: \sfilename{series} file, and copies the patch into the bos@25: \sdirname{.hg/patches} directory. It adds the entry immediately after bos@25: the topmost applied patch, but does not push the patch. bos@25: bos@25: If the \sdirname{.hg/patches} directory is a repository, bos@25: \hgcmd{qimport} automatically does an \hgcmd{add} of the imported bos@25: patch. bos@25: bos@25: \subsection{\hgcmd{qinit}---prepare a repository to work with MQ} bos@25: bos@25: The \hgcmd{qinit} command prepares a repository to work with MQ. It bos@25: creates a directory called \sdirname{.hg/patches}. bos@25: bos@25: Options: bos@25: \begin{itemize} bos@25: \item[\hgopt{qinit}{-c}] Create \sdirname{.hg/patches} as a repository bos@25: in its own right. Also creates a \sfilename{.hgignore} file that bos@25: will ignore the \sfilename{status} file. bos@25: \end{itemize} bos@25: bos@25: When the \sdirname{.hg/patches} directory is a repository, the bos@25: \hgcmd{qimport} and \hgcmd{qnew} commands automatically \hgcmd{add} bos@25: new patches. bos@25: bos@25: \subsection{\hgcmd{qnew}---create a new patch} bos@25: bos@25: The \hgcmd{qnew} command creates a new patch. It takes one mandatory bos@25: argument, the name to use for the patch file. The newly created patch bos@25: is created empty by default. It is added to the \sfilename{series} bos@25: file after the current topmost applied patch, and is immediately bos@25: pushed on top of that patch. bos@25: bos@25: If \hgcmd{qnew} finds modified files in the working directory, it will bos@25: refuse to create a new patch unless the \hgopt{qnew}{-f} option is bos@25: used (see below). This behaviour allows you to \hgcmd{qrefresh} your bos@25: topmost applied patch before you apply a new patch on top of it. bos@25: bos@25: Options: bos@25: \begin{itemize} bos@25: \item[\hgopt{qnew}{-f}] Create a new patch if the contents of the bos@25: working directory are modified. Any outstanding modifications are bos@25: added to the newly created patch, so after this command completes, bos@25: the working directory will no longer be modified. bos@25: \item[\hgopt{qnew}{-m}] Use the given text as the commit message. bos@25: This text will be stored at the beginning of the patch file, before bos@25: the patch data. bos@25: \end{itemize} bos@25: bos@25: \subsection{\hgcmd{qnext}---print the name of the next patch} bos@25: bos@25: The \hgcmd{qnext} command prints the name name of the next patch in bos@25: the \sfilename{series} file after the topmost applied patch. This bos@25: patch will become the topmost applied patch if you run \hgcmd{qpush}. bos@25: bos@25: \subsection{\hgcmd{qpop}---pop patches off the stack} bos@25: bos@25: The \hgcmd{qpop} command removes applied patches from the top of the bos@25: stack of applied patches. By default, it removes only one patch. bos@25: bos@25: This command removes the changesets that represent the popped patches bos@25: from the repository, and updates the working directory to undo the bos@25: effects of the patches. bos@25: bos@25: This command takes an optional argument, which it uses as the name or bos@25: index of the patch to pop to. If given a name, it will pop patches bos@25: until the named patch is no longer applied. If given a number, bos@25: \hgcmd{qpop} treats the number as an index into the entries in the bos@25: series file, counting from zero (empty lines and lines containing only bos@25: comments do not count). It pops patches until the patch identified by bos@25: the given index is no longer applied. bos@25: bos@25: The \hgcmd{qpop} command does not read or write patches or the bos@25: \sfilename{series} file. It is thus safe to \hgcmd{qpop} a patch that bos@25: you have removed from the \sfilename{series} file, or a patch that you bos@25: have renamed or deleted entirely. In the latter two cases, use the bos@25: name of the patch as it was when you applied it. bos@25: bos@25: By default, the \hgcmd{qpop} command will not pop any patches if the bos@25: working directory has been modified. You can override this behaviour bos@25: using the \hgopt{qpop}{-f} option, which reverts all modifications in bos@25: the working directory. bos@25: bos@25: Options: bos@25: \begin{itemize} bos@25: \item[\hgopt{qpop}{-a}] Pop all applied patches. This returns the bos@25: repository to its state before you applied any patches. bos@25: \item[\hgopt{qpop}{-f}] Forcibly revert any modifications to the bos@25: working directory when popping. bos@25: \item[\hgopt{qpop}{-n}] Pop a patch from the named queue. bos@25: \end{itemize} bos@25: bos@25: The \hgcmd{qpop} command removes one line from the end of the bos@25: \sfilename{status} file for each patch that it pops. bos@25: \subsection{\hgcmd{qprev}---print the name of the previous patch} bos@25: bos@25: The \hgcmd{qprev} command prints the name of the patch in the bos@25: \sfilename{series} file that comes before the topmost applied patch. bos@25: This will become the topmost applied patch if you run \hgcmd{qpop}. bos@25: bos@25: \subsection{\hgcmd{qpush}---push patches onto the stack} bos@26: \label{sec:mq:cmd:qpush} bos@25: bos@25: The \hgcmd{qpush} command adds patches onto the applied stack. By bos@25: default, it adds only one patch. bos@25: bos@25: This command creates a new changeset to represent each applied patch, bos@25: and updates the working directory to apply the effects of the patches. bos@25: bos@26: The default data used when creating a changeset are as follows: bos@25: \begin{itemize} bos@25: \item The commit date and time zone are the current date and time bos@25: zone. Because these data are used to compute the identity of a bos@25: changeset, this means that if you \hgcmd{qpop} a patch and bos@25: \hgcmd{qpush} it again, the changeset that you push will have a bos@25: different identity than the changeset you popped. bos@25: \item The author is the same as the default used by the \hgcmd{commit} bos@25: command. bos@25: \item The commit message is any text from the patch file that comes bos@25: before the first diff header. If there is no such text, a default bos@25: commit message is used that identifies the name of the patch. bos@25: \end{itemize} bos@26: If a patch contains a Mercurial patch header (XXX add link), the bos@26: information in the patch header overrides these defaults. bos@25: bos@25: Options: bos@25: \begin{itemize} bos@25: \item[\hgopt{qpush}{-a}] Push all unapplied patches from the bos@25: \sfilename{series} file until there are none left to push. bos@25: \item[\hgopt{qpush}{-l}] Add the name of the patch to the end bos@25: of the commit message. bos@25: \item[\hgopt{qpush}{-m}] If a patch fails to apply cleanly, use the bos@25: entry for the patch in another saved queue to compute the parameters bos@25: for a three-way merge, and perform a three-way merge using the bos@25: normal Mercurial merge machinery. Use the resolution of the merge bos@25: as the new patch content. bos@25: \item[\hgopt{qpush}{-n}] Use the named queue if merging while pushing. bos@25: \end{itemize} bos@25: bos@25: The \hgcmd{qpush} command reads, but does not modify, the bos@25: \sfilename{series} file. It appends one line to the \hgcmd{status} bos@25: file for each patch that it pushes. bos@25: bos@25: \subsection{\hgcmd{qrefresh}---update the topmost applied patch} bos@25: bos@25: The \hgcmd{qrefresh} command updates the topmost applied patch. It bos@25: modifies the patch, removes the old changeset that represented the bos@25: patch, and creates a new changeset to represent the modified patch. bos@25: bos@25: The \hgcmd{qrefresh} command looks for the following modifications: bos@25: \begin{itemize} bos@25: \item Changes to the commit message, i.e.~the text before the first bos@25: diff header in the patch file, are reflected in the new changeset bos@25: that represents the patch. bos@25: \item Modifications to tracked files in the working directory are bos@25: added to the patch. bos@25: \item Changes to the files tracked using \hgcmd{add}, \hgcmd{copy}, bos@25: \hgcmd{remove}, or \hgcmd{rename}. Added files and copy and rename bos@25: destinations are added to the patch, while removed files and rename bos@25: sources are removed. bos@25: \end{itemize} bos@25: bos@25: Even if \hgcmd{qrefresh} detects no changes, it still recreates the bos@25: changeset that represents the patch. This causes the identity of the bos@25: changeset to differ from the previous changeset that identified the bos@25: patch. bos@25: bos@26: \subsection{\hgcmd{qrestore}---restore saved queue state} bos@26: bos@26: XXX No idea what this does. bos@26: bos@26: \subsection{\hgcmd{qsave}---save current queue state} bos@26: bos@26: XXX Likewise. bos@26: bos@26: \subsection{\hgcmd{qseries}---print the entire patch series} bos@26: bos@26: The \hgcmd{qseries} command prints the entire patch series from the bos@26: \sfilename{series} file. It prints only patch names, not empty lines bos@26: or comments. It prints in order from first to be applied to last. bos@26: bos@26: \subsection{\hgcmd{qtop}---print the name of the current patch} bos@26: bos@26: The \hgcmd{qtop} prints the name of the topmost currently applied bos@26: patch. bos@26: bos@26: \subsection{\hgcmd{qunapplied}---print patches not yet applied} bos@26: bos@26: The \hgcmd{qunapplied} command prints the names of patches from the bos@26: \sfilename{series} file that are not yet applied. It prints them in bos@26: order from the next patch that will be pushed to the last. bos@26: bos@26: \subsection{\hgcmd{qversion}} bos@26: bos@26: The \hgcmd{qversion} command prints the version of MQ that is in use. bos@26: bos@26: \subsection{\hgcmd{strip}---remove a revision and descendants} bos@26: bos@26: The \hgcmd{strip} command removes a revision, and all of its bos@26: descendants, from the repository. It undoes the effects of the bos@26: removed revisions from the repository, and updates the working bos@26: directory to the first parent of the removed revision. bos@26: bos@26: The \hgcmd{strip} command saves a backup of the removed changesets in bos@26: a bundle, so that they can be reapplied if removed in error. bos@26: bos@26: Options: bos@26: \begin{itemize} bos@26: \item[\hgopt{strip}{-b}] Save unrelated changesets that are intermixed bos@26: with the stripped changesets in the backup bundle. bos@26: \item[\hgopt{strip}{-f}] If a branch has multiple heads, remove all bos@26: heads. XXX This should be renamed, and use \texttt{-f} to strip revs bos@26: when there are pending changes. bos@26: \item[\hgopt{strip}{-n}] Do not save a backup bundle. bos@26: \end{itemize} bos@25: \section{MQ file reference} bos@25: bos@25: bos@25: \subsection{The \sfilename{series} file} bos@25: bos@26: The \sfilename{series} file contains a list of the names of all bos@26: patches that MQ can apply. It is represented as a list of names, with bos@26: one name saved per line. Leading and trailing white space in each bos@26: line are ignored. bos@26: bos@26: Lines may contain comments. A comment begins with the ``\texttt{\#}'' bos@26: character, and extends to the end of the line. Empty lines, and lines bos@26: that contain only comments, are ignored. bos@26: bos@26: You will often need to edit the \sfilename{series} file by hand, hence bos@26: the support for comments and empty lines noted above. For example, bos@26: you can comment out a patch temporarily, and \hgcmd{qpush} will skip bos@26: over that patch when applying patches. You can also change the order bos@26: in which patches are applied by reordering their entries in the bos@26: \sfilename{series} file. bos@26: bos@26: Placing the \sfilename{series} file under revision control is also bos@26: supported; it is a good idea to place all of the patches that it bos@26: refers to under revision control, as well. If you create a patch bos@26: directory using the \hgopt{qinit}{-c} option to \hgcmd{qinit}, this bos@26: will be done for you automatically. bos@25: \subsection{The \sfilename{status} file} bos@25: bos@26: The \sfilename{status} file contains the names and changeset hashes of bos@26: all patches that MQ currently has applied. Unlike the bos@26: \sfilename{series} file, this file is not intended for editing. You bos@26: should not place this file under revision control, or modify it in any bos@26: way. It is used by MQ strictly for internal book-keeping. bos@19: bos@1: %%% Local Variables: bos@1: %%% mode: latex bos@1: %%% TeX-master: "00book" bos@1: %%% End: