1185.1.29
by Robert Collins
merge merge tweaks from aaron, which includes latest .dev |
1 |
======= |
2 |
Merging |
|
3 |
======= |
|
4 |
||
5 |
There should be one merge command which does the right thing, and |
|
6 |
which is called 'merge'. |
|
7 |
||
8 |
The merge command pulls a changeset or a range of changesets into your |
|
9 |
tree. It knows what changes have already been integrated and avoids |
|
10 |
pulling them again. |
|
11 |
||
12 |
There should be some intelligence about working out what changes have |
|
13 |
already been merged. |
|
14 |
||
15 |
The tool intelligently chooses (or perhaps synthesizes) an ancestor |
|
16 |
and two trees to merge. These are then intelligently merged. |
|
17 |
||
18 |
Merge should refuse to run (unless forced) if there are any |
|
19 |
uncommitted changes in your tree beforehand. This has two purposes: |
|
20 |
if you mess up the merge you won't lose anything important; secondly |
|
21 |
this makes it more likely that the merge will be relatively pure. |
|
22 |
||
23 |
It is a good idea to commit as soon as a merge is complete and |
|
24 |
satisfactorily resolved, so as to protect the work you did in the |
|
25 |
merge and to keep it separate from later development. (Mark suggests |
|
26 |
an option to automatically commit when the merge is complete.) |
|
27 |
||
28 |
||
29 |
Recording merges |
|
30 |
---------------- |
|
31 |
||
32 |
bzr records what branches have been merged so far. This is useful as |
|
33 |
historical information and also for later choosing a merge ancestor. |
|
34 |
||
35 |
For each revision we record all the other revisions which have come |
|
36 |
into this tree, either by being completely merged or as cherry-picks. |
|
37 |
||
38 |
(This design is similar to the PatchLogPruning__ draft from baz.) |
|
39 |
||
40 |
__ http://wiki.gnuarch.org/PatchLogPruning |
|
41 |
||
42 |
This list of merged revisions is generally append-only, but can be |
|
43 |
reduced if changes are taken back out. Changes can be |
|
44 |
anti-cherry-picked, which causes any successors to change from being |
|
45 |
fully-merged to being cherry-picked. |
|
46 |
||
47 |
The list of merged patches is stored delta-compressed. |
|
48 |
||
49 |
||
50 |
``tla update`` |
|
51 |
-------------- |
|
52 |
||
53 |
``tla update`` performs a useful but slightly subtle change: it pulls |
|
54 |
in only changes that have been made on the other branch since you last |
|
55 |
merged. That is to say, it sets the merge basis as the most recent |
|
56 |
merged-from point on the other branch. |
|
57 |
||
58 |
This means that any changes which were taken from your branch into the |
|
59 |
other and then reversed or modified will not be reversed. Those |
|
60 |
changes will always be considered as new in your branch and will have |
|
61 |
precedence. |
|
62 |
||
63 |
The basic idea of a merge that only brings in remote work and doesn't |
|
64 |
revert your own changes is good. It could be handled by a three way |
|
65 |
merge with a specified version but perhaps there is a better way. |
|
66 |
||
67 |
||
68 |
Merging tree shape |
|
69 |
------------------ |
|
70 |
||
71 |
Merge is conducted at two levels: merging the tree shape, and merging |
|
72 |
the file contents. Merging the tree shape means accounting for |
|
73 |
renames, adds, deletes, etc. This is almost the same as merging the |
|
74 |
two inventories, but we need to do a smart merge on them to enforce |
|
75 |
structural invariants. |
|
76 |
||
77 |
||
78 |
||
79 |
Interrupting a merge |
|
80 |
-------------------- |
|
81 |
||
82 |
Some tools insist that you complete the entire merge while the |
|
83 |
``merge`` command is running; you cannot exit the program or restart |
|
84 |
the computer because state is held in memory. We should avoid that. |
|
85 |
At least when the tool is waiting for user input it should have |
|
86 |
written everything to disk sufficient to pick up and continue the |
|
87 |
merge from that point. |
|
88 |
||
89 |
This suggests that there should be a command to continue a merge; |
|
90 |
perhaps ``bzr resolve`` should look for any unresolved changes and |
|
91 |
start resolving them. ``bzr merge`` can (by default) automatically |
|
92 |
start this process. |
|
93 |
||
94 |
One hard aspect is transformation of the tree state such as renames, |
|
95 |
directory creation, etc. This might include files swapping place, |
|
96 |
etc. We would like to do atomically but cannot. |
|
97 |
||
98 |
||
99 |
||
100 |
Aborting a merge |
|
101 |
---------------- |
|
102 |
||
103 |
If a merge has been begun but not committed then ``bzr revert`` should |
|
104 |
put everything back as it was in the previous revision. This includes |
|
105 |
resetting the tree state and texts, and also clearing the list of |
|
106 |
pending-merged revisions. |
|
107 |
||
108 |
||
109 |
||
110 |
Offline merge |
|
111 |
------------- |
|
112 |
||
113 |
It should be possible to download all the data necessary to do a merge |
|
114 |
from a remote branch, then disconnect and complete the merge. It |
|
115 |
should be possible to interrupt and continue the merge during this |
|
116 |
process. |
|
117 |
||
118 |
This implies that all the data is pulled down and stored somewhere |
|
119 |
locally before the actual merge begins. It could be pulled either |
|
120 |
into the revision history on non-trunk revisions, or into temporary |
|
121 |
files. |
|
122 |
||
123 |
It seems useful to move all revisions and texts from the other branch |
|
124 |
into the storage of this branch, in concordance with the general idea |
|
125 |
of every branch moving towards complete knowledge. This allows the |
|
126 |
most options for an offline merge, and also for later looking back to |
|
127 |
see what was merged in and what decisions were made during the merge. |
|
128 |
||
129 |
||
130 |
||
131 |
Merge metadata |
|
132 |
-------------- |
|
133 |
||
134 |
What does cherry-picking mean here? It means we merged the changes |
|
135 |
from a revision relative to its predecessor? But what if we actually |
|
136 |
want to merge the delta relative to something else? Can that be |
|
137 |
represented? |
|
138 |
||
139 |
||
140 |
Rejected merges |
|
141 |
--------------- |
|
142 |
||
143 |
ddaa says perhaps we should have three states: with respect to a |
|
144 |
branch any foreign revision can be *merged*, *not-merged*, or *rejected*. |
|
145 |
The difference between *not-merged* and *rejected* is that not-merged |
|
146 |
patches will try to merge in when you next sync from their |
|
147 |
branch, whereas rejected changes will not. |
|
148 |
||
149 |
'rejected' seems technically equivalent to it merged with the text |
|
150 |
changes not present. But perhaps there should be something more? |
|
151 |
||
152 |
||
153 |
Excluded changes |
|
154 |
---------------- |
|
155 |
||
156 |
Bitkeeper has the very interesting feature of *excluded* changesets, |
|
157 |
where something previously committed to or merged into this branch is |
|
158 |
treated as if it never occurred. Because of their representation of |
|
159 |
changes as a weave they can do this without dependency problems on |
|
160 |
later merges. |
|
161 |
||
162 |
Although the later changes will not mechanically conflict, there is of |
|
163 |
course no guarantee that excluding the patch will generate anything |
|
164 |
semantically valid. |
|
165 |
||
166 |
Cool though this is, it seems that few people understand it well |
|
167 |
enough to use it confidently. It complicates the merge algorithms and |
|
168 |
seems to have been a source of some bugs. It may be better just to |
|
169 |
apply a reversed patch. |
|
170 |
||
171 |
||
172 |
||
173 |
Implementation |
|
174 |
-------------- |
|
175 |
||
176 |
Each revision has a pointer to two sets, represented as lists of |
|
177 |
revision-ids: |
|
178 |
||
179 |
* ``merged-revisions`` |
|
180 |
* ``picked-revisions`` |
|
181 |
||
182 |
When a branch is merged in, its revision history plus merged-revisions |
|
183 |
are added to the merged-revisions file. When changes are |
|
184 |
cherry-picked in they are added to the picked-revisions. |
|
185 |
||
186 |
These lists are stored in the text store and their sha1 and id is |
|
187 |
stored in the revision. |
|
188 |
||
189 |
While a merge is underway, these are stored in |
|
190 |
``.bzr/pending-merged-revisions`` and |
|
191 |
``.bzr/pending-picked-revisions``. |