3 ms·
Yeah, normally for 3-way merges you want the kind of graph relationship you suggest (that the base is the most recent common ancestor for the two versions you w
by dan-robertson 3y ago
Yeah, normally for 3-way merges you want the kind of graph relationship you suggest (that the base is the most recent common ancestor for the two versions you want to merge)
I think two questions you should ask are:
1) what does it mean to ‘apply a patch’ where the patch is the diff from X to Y but you are applying to a different revision from X.
2) what even is a patch in git?
Darcs thinks in terms of patches but git, despite showing you lots of diffs is really only thinking in terms of snapshots. The answer to question 2 is that patches in git are diffs between revisions and, in particular between the parent of a commit and the revision of the commit itself.
The answer to (1) is that ‘apply a patch’ in git is actually just a 3-way merge.
If you write patches as arrows between revisions then the 3-way merge of two patches P, Q from a shared base is applying one patch to the tip of the other:
P
B ~~~~~~~~> X
\ \
\ Q \ Q’
\ \
~~~> Y ~~~> M
Here M is the 3-way merge of X and Y at base B and Q’, and the diff from X to M is the patch Q applied at X. For a normal merge, you make X and Y parents of M. Git merely generalises this to cases where B is not the parent of X: you imagine a patch going from the base of the one implied by the commit you want to cherry-pick (I.e. the parent of the commit) all the way to the place where you want to base it on. This time, you are only doing the 3-way merge to compute the tip of your patch, you already know the base (it’s the place where you are applying the patch) and instead of producing a merge commit, you produce a commit with all the data from the old one before the cherry-pick except that you set the base to the place you cherry-pick onto.
In darcs theory of patches terminology, you commute the cherry-pick patch backwards (ie going from (?->B)(B->Y1)(Y1->Y2)(Y2->Cherry) to (?->B)(B->Cherry’)(Cherry’->Y1’)(Y1’->Y2’)), somehow inject it before the B->X1 patch, and then commute it forwards to sit after X3->Head.
One question to ask is whether this magic 3-way merge to apply patches works in these cases. And the answer is yes, it works about as well as regular 3-way merges, so you can get merge conflicts as well as some varieties of incorrect results (cf the Darcs docs about this)