in this syntax we're making up as we go....
- We have a branch of versioned states [A, B, C] called mainline.
- We add the branch of versioned states [B, Change.1, Change.2, Change.3]
- Some other pair has an image with C loaded.
- They wish to apply our change.
- They choose Change.2 and say "Apply".
- D=merge(C, [B, Change.2])
where B is determined by inspecting the ancestry of both C and Change.2
Using a merge tool that can highlight conflicts they select 1 of many solutions to express two changesets as one:
- changeset resolution = choose( [B, C] * [B, Change.2] )
and then apply and versions the resulting state: - D = apply( C, resolution )
Note that the ancestry of D is now (C, Change.2).
To continue the example above: say
- they continue the mainline a little further, with E-F-G.
- they decide to apply Change.3 to G, creating versioned state G'
- G' = merge(G, [Change.2, Change.3])
where Change.2 is automatically determined by looking at the ancestry of G and Change.3.
The system isn't going to go back to B to compute the necessary changes, since that's no longer the closest common ancestor: D is annotated with two ancestors C and Change.2.
So is one preferred over the other?
C is very slightly preferred over Change.2, but that preference rarely matters in practice. The "closest common ancestor" is determined by a min-max algorithm: taking both G and Change.3 as roots of an ancestry graph, consider the longest possible non-looping paths to each other shared ancestor in the graph, and pick the one with the shortest such path. The main reason for this algorithm is to ensure that if there's a relationship "X is an ancestor of Y", Y will always be considered closer than X.
So it will compute the changes between Change.2 and Change.3, and apply only those.
- resolution = choose([Change.2, G] * [Change.2, Change.3])
- G' = apply(G, resolution)
The ancestry of G' is (G, Change.3)
On the other hand, if someone else has an old image with only C loaded, and they apply Change.3, the system will compute the changes from B instead. That's what I mean by the start point changing depending on what you are applying the change to.