[darcs-users] Make darcs force-commute patches from CLI, to learn about darcs?

Ben Franksen ben.franksen at online.de
Fri Jun 26 08:53:34 UTC 2020

Am 26.06.20 um 05:03 schrieb James Cook:
>>> What I'd like to do is create a repository R1 with patches A and B,
>>> and then look at the patches that result if A and B get
>>> force-commuted.
>>> E.g. if I could pull just patch B and not A to a new repository, I
>>> think that would do the trick, but of course darcs pull won't let me
>>> do that because B depends on A.
>> The main question here is: What do you expect the result of such a
>> force-commute would be?
> I've been reading about patch theory [0]. I *thought* what's supposed
> to happen is this:
> * The effect of B' is the same as the effect of A. (i.e. create the file)
> * The effect of A' is the same as the effect of B. (i.e. add "some text")
> * Therefore, B'A' does the same thing as AB.
> * B' and A' include some information about the conflict, in addition
> to their effects described above. (They are "conflictor" patches.)
> * If I commute B' and A' again, I get back AB, since <-> is a
> symmetric relation.

I understand. However, there is no patch theory I am aware of that is
able to make this work, except those where *any* two patches commute, so
there are no dependencies and patches never conflict.

> However, that doesn't seem to be what happened (see below).

No, indeed. The procedure I described /edits/ the patch history,
assigning new identities to both patches.

> Even if that were correct, it still doesn't leave me with a complete
> picture of what darcs actually does, so I wanted to experiment.
>>> Question 1: Is there a simple way to make darcs do this?
>> Not exactly simple, but it is possible:
>> darcs clone . ../saved
>> darcs rebase suspend # select B and A
>> darcs rebase obliterate # select A
>> darcs rebase unsuspend # select B
>> darcs pull ../saved # select A
>> You should expect to get conflicts first when you unsuspend B (after
>> obliterating A) and then also when you re-pull A from the clone. You
>> will probably want to amend the conflict resolution into the conflicted
>> patch.
> Thanks, that seems to have worked. (I only got the first conflict, not
> the second.) But now I'm confused.
> Based on, for example, the "Forced commutation" section of
> https://en.wikibooks.org/wiki/Understanding_Darcs/Patch_theory_and_conflicts
> , I expected B' to add the file "foo", and A' to add "some text" (so,
> B' has the effect of A and A' has the effect of B).
> Instead of that, I get this:
> (a) If I follow your advice and amend the conflict resolution into B'
> before pulling, then (the amended) B' has the effect of AB, and A' has
> no effect.
> (b) If I run "darcs revert" instead of amending the conflict
> resolution into B', then B' has the effect of A and A' still has no
> effect.
> Confusingly, darcs offers to pull B from ../saved --- I thought darcs
> should consider it to already be present (as B').
> I also noticed that if I run the swap a second time, I don't exactly
> get A and B back. (In the (a) case, I get patches with the same
> effects, but the new B starts with "duplicate"). I thought commutation
> was always supposed to be symmetric. Does that not apply when
> conflictors are involved?

You can rest assured that proper commutation is symmetric. The procedure
I described is *not* a commutation! The 'rebase' and 'amend' commands
create completely new patches that are unrelated to the original ones.
It's more like 'darcs unrecord', fiddle around with the changes, then
again 'darcs record' in a different order.

As I said in the beginning, there is no force-commute command in darcs
because that would be unsound. By definition, if B depends on A this
means A;B does /not/ commute. In the theory, one starts with primitive
patches for which there is no total merge operation, only a partial
clean-merge that may fail. If you have two independently recorded
patches A and B in the same context (we write this as A\/B), then
clean-merge succeeds iff A^;B commutes (where ^ means inversion). If
clean-merge(A\/B) does not succeed, then A\/B are said to be in conflict.

When we add conflictors, we extend the set/type of primitive patches to
a larger set, such that now any two patches can be merged. However, we
must require that this extension preserves commutation behavior. In
particular, if A;B does not commute, then their embeddings in the larger
set of patches must commute neither.

I know that Judah Jacobsen in his inverse semigroup paper writes that
adding conflictors makes any two patches commutable. This is wrong. He
derived this from the square commute law. But when you add conflictors,
this law is no longer valid. Indeed, the existence of the square-commute
law is precisely what distinguishes primitive patches from (potentially)
conflicted ones. Another way to see the contradiction here is that if
you can commute any two patches, then there is no longer any way to
define (or calculate) which patches are in conflict: if A^;B always
commutes, then A\/B always merges cleanly.

The only way to implement force-commute in a sound manner is to assign
new identities to both patches. It is thus not a proper commute and does
not have to obey the usual patch laws.


More information about the darcs-users mailing list