I had the following plan to do this:
- suspend the dependent patches (those which depend on the patch
which I want to re-order or throw away).
- somehow unrecord the patch to re-order and save it somewhere else
(perhaps in another "darcs branch", i.e., a copy of the repo) and revert
the changes to the working directory so that the working directory is
clean.
- after that, unsuspend the suspended patches up to the state
where I want to insert the re-ordered patch. (Resolving all arising conflicts.)
- apply the saved patch (perhaps, by pulling from the saved "branch",
i.e., the copy of the darcs repo which I have saved on step 2).
- unsuspend all remaining patches. (Resolving all arising conflicts.)
Here are some notes on how all this has proceeded.
1. suspend the dependent patches
If among the patches dependent on the patch you want to re-order there
is a single "minimal" one (according to the graph of dependencies),
then you simply give the command to suspend it (and after that there
will be no "active" patches which would depend on the re-ordered
patch):
darcs suspend -h <MINIMAL-DEPENDENT-HASH>
(and confirm the suspension of all other dependent patches).
Of course, if there are several minimal dependent patches, you have to
suspend each (each's subgraph will be asked for suspension).
2. save and revert the unwanted changes
Preparation
First, I look at the changes I'm going to work with:
darcs diff -h 61fbb4aeac9e69cf30d232eda274c18194d7a8d9 --diff-command='emacs -f ediff-directories-with-ancestor-command %1 %2'
(The change was logically simple, but diff
showed it in a
complicated way, so, here, I launched Emacs's ediff via a special
function I had written for this purpose.)
I saw that the change included some cleanup and the addition of a new
feature. So, the plan is now to split it: unrecord the patch, and record two
patches instead.
darcs unrec -h 61fbb4aeac9e69cf30d232eda274c18194d7a8d9
Now, I can view and (perhaps, work) with the changes with ediff, too.
darcs diff --diff-command='emacs -f ediff-directories-with-ancestor-command %1 %2'
First, I record the cleanup patch (selecting and editing only the
relevant hunks). Then, the added action:
darcs rec -m 'examples/Process.hs: code cleanup (present as a sequence of actions and error handling)'
darcs rec -m 'examples/Process.hs: print the C program (from the AST) after the check (as gcc -E does)'
Saving as a patch (a variant)
One could use darcs obliterate -o
or -O
to save the obliterated
change, and then restore it with darcs apply
(according to that advice).
But I proceeded differently:
Saving as a branch (a variant)
Cloning didn't work for a repo with suspended patches:
~/TOOLS/prog/language-c $ darcs clone . ../language-c_printAST
darcs failed: Can't clone a repository with a rebase in progress
~/TOOLS/prog/language-c $
So, let's make a copy (and check whether we would be allowed to pull
from it):
~/TOOLS/prog/language-c $ cp -a ../language-c ../language-c_printAST
~/TOOLS/prog/language-c $ darcs pull ../language-c_printAST
darcs failed: Incompatibility with repository /home/imz/TOOLS/prog/language-c_printAST:
Cannot transfer patches from a repository where a rebase is in progress
~/TOOLS/prog/language-c $ cd ../language-c_printAST/
~/TOOLS/prog/language-c_printAST $ darcs rebase obliterate
<...>
Really obliterate all undecided patches? y
Rebase finished!
~/TOOLS/prog/language-c_printAST $ cd ../language-c
~/TOOLS/prog/language-c $ darcs pull ../language-c_printAST
HINT: if you want to change the default remote repository to
/home/imz/TOOLS/prog/language-c_printAST,
quit now and issue the same command with the --set-default flag.
No remote patches to pull in!
~/TOOLS/prog/language-c $
Ok, good, so we will pull from that repo later.
Revert the changes
Throw away the unwanted (or re-ordered) patch:
darcs obliterate
3. Unsuspend the patches that should come before it
It's a good idea to make a backup copy of the repo at this point, because you
might screw something up during the unsuspending and resolving conflicts.
Unsuspend the patches that should come before it. (Unfortunately,
external merge tool is not supported in unsuspend
.) It's better to
unsuspend them one by one as you'll have to resolve the conflicts
caused by each one and amend the patch:
darcs rebase unsuspend
# resolve conflicts
darcs amend
# repeat for the remaining patches you want to have
4. Apply the saved patch
darcs pull ../../language-c_printAST
# resolve conflicts
darcs amend
5. Unsuspend all remaining patches.
(Again, it's better to do this one by one.)
darcs rebase unsuspend
# resolve conflicts
darcs amend
# repeat for the remaining patches you want to have
(For some reason, on the first attempt, I lost a hunk in the last
unsuspended patch. But I repeated everything in a copy of the backup
copy, and there I reached the wished final state.)