Note:
This page appears to contain material that is no longer relevant. Please help improve this page by updating its content.
Merging Patches
The MqExtension can help you rebase your patches via three-way merging. This feature is still under active development, but the general usage will be updated here as things change.
The most common scenario is a patch queue against upstream revision A which you want to update to upstream revision B. The basic model is to fully apply your current patch queue on top of revision A, and then use those changesets for merging any patches that don't apply properly to the new upstream revision. Merging is only used when a patch applies with fuzz or rejects against the new base.
Example:
# check that there are no uncommitted (not qrefreshed) changes. # The steps below discard any such changes without any warning, at least in Mercurial 1.0.2 hg status # push all of your patches. This gives you changesets # in the hg repo to merge with. hg qpush -a # use hg qsave to make a copy of the patch directory # it prints the name of the backup directory used hg qsave -e -c # pull the new upstream revision. Do not use pull -u hg pull # update to the new upstream head. Do not use update -m hg update -C tip # use hg qpush -m to merge each patch hg qpush -m -a # after verifying the results, pop the old patch queue and # delete the backups. Since hg qpush -a -m created merge # sets, we need to get rid of them with hg qpop first # # patches.N was printed by hg qsave # hg qpop -a hg qpop -a -n patches.N rm -rf .hg/patches.N
Command Detail
hg qsave -e -c does three things. First it pushes a save changeset onto the top of your current queue. This records the state of the status and series file in the save changeset. It can be removed with qpop, qrestore or strip.
hg qsave -c will make a copy of the patch directory. By default this will be named .hg/patches.N, where N is an integer >= 1. if .hg/patches.1 already exists, .hg/patches.2 will be used, etc. hg qsave -c -n name will use .hg/name as the destination for the copy.
hg qsave -e will delete .hg/patches/status after creating the save changeset. This file holds information about which patches are applied, so deleting it makes it look as though the patch queue is empty.
hg qpush -m triggers a three-way merge if the patch fails to apply. A saved patch queue is used to find the changesets for merging. qpush defaults to the .hg/patches.N directory with the highest number when trying to find a saved patch queue. hg qpush -m -n name can be used to specify the name of the save directory.
During qpush -m, each patch in .hg/patches/series is applied normally. If there are fuzz or rejects, the save queue status file is checked for a patch with the same name. A three way merge is done with the corresponding changeset, and a new patch is generated based on the result. The resulting merge changeset is then stripped away and the new patch is applied in the current queue.
At the end of the process described above, your repository will have one extra head from the old patch queue, and a copy of the old patch queue will be in .hg/patches.N. The extra head can be removed with hg qpop -a -n patches.N or hg strip and you can delete .hg/patches.N when you no longer need it as a backup.
Questions
Why do we do hg qpush -a in the beginning, just to make sure the patches apply correctly before we do the merge?
- Only applied patches will be merged when updating. There is a status file in the patches directory that includes version information. This is used for the merge that takes place when the simple (internal) patch command fails during the qpush -m stage.
- This example assumes we don't version control the patches, right? If we do version control them, I'd expect the process to be simplified to:
# pull the new upstream revision hg pull # update to the new upstream head hg update -C tip # use hg qpush -m to merge each patch hg qpush -m -a -M "Merging with version X.Y.Z from upstream"
The -M <msg> would instruct hg qpush to checkin each merged patch with the given changelog message.
There doesn't seem to be -M option for hg qpush in Mercurial 1.0.
See Also
qrebase command based on this page described in email thread http://www.selenic.com/pipermail/mercurial/2008-May/019075.html , hosted at http://freehg.org/u/morisgi/qrebase/