In darcs, what if I want to re-order to the top (or just throw away) a patch which other patches depend on (i.e., change the same file)?
In git, I'd simply do a git rebase -i <UNTOUCHED-REVISION>
and reorder or throw away some changes; then git would in a dumb fashion try to apply the old changes to the new variant of the tree one by one, and ask me to resolve the arising conflicts.
In darcs, I see no way to force it to ignore the dependencies between patches. If I obliterate
or suspend
(or unrecord
) a patch which other patches depend on, darcs refuses to do it. (Because it wants to behave in a clever manner.)
I had the following plan to do this:
Here are some notes on how all this has proceeded.
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).
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)'
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:
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.
Throw away the unwanted (or re-ordered) patch:
darcs obliterate
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
darcs pull ../../language-c_printAST
# resolve conflicts
darcs amend
(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.)