<> = Merging Modified Patches = == The problem == Using MqExtension one can edit patches in any order. If some patch is modified (edit files, {{{hg qrefresh}}}), the change may conflict with patches that apply on top of this patch. When this happens, {{{hg qpush}}} complains, and creates {{{.rej}}} reject files. The conflict then has to be resolved manually, using editor, and the patch that conflicted can be refreshed using {{{hg qrefresh}}}. This process may have to be repeated if more patches apply on top and cause conflicts. Manual resolution of conflicts using {{{.rej}}} files is much less convenient than the usual Mercurial merge process. A different, though related, problem is when the changes in a patch conflict with previously applied patches, or with the base files. The solution provided here does not apply to that problem. == Solution == One can modify MqMerge procedure to apply it to conflicting patches and use the power of Mercurial merge process for resolving patch conflicts, and avoid {{{.rej}}} files. === Knowing in advance === If one knows in advance that edit of some patch would cause conflicts with patches applied on top of it, do the following: {{{ # Push all patches. hg qpush -a # Find out what is the qparent revision. hg log --template '{rev}:{node|short}\n' -r qparent # Take note of printed revision; note the treatment # of qparent = 000000000000 below. # Save the patch queue state. hg qsave -e -c # Take note of patches. # Go to revision before any patches are applied. # [TODO: can this step be skipped? If yes, hg log can be skipped too] hg update # Go to the patch you want to edit. hg qpush -m # Repeat until you reach the patch you want to edit, # or you could use hg qgoto . # Edit the files. # Reflect the changes in the patch. hg qrefresh # Push all patches, using hg to perform merges. hg qpush -m -a # Cleanup hg qpop -a hg qpop -a -n patches. rm -rf .hg/patches. }}} A somewhat special case occurs when the patch queue is applied atop a fresh repository (i.e., no commits to the working directory were made before applying the patch queue), meaning the {{{hg log}}} command will list the {{{qparent}}} as {{{-1:000000000000}}}. When performing the {{{hg update}}}, either use {{{hg update -r 000000000000}}} or {{{hg update -r null}}}; {{{hg update -r -1}}} will be interpreted as an alias for the tip and will actually not change the working directory. === Not knowing in advance === If you don't know in advance that patch edit will cause a conflict with subsequent patches (a common case) you can still use the above procedure, if you have somewhere a version of the patch before {{{hg qrefresh}}}. For example, if you use versioned patch queues (initialized with {{{hg qinit -c}}}) you could retrieve the old version from the patch repository. {{{ # Save the refreshed patch cp -i .hg/patches/mypatch ~/ # Restore the previous version of the patch. # For example: mq revert .hg/patches/mypatch # Pop all patches hg qpop -a }}} The above "restore" command assumes that versioned patches are used (see above), and that the changes to the patches haven't been committed yet, but the changes before the patch update have been committed. If all changes have been committed you can use {{{mq revert -r .hg/patches/mypatch}}}. Also, this assumes that a convenience alias was defined: {{{alias mq='hg -R $(hg root)/.hg/patches'}}}. In any case, the key is that you have to have the previous version of this patch somewhere, and you need to restore the patch in mq to that version (after saving the new version). Now, follow the above merge procedure until "Edit the files". Then: {{{ # Put back the modified patch into the patch queue cp ~/mypatch .hg/patches/ # Pop and push the make mq use this patch hg qpop hg qpush }}} Now, continue with the merge procedure starting with {{{hg qpush -m -a}}}.