##// END OF EJS Templates
documentation: add some internals documentation about bid merge...
marmoute -
r45605:6c22f3ab default draft
parent child Browse files
Show More
@@ -0,0 +1,115 b''
1 Bid merge is a feature introduced in Mercurial 3.0, a merge algorithm for
2 dealing with complicated merges.
3
4 Bid merge is controled by the `merge.preferancestor` configuration option. The
5 default is set to `merge.preferancetors=*` and enable bid merge. Mercurial will
6 perform a bid merge in the cases where a merge otherwise would emit a note:
7 using X as ancestor of X and X message.
8
9 Problem it is solving
10 =====================
11
12 Mercurial's core merge algorithm is the traditional "three-way merge". This
13 algorithm combines all the changes in two changesets relative to a common
14 ancestor. But with complex DAGs, it is often possible to have more than one
15 "best" common ancestor, with no easy way to distinguish between them.
16
17 For example, C and D has 2 common ancestors in the following graph::
18
19 C D
20 |\ /|
21 | x |
22 |/ \|
23 A B
24 \ /
25 R
26
27 Mercurial used to arbitrarily chooses the first of these, which can result in
28 various issues:
29
30 * unexpected hard 3-way merges that would have been completely trivial if
31 another ancestor had been used
32
33 * conflicts that have already been resolved may reappear
34
35 * changes that have been reversed can silently oscillate
36
37 One common problem is a merge which with the "right" ancestor would be trivial
38 to resolve because only one side changed. Using another ancestor where the same
39 lines are different, it will give an annoying 3-way merge.
40
41 Other systems like Git have attacked some of these problems with a so-called
42 "recursive" merge strategy, that internally merges all the possible ancestors
43 to produce a single "virtual" ancestor to merge against. This is awkward as the
44 internal merge itself may involve conflicts (and possibly even multiple levels
45 of recursion), which either requires choosing a conflict disposition (e.g.
46 always choose the local version) or exposing the user to extremely confusing
47 merge prompts for old revisions. Generating the virtual merge also potentially
48 involves invoking filters and extensions.
49
50 Concept
51 =======
52
53 (Bid merge is pretty much the same as Consensus merge.)
54
55 Bid merge is a strategy that attempts to sensibly combine the results of the
56 multiple possible three-way merges directly without producing a virtual
57 ancestor. The basic idea is that for each ancestor, we perform a top-level
58 manifest merge and generate a list of proposed actions, which we consider
59 "bids". We then make an "auction" among all the bids for each file and pick the
60 most favourable. Some files might be trivial to merge with one ancestor, other
61 files with another ancestor.
62
63 The most obvious advantage of considering multiple ancestors is the case where
64 some of the bids for a file is a "real" (interactive) merge but where one or
65 more bids just take on of the parent revisions. A bid for just taking an
66 existing revision is very simple and low risk and is an obvious winner.
67
68 The auction algorithm for merging the bids is so far very simple:
69
70 * If there is consensus from all the ancestors, there is no doubt what to do. A
71 clever result will be indistinguishable from just picking a random bid. The
72 consensus case is thus not only trivial, it is also already handled
73 perfectly.
74
75 * If "keep local" or "get from other" actions is an option (and there is only
76 one such option), just do it.
77
78 * If the auction doesn't have a single clear winner, pick one of the bids
79 "randomly" - just as it would have done if only one ancestor was considered.
80
81 This meta merge algorithm has room for future improvements, especially for
82 doing better than picking a random bid.
83
84 Some observations
85 =================
86
87 Experience with bid merge shows that many merges that actually have a very
88 simple solution (because only one side changed) only can be solved efficiently
89 when we start looking at file content in filemerge ... and it thus also
90 requires all ancestors passed to filemerge. That is because Mercurial includes
91 the history in filelog hashes. A file with changes that ends up not changing
92 the content (could be change + backout or graft + merge or criss cross merges)
93 still shows up as a changed file to manifestmerge. (The git data model has an
94 advantage here when it uses hashes of content without history.) One way to
95 handle that would be to refactor manifestmerge, mergestate/resolve and
96 filemerge so they become more of the same thing.
97
98 There is also cases where different conflicting chunks could benefit from using
99 multiple ancestors in filemerge - but that will require merge tools with fancy
100 support for using multiple ancestors in 3+-way merge. That is left as an
101 exercise for another day. That seems to be a case where "recursive merge" has
102 an advantage.
103
104 The current manifest merge actions are very low level imperative and not
105 symmetrical. They do not only describe how two manifests should be merged, they
106 also describe a strategy for changing a context from a state where it is one of
107 the parents to the state where it is the result of the merge with the other
108 parent. I can imagine that manifestmerge could be simplified (and made more
109 suitable for in memory merges) by separating the abstract merge actions from
110 the actual file system operation actions. A more clever wcontext could perhaps
111 also take care of some of the branchmerge special cases.
112
113 We assume that the definition of Mercurial manifest merge will make sure that
114 exactly the same files will be produced, no matter which ancestor is used. That
115 assumption might be wrong in very rare cases that really not is a problem.
@@ -345,6 +345,11 b' def loaddoc(topic, subdir=None):'
345
345
346 internalstable = sorted(
346 internalstable = sorted(
347 [
347 [
348 (
349 [b'bid-merge'],
350 _(b'Bid Merge Algorithm'),
351 loaddoc(b'bid-merge', subdir=b'internals'),
352 ),
348 ([b'bundle2'], _(b'Bundle2'), loaddoc(b'bundle2', subdir=b'internals')),
353 ([b'bundle2'], _(b'Bundle2'), loaddoc(b'bundle2', subdir=b'internals')),
349 ([b'bundles'], _(b'Bundles'), loaddoc(b'bundles', subdir=b'internals')),
354 ([b'bundles'], _(b'Bundles'), loaddoc(b'bundles', subdir=b'internals')),
350 ([b'cbor'], _(b'CBOR'), loaddoc(b'cbor', subdir=b'internals')),
355 ([b'cbor'], _(b'CBOR'), loaddoc(b'cbor', subdir=b'internals')),
@@ -1094,6 +1094,7 b' internals topic renders index of availab'
1094
1094
1095 To access a subtopic, use "hg help internals.{subtopic-name}"
1095 To access a subtopic, use "hg help internals.{subtopic-name}"
1096
1096
1097 bid-merge Bid Merge Algorithm
1097 bundle2 Bundle2
1098 bundle2 Bundle2
1098 bundles Bundles
1099 bundles Bundles
1099 cbor CBOR
1100 cbor CBOR
@@ -3439,6 +3440,13 b' Sub-topic indexes rendered properly'
3439 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
3440 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
3440
3441
3441 <tr><td>
3442 <tr><td>
3443 <a href="/help/internals.bid-merge">
3444 bid-merge
3445 </a>
3446 </td><td>
3447 Bid Merge Algorithm
3448 </td></tr>
3449 <tr><td>
3442 <a href="/help/internals.bundle2">
3450 <a href="/help/internals.bundle2">
3443 bundle2
3451 bundle2
3444 </a>
3452 </a>
General Comments 0
You need to be logged in to leave comments. Login now