##// END OF EJS Templates
merge: minimize conflicts when common base is not shown (issue4447)...
Ryan McElroy -
r28072:c3e9269d default
parent child Browse files
Show More
@@ -1,459 +1,466 b''
1 # Copyright (C) 2004, 2005 Canonical Ltd
1 # Copyright (C) 2004, 2005 Canonical Ltd
2 #
2 #
3 # This program is free software; you can redistribute it and/or modify
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
6 # (at your option) any later version.
7 #
7 #
8 # This program is distributed in the hope that it will be useful,
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
11 # GNU General Public License for more details.
12 #
12 #
13 # You should have received a copy of the GNU General Public License
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, see <http://www.gnu.org/licenses/>.
14 # along with this program; if not, see <http://www.gnu.org/licenses/>.
15
15
16 # mbp: "you know that thing where cvs gives you conflict markers?"
16 # mbp: "you know that thing where cvs gives you conflict markers?"
17 # s: "i hate that."
17 # s: "i hate that."
18
18
19 from __future__ import absolute_import
19 from __future__ import absolute_import
20
20
21 import os
21 import os
22 import sys
22 import sys
23
23
24 from .i18n import _
24 from .i18n import _
25 from . import (
25 from . import (
26 error,
26 error,
27 mdiff,
27 mdiff,
28 scmutil,
28 scmutil,
29 util,
29 util,
30 )
30 )
31
31
32 class CantReprocessAndShowBase(Exception):
32 class CantReprocessAndShowBase(Exception):
33 pass
33 pass
34
34
35 def intersect(ra, rb):
35 def intersect(ra, rb):
36 """Given two ranges return the range where they intersect or None.
36 """Given two ranges return the range where they intersect or None.
37
37
38 >>> intersect((0, 10), (0, 6))
38 >>> intersect((0, 10), (0, 6))
39 (0, 6)
39 (0, 6)
40 >>> intersect((0, 10), (5, 15))
40 >>> intersect((0, 10), (5, 15))
41 (5, 10)
41 (5, 10)
42 >>> intersect((0, 10), (10, 15))
42 >>> intersect((0, 10), (10, 15))
43 >>> intersect((0, 9), (10, 15))
43 >>> intersect((0, 9), (10, 15))
44 >>> intersect((0, 9), (7, 15))
44 >>> intersect((0, 9), (7, 15))
45 (7, 9)
45 (7, 9)
46 """
46 """
47 assert ra[0] <= ra[1]
47 assert ra[0] <= ra[1]
48 assert rb[0] <= rb[1]
48 assert rb[0] <= rb[1]
49
49
50 sa = max(ra[0], rb[0])
50 sa = max(ra[0], rb[0])
51 sb = min(ra[1], rb[1])
51 sb = min(ra[1], rb[1])
52 if sa < sb:
52 if sa < sb:
53 return sa, sb
53 return sa, sb
54 else:
54 else:
55 return None
55 return None
56
56
57 def compare_range(a, astart, aend, b, bstart, bend):
57 def compare_range(a, astart, aend, b, bstart, bend):
58 """Compare a[astart:aend] == b[bstart:bend], without slicing.
58 """Compare a[astart:aend] == b[bstart:bend], without slicing.
59 """
59 """
60 if (aend - astart) != (bend - bstart):
60 if (aend - astart) != (bend - bstart):
61 return False
61 return False
62 for ia, ib in zip(xrange(astart, aend), xrange(bstart, bend)):
62 for ia, ib in zip(xrange(astart, aend), xrange(bstart, bend)):
63 if a[ia] != b[ib]:
63 if a[ia] != b[ib]:
64 return False
64 return False
65 else:
65 else:
66 return True
66 return True
67
67
68 class Merge3Text(object):
68 class Merge3Text(object):
69 """3-way merge of texts.
69 """3-way merge of texts.
70
70
71 Given strings BASE, OTHER, THIS, tries to produce a combined text
71 Given strings BASE, OTHER, THIS, tries to produce a combined text
72 incorporating the changes from both BASE->OTHER and BASE->THIS."""
72 incorporating the changes from both BASE->OTHER and BASE->THIS."""
73 def __init__(self, basetext, atext, btext, base=None, a=None, b=None):
73 def __init__(self, basetext, atext, btext, base=None, a=None, b=None):
74 self.basetext = basetext
74 self.basetext = basetext
75 self.atext = atext
75 self.atext = atext
76 self.btext = btext
76 self.btext = btext
77 if base is None:
77 if base is None:
78 base = mdiff.splitnewlines(basetext)
78 base = mdiff.splitnewlines(basetext)
79 if a is None:
79 if a is None:
80 a = mdiff.splitnewlines(atext)
80 a = mdiff.splitnewlines(atext)
81 if b is None:
81 if b is None:
82 b = mdiff.splitnewlines(btext)
82 b = mdiff.splitnewlines(btext)
83 self.base = base
83 self.base = base
84 self.a = a
84 self.a = a
85 self.b = b
85 self.b = b
86
86
87 def merge_lines(self,
87 def merge_lines(self,
88 name_a=None,
88 name_a=None,
89 name_b=None,
89 name_b=None,
90 name_base=None,
90 name_base=None,
91 start_marker='<<<<<<<',
91 start_marker='<<<<<<<',
92 mid_marker='=======',
92 mid_marker='=======',
93 end_marker='>>>>>>>',
93 end_marker='>>>>>>>',
94 base_marker=None,
94 base_marker=None,
95 localorother=None):
95 localorother=None,
96 minimize=False):
96 """Return merge in cvs-like form.
97 """Return merge in cvs-like form.
97 """
98 """
98 self.conflicts = False
99 self.conflicts = False
99 newline = '\n'
100 newline = '\n'
100 if len(self.a) > 0:
101 if len(self.a) > 0:
101 if self.a[0].endswith('\r\n'):
102 if self.a[0].endswith('\r\n'):
102 newline = '\r\n'
103 newline = '\r\n'
103 elif self.a[0].endswith('\r'):
104 elif self.a[0].endswith('\r'):
104 newline = '\r'
105 newline = '\r'
105 if name_a and start_marker:
106 if name_a and start_marker:
106 start_marker = start_marker + ' ' + name_a
107 start_marker = start_marker + ' ' + name_a
107 if name_b and end_marker:
108 if name_b and end_marker:
108 end_marker = end_marker + ' ' + name_b
109 end_marker = end_marker + ' ' + name_b
109 if name_base and base_marker:
110 if name_base and base_marker:
110 base_marker = base_marker + ' ' + name_base
111 base_marker = base_marker + ' ' + name_base
111 merge_regions = self.merge_regions()
112 merge_regions = self.merge_regions()
113 if minimize:
114 merge_regions = self.minimize(merge_regions)
112 for t in merge_regions:
115 for t in merge_regions:
113 what = t[0]
116 what = t[0]
114 if what == 'unchanged':
117 if what == 'unchanged':
115 for i in range(t[1], t[2]):
118 for i in range(t[1], t[2]):
116 yield self.base[i]
119 yield self.base[i]
117 elif what == 'a' or what == 'same':
120 elif what == 'a' or what == 'same':
118 for i in range(t[1], t[2]):
121 for i in range(t[1], t[2]):
119 yield self.a[i]
122 yield self.a[i]
120 elif what == 'b':
123 elif what == 'b':
121 for i in range(t[1], t[2]):
124 for i in range(t[1], t[2]):
122 yield self.b[i]
125 yield self.b[i]
123 elif what == 'conflict':
126 elif what == 'conflict':
124 if localorother == 'local':
127 if localorother == 'local':
125 for i in range(t[3], t[4]):
128 for i in range(t[3], t[4]):
126 yield self.a[i]
129 yield self.a[i]
127 elif localorother == 'other':
130 elif localorother == 'other':
128 for i in range(t[5], t[6]):
131 for i in range(t[5], t[6]):
129 yield self.b[i]
132 yield self.b[i]
130 else:
133 else:
131 self.conflicts = True
134 self.conflicts = True
132 if start_marker is not None:
135 if start_marker is not None:
133 yield start_marker + newline
136 yield start_marker + newline
134 for i in range(t[3], t[4]):
137 for i in range(t[3], t[4]):
135 yield self.a[i]
138 yield self.a[i]
136 if base_marker is not None:
139 if base_marker is not None:
137 yield base_marker + newline
140 yield base_marker + newline
138 for i in range(t[1], t[2]):
141 for i in range(t[1], t[2]):
139 yield self.base[i]
142 yield self.base[i]
140 if mid_marker is not None:
143 if mid_marker is not None:
141 yield mid_marker + newline
144 yield mid_marker + newline
142 for i in range(t[5], t[6]):
145 for i in range(t[5], t[6]):
143 yield self.b[i]
146 yield self.b[i]
144 if end_marker is not None:
147 if end_marker is not None:
145 yield end_marker + newline
148 yield end_marker + newline
146 else:
149 else:
147 raise ValueError(what)
150 raise ValueError(what)
148
151
149 def merge_groups(self):
152 def merge_groups(self):
150 """Yield sequence of line groups. Each one is a tuple:
153 """Yield sequence of line groups. Each one is a tuple:
151
154
152 'unchanged', lines
155 'unchanged', lines
153 Lines unchanged from base
156 Lines unchanged from base
154
157
155 'a', lines
158 'a', lines
156 Lines taken from a
159 Lines taken from a
157
160
158 'same', lines
161 'same', lines
159 Lines taken from a (and equal to b)
162 Lines taken from a (and equal to b)
160
163
161 'b', lines
164 'b', lines
162 Lines taken from b
165 Lines taken from b
163
166
164 'conflict', base_lines, a_lines, b_lines
167 'conflict', base_lines, a_lines, b_lines
165 Lines from base were changed to either a or b and conflict.
168 Lines from base were changed to either a or b and conflict.
166 """
169 """
167 for t in self.merge_regions():
170 for t in self.merge_regions():
168 what = t[0]
171 what = t[0]
169 if what == 'unchanged':
172 if what == 'unchanged':
170 yield what, self.base[t[1]:t[2]]
173 yield what, self.base[t[1]:t[2]]
171 elif what == 'a' or what == 'same':
174 elif what == 'a' or what == 'same':
172 yield what, self.a[t[1]:t[2]]
175 yield what, self.a[t[1]:t[2]]
173 elif what == 'b':
176 elif what == 'b':
174 yield what, self.b[t[1]:t[2]]
177 yield what, self.b[t[1]:t[2]]
175 elif what == 'conflict':
178 elif what == 'conflict':
176 yield (what,
179 yield (what,
177 self.base[t[1]:t[2]],
180 self.base[t[1]:t[2]],
178 self.a[t[3]:t[4]],
181 self.a[t[3]:t[4]],
179 self.b[t[5]:t[6]])
182 self.b[t[5]:t[6]])
180 else:
183 else:
181 raise ValueError(what)
184 raise ValueError(what)
182
185
183 def merge_regions(self):
186 def merge_regions(self):
184 """Return sequences of matching and conflicting regions.
187 """Return sequences of matching and conflicting regions.
185
188
186 This returns tuples, where the first value says what kind we
189 This returns tuples, where the first value says what kind we
187 have:
190 have:
188
191
189 'unchanged', start, end
192 'unchanged', start, end
190 Take a region of base[start:end]
193 Take a region of base[start:end]
191
194
192 'same', astart, aend
195 'same', astart, aend
193 b and a are different from base but give the same result
196 b and a are different from base but give the same result
194
197
195 'a', start, end
198 'a', start, end
196 Non-clashing insertion from a[start:end]
199 Non-clashing insertion from a[start:end]
197
200
198 'conflict', zstart, zend, astart, aend, bstart, bend
201 'conflict', zstart, zend, astart, aend, bstart, bend
199 Conflict between a and b, with z as common ancestor
202 Conflict between a and b, with z as common ancestor
200
203
201 Method is as follows:
204 Method is as follows:
202
205
203 The two sequences align only on regions which match the base
206 The two sequences align only on regions which match the base
204 and both descendants. These are found by doing a two-way diff
207 and both descendants. These are found by doing a two-way diff
205 of each one against the base, and then finding the
208 of each one against the base, and then finding the
206 intersections between those regions. These "sync regions"
209 intersections between those regions. These "sync regions"
207 are by definition unchanged in both and easily dealt with.
210 are by definition unchanged in both and easily dealt with.
208
211
209 The regions in between can be in any of three cases:
212 The regions in between can be in any of three cases:
210 conflicted, or changed on only one side.
213 conflicted, or changed on only one side.
211 """
214 """
212
215
213 # section a[0:ia] has been disposed of, etc
216 # section a[0:ia] has been disposed of, etc
214 iz = ia = ib = 0
217 iz = ia = ib = 0
215
218
216 for region in self.find_sync_regions():
219 for region in self.find_sync_regions():
217 zmatch, zend, amatch, aend, bmatch, bend = region
220 zmatch, zend, amatch, aend, bmatch, bend = region
218 #print 'match base [%d:%d]' % (zmatch, zend)
221 #print 'match base [%d:%d]' % (zmatch, zend)
219
222
220 matchlen = zend - zmatch
223 matchlen = zend - zmatch
221 assert matchlen >= 0
224 assert matchlen >= 0
222 assert matchlen == (aend - amatch)
225 assert matchlen == (aend - amatch)
223 assert matchlen == (bend - bmatch)
226 assert matchlen == (bend - bmatch)
224
227
225 len_a = amatch - ia
228 len_a = amatch - ia
226 len_b = bmatch - ib
229 len_b = bmatch - ib
227 len_base = zmatch - iz
230 len_base = zmatch - iz
228 assert len_a >= 0
231 assert len_a >= 0
229 assert len_b >= 0
232 assert len_b >= 0
230 assert len_base >= 0
233 assert len_base >= 0
231
234
232 #print 'unmatched a=%d, b=%d' % (len_a, len_b)
235 #print 'unmatched a=%d, b=%d' % (len_a, len_b)
233
236
234 if len_a or len_b:
237 if len_a or len_b:
235 # try to avoid actually slicing the lists
238 # try to avoid actually slicing the lists
236 equal_a = compare_range(self.a, ia, amatch,
239 equal_a = compare_range(self.a, ia, amatch,
237 self.base, iz, zmatch)
240 self.base, iz, zmatch)
238 equal_b = compare_range(self.b, ib, bmatch,
241 equal_b = compare_range(self.b, ib, bmatch,
239 self.base, iz, zmatch)
242 self.base, iz, zmatch)
240 same = compare_range(self.a, ia, amatch,
243 same = compare_range(self.a, ia, amatch,
241 self.b, ib, bmatch)
244 self.b, ib, bmatch)
242
245
243 if same:
246 if same:
244 yield 'same', ia, amatch
247 yield 'same', ia, amatch
245 elif equal_a and not equal_b:
248 elif equal_a and not equal_b:
246 yield 'b', ib, bmatch
249 yield 'b', ib, bmatch
247 elif equal_b and not equal_a:
250 elif equal_b and not equal_a:
248 yield 'a', ia, amatch
251 yield 'a', ia, amatch
249 elif not equal_a and not equal_b:
252 elif not equal_a and not equal_b:
250 yield 'conflict', iz, zmatch, ia, amatch, ib, bmatch
253 yield 'conflict', iz, zmatch, ia, amatch, ib, bmatch
251 else:
254 else:
252 raise AssertionError("can't handle a=b=base but unmatched")
255 raise AssertionError("can't handle a=b=base but unmatched")
253
256
254 ia = amatch
257 ia = amatch
255 ib = bmatch
258 ib = bmatch
256 iz = zmatch
259 iz = zmatch
257
260
258 # if the same part of the base was deleted on both sides
261 # if the same part of the base was deleted on both sides
259 # that's OK, we can just skip it.
262 # that's OK, we can just skip it.
260
263
261
264
262 if matchlen > 0:
265 if matchlen > 0:
263 assert ia == amatch
266 assert ia == amatch
264 assert ib == bmatch
267 assert ib == bmatch
265 assert iz == zmatch
268 assert iz == zmatch
266
269
267 yield 'unchanged', zmatch, zend
270 yield 'unchanged', zmatch, zend
268 iz = zend
271 iz = zend
269 ia = aend
272 ia = aend
270 ib = bend
273 ib = bend
271
274
272 def minimize(self, merge_regions):
275 def minimize(self, merge_regions):
273 """Trim conflict regions of lines where A and B sides match.
276 """Trim conflict regions of lines where A and B sides match.
274
277
275 Lines where both A and B have made the same changes at the begining
278 Lines where both A and B have made the same changes at the begining
276 or the end of each merge region are eliminated from the conflict
279 or the end of each merge region are eliminated from the conflict
277 region and are instead considered the same.
280 region and are instead considered the same.
278 """
281 """
279 for region in merge_regions:
282 for region in merge_regions:
280 if region[0] != "conflict":
283 if region[0] != "conflict":
281 yield region
284 yield region
282 continue
285 continue
283 issue, z1, z2, a1, a2, b1, b2 = region
286 issue, z1, z2, a1, a2, b1, b2 = region
284 alen = a2 - a1
287 alen = a2 - a1
285 blen = b2 - b1
288 blen = b2 - b1
286
289
287 # find matches at the front
290 # find matches at the front
288 ii = 0
291 ii = 0
289 while ii < alen and ii < blen and \
292 while ii < alen and ii < blen and \
290 self.a[a1 + ii] == self.b[b1 + ii]:
293 self.a[a1 + ii] == self.b[b1 + ii]:
291 ii += 1
294 ii += 1
292 startmatches = ii
295 startmatches = ii
293
296
294 # find matches at the end
297 # find matches at the end
295 ii = 0
298 ii = 0
296 while ii < alen and ii < blen and \
299 while ii < alen and ii < blen and \
297 self.a[a2 - ii - 1] == self.b[b2 - ii - 1]:
300 self.a[a2 - ii - 1] == self.b[b2 - ii - 1]:
298 ii += 1
301 ii += 1
299 endmatches = ii
302 endmatches = ii
300
303
301 if startmatches > 0:
304 if startmatches > 0:
302 yield 'same', a1, a1 + startmatches
305 yield 'same', a1, a1 + startmatches
303
306
304 yield ('conflict', z1, z2,
307 yield ('conflict', z1, z2,
305 a1 + startmatches, a2 - endmatches,
308 a1 + startmatches, a2 - endmatches,
306 b1 + startmatches, b2 - endmatches)
309 b1 + startmatches, b2 - endmatches)
307
310
308 if endmatches > 0:
311 if endmatches > 0:
309 yield 'same', a2 - endmatches, a2
312 yield 'same', a2 - endmatches, a2
310
313
311 def find_sync_regions(self):
314 def find_sync_regions(self):
312 """Return a list of sync regions, where both descendants match the base.
315 """Return a list of sync regions, where both descendants match the base.
313
316
314 Generates a list of (base1, base2, a1, a2, b1, b2). There is
317 Generates a list of (base1, base2, a1, a2, b1, b2). There is
315 always a zero-length sync region at the end of all the files.
318 always a zero-length sync region at the end of all the files.
316 """
319 """
317
320
318 ia = ib = 0
321 ia = ib = 0
319 amatches = mdiff.get_matching_blocks(self.basetext, self.atext)
322 amatches = mdiff.get_matching_blocks(self.basetext, self.atext)
320 bmatches = mdiff.get_matching_blocks(self.basetext, self.btext)
323 bmatches = mdiff.get_matching_blocks(self.basetext, self.btext)
321 len_a = len(amatches)
324 len_a = len(amatches)
322 len_b = len(bmatches)
325 len_b = len(bmatches)
323
326
324 sl = []
327 sl = []
325
328
326 while ia < len_a and ib < len_b:
329 while ia < len_a and ib < len_b:
327 abase, amatch, alen = amatches[ia]
330 abase, amatch, alen = amatches[ia]
328 bbase, bmatch, blen = bmatches[ib]
331 bbase, bmatch, blen = bmatches[ib]
329
332
330 # there is an unconflicted block at i; how long does it
333 # there is an unconflicted block at i; how long does it
331 # extend? until whichever one ends earlier.
334 # extend? until whichever one ends earlier.
332 i = intersect((abase, abase + alen), (bbase, bbase + blen))
335 i = intersect((abase, abase + alen), (bbase, bbase + blen))
333 if i:
336 if i:
334 intbase = i[0]
337 intbase = i[0]
335 intend = i[1]
338 intend = i[1]
336 intlen = intend - intbase
339 intlen = intend - intbase
337
340
338 # found a match of base[i[0], i[1]]; this may be less than
341 # found a match of base[i[0], i[1]]; this may be less than
339 # the region that matches in either one
342 # the region that matches in either one
340 assert intlen <= alen
343 assert intlen <= alen
341 assert intlen <= blen
344 assert intlen <= blen
342 assert abase <= intbase
345 assert abase <= intbase
343 assert bbase <= intbase
346 assert bbase <= intbase
344
347
345 asub = amatch + (intbase - abase)
348 asub = amatch + (intbase - abase)
346 bsub = bmatch + (intbase - bbase)
349 bsub = bmatch + (intbase - bbase)
347 aend = asub + intlen
350 aend = asub + intlen
348 bend = bsub + intlen
351 bend = bsub + intlen
349
352
350 assert self.base[intbase:intend] == self.a[asub:aend], \
353 assert self.base[intbase:intend] == self.a[asub:aend], \
351 (self.base[intbase:intend], self.a[asub:aend])
354 (self.base[intbase:intend], self.a[asub:aend])
352
355
353 assert self.base[intbase:intend] == self.b[bsub:bend]
356 assert self.base[intbase:intend] == self.b[bsub:bend]
354
357
355 sl.append((intbase, intend,
358 sl.append((intbase, intend,
356 asub, aend,
359 asub, aend,
357 bsub, bend))
360 bsub, bend))
358
361
359 # advance whichever one ends first in the base text
362 # advance whichever one ends first in the base text
360 if (abase + alen) < (bbase + blen):
363 if (abase + alen) < (bbase + blen):
361 ia += 1
364 ia += 1
362 else:
365 else:
363 ib += 1
366 ib += 1
364
367
365 intbase = len(self.base)
368 intbase = len(self.base)
366 abase = len(self.a)
369 abase = len(self.a)
367 bbase = len(self.b)
370 bbase = len(self.b)
368 sl.append((intbase, intbase, abase, abase, bbase, bbase))
371 sl.append((intbase, intbase, abase, abase, bbase, bbase))
369
372
370 return sl
373 return sl
371
374
372 def find_unconflicted(self):
375 def find_unconflicted(self):
373 """Return a list of ranges in base that are not conflicted."""
376 """Return a list of ranges in base that are not conflicted."""
374 am = mdiff.get_matching_blocks(self.basetext, self.atext)
377 am = mdiff.get_matching_blocks(self.basetext, self.atext)
375 bm = mdiff.get_matching_blocks(self.basetext, self.btext)
378 bm = mdiff.get_matching_blocks(self.basetext, self.btext)
376
379
377 unc = []
380 unc = []
378
381
379 while am and bm:
382 while am and bm:
380 # there is an unconflicted block at i; how long does it
383 # there is an unconflicted block at i; how long does it
381 # extend? until whichever one ends earlier.
384 # extend? until whichever one ends earlier.
382 a1 = am[0][0]
385 a1 = am[0][0]
383 a2 = a1 + am[0][2]
386 a2 = a1 + am[0][2]
384 b1 = bm[0][0]
387 b1 = bm[0][0]
385 b2 = b1 + bm[0][2]
388 b2 = b1 + bm[0][2]
386 i = intersect((a1, a2), (b1, b2))
389 i = intersect((a1, a2), (b1, b2))
387 if i:
390 if i:
388 unc.append(i)
391 unc.append(i)
389
392
390 if a2 < b2:
393 if a2 < b2:
391 del am[0]
394 del am[0]
392 else:
395 else:
393 del bm[0]
396 del bm[0]
394
397
395 return unc
398 return unc
396
399
397 def simplemerge(ui, local, base, other, **opts):
400 def simplemerge(ui, local, base, other, **opts):
398 def readfile(filename):
401 def readfile(filename):
399 f = open(filename, "rb")
402 f = open(filename, "rb")
400 text = f.read()
403 text = f.read()
401 f.close()
404 f.close()
402 if util.binary(text):
405 if util.binary(text):
403 msg = _("%s looks like a binary file.") % filename
406 msg = _("%s looks like a binary file.") % filename
404 if not opts.get('quiet'):
407 if not opts.get('quiet'):
405 ui.warn(_('warning: %s\n') % msg)
408 ui.warn(_('warning: %s\n') % msg)
406 if not opts.get('text'):
409 if not opts.get('text'):
407 raise error.Abort(msg)
410 raise error.Abort(msg)
408 return text
411 return text
409
412
410 mode = opts.get('mode','merge')
413 mode = opts.get('mode','merge')
411 if mode == 'union':
414 if mode == 'union':
412 name_a = None
415 name_a = None
413 name_b = None
416 name_b = None
414 name_base = None
417 name_base = None
415 else:
418 else:
416 name_a = local
419 name_a = local
417 name_b = other
420 name_b = other
418 name_base = None
421 name_base = None
419 labels = opts.get('label', [])
422 labels = opts.get('label', [])
420 if len(labels) > 0:
423 if len(labels) > 0:
421 name_a = labels[0]
424 name_a = labels[0]
422 if len(labels) > 1:
425 if len(labels) > 1:
423 name_b = labels[1]
426 name_b = labels[1]
424 if len(labels) > 2:
427 if len(labels) > 2:
425 name_base = labels[2]
428 name_base = labels[2]
426 if len(labels) > 3:
429 if len(labels) > 3:
427 raise error.Abort(_("can only specify three labels."))
430 raise error.Abort(_("can only specify three labels."))
428
431
429 try:
432 try:
430 localtext = readfile(local)
433 localtext = readfile(local)
431 basetext = readfile(base)
434 basetext = readfile(base)
432 othertext = readfile(other)
435 othertext = readfile(other)
433 except error.Abort:
436 except error.Abort:
434 return 1
437 return 1
435
438
436 local = os.path.realpath(local)
439 local = os.path.realpath(local)
437 if not opts.get('print'):
440 if not opts.get('print'):
438 opener = scmutil.opener(os.path.dirname(local))
441 opener = scmutil.opener(os.path.dirname(local))
439 out = opener(os.path.basename(local), "w", atomictemp=True)
442 out = opener(os.path.basename(local), "w", atomictemp=True)
440 else:
443 else:
441 out = sys.stdout
444 out = sys.stdout
442
445
443 m3 = Merge3Text(basetext, localtext, othertext)
446 m3 = Merge3Text(basetext, localtext, othertext)
444 extrakwargs = {"localorother": opts.get("localorother", None)}
447 extrakwargs = {
448 "localorother": opts.get("localorother", None),
449 'minimize': True,
450 }
445 if mode == 'union':
451 if mode == 'union':
446 extrakwargs['start_marker'] = None
452 extrakwargs['start_marker'] = None
447 extrakwargs['mid_marker'] = None
453 extrakwargs['mid_marker'] = None
448 extrakwargs['end_marker'] = None
454 extrakwargs['end_marker'] = None
449 elif name_base is not None:
455 elif name_base is not None:
450 extrakwargs['base_marker'] = '|||||||'
456 extrakwargs['base_marker'] = '|||||||'
451 extrakwargs['name_base'] = name_base
457 extrakwargs['name_base'] = name_base
458 extrakwargs['minimize'] = False
452 for line in m3.merge_lines(name_a=name_a, name_b=name_b, **extrakwargs):
459 for line in m3.merge_lines(name_a=name_a, name_b=name_b, **extrakwargs):
453 out.write(line)
460 out.write(line)
454
461
455 if not opts.get('print'):
462 if not opts.get('print'):
456 out.close()
463 out.close()
457
464
458 if m3.conflicts and not mode == 'union':
465 if m3.conflicts and not mode == 'union':
459 return 1
466 return 1
@@ -1,291 +1,276 b''
1 $ hg init
1 $ hg init
2 $ cat << EOF > a
2 $ cat << EOF > a
3 > Small Mathematical Series.
3 > Small Mathematical Series.
4 > One
4 > One
5 > Two
5 > Two
6 > Three
6 > Three
7 > Four
7 > Four
8 > Five
8 > Five
9 > Hop we are done.
9 > Hop we are done.
10 > EOF
10 > EOF
11 $ hg add a
11 $ hg add a
12 $ hg commit -m ancestor
12 $ hg commit -m ancestor
13 $ cat << EOF > a
13 $ cat << EOF > a
14 > Small Mathematical Series.
14 > Small Mathematical Series.
15 > 1
15 > 1
16 > 2
16 > 2
17 > 3
17 > 3
18 > 4
18 > 4
19 > 5
19 > 5
20 > Hop we are done.
20 > Hop we are done.
21 > EOF
21 > EOF
22 $ hg commit -m branch1
22 $ hg commit -m branch1
23 $ hg co 0
23 $ hg co 0
24 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
24 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
25 $ cat << EOF > a
25 $ cat << EOF > a
26 > Small Mathematical Series.
26 > Small Mathematical Series.
27 > 1
27 > 1
28 > 2
28 > 2
29 > 3
29 > 3
30 > 6
30 > 6
31 > 8
31 > 8
32 > Hop we are done.
32 > Hop we are done.
33 > EOF
33 > EOF
34 $ hg commit -m branch2
34 $ hg commit -m branch2
35 created new head
35 created new head
36
36
37 $ hg merge 1
37 $ hg merge 1
38 merging a
38 merging a
39 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
39 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
40 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
40 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
41 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
41 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
42 [1]
42 [1]
43
43
44 $ hg id
44 $ hg id
45 618808747361+c0c68e4fe667+ tip
45 618808747361+c0c68e4fe667+ tip
46
46
47 $ cat a
47 $ cat a
48 Small Mathematical Series.
48 Small Mathematical Series.
49 <<<<<<< local: 618808747361 - test: branch2
50 1
49 1
51 2
50 2
52 3
51 3
52 <<<<<<< local: 618808747361 - test: branch2
53 6
53 6
54 8
54 8
55 =======
55 =======
56 1
57 2
58 3
59 4
56 4
60 5
57 5
61 >>>>>>> other: c0c68e4fe667 - test: branch1
58 >>>>>>> other: c0c68e4fe667 - test: branch1
62 Hop we are done.
59 Hop we are done.
63
60
64 $ hg status
61 $ hg status
65 M a
62 M a
66 ? a.orig
63 ? a.orig
67
64
68 Verify custom conflict markers
65 Verify custom conflict markers
69
66
70 $ hg up -q --clean .
67 $ hg up -q --clean .
71 $ printf "\n[ui]\nmergemarkertemplate={author} {rev}\n" >> .hg/hgrc
68 $ printf "\n[ui]\nmergemarkertemplate={author} {rev}\n" >> .hg/hgrc
72
69
73 $ hg merge 1
70 $ hg merge 1
74 merging a
71 merging a
75 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
72 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
76 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
73 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
77 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
74 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
78 [1]
75 [1]
79
76
80 $ cat a
77 $ cat a
81 Small Mathematical Series.
78 Small Mathematical Series.
82 <<<<<<< local: test 2
83 1
79 1
84 2
80 2
85 3
81 3
82 <<<<<<< local: test 2
86 6
83 6
87 8
84 8
88 =======
85 =======
89 1
90 2
91 3
92 4
86 4
93 5
87 5
94 >>>>>>> other: test 1
88 >>>>>>> other: test 1
95 Hop we are done.
89 Hop we are done.
96
90
97 Verify line splitting of custom conflict marker which causes multiple lines
91 Verify line splitting of custom conflict marker which causes multiple lines
98
92
99 $ hg up -q --clean .
93 $ hg up -q --clean .
100 $ cat >> .hg/hgrc <<EOF
94 $ cat >> .hg/hgrc <<EOF
101 > [ui]
95 > [ui]
102 > mergemarkertemplate={author} {rev}\nfoo\nbar\nbaz
96 > mergemarkertemplate={author} {rev}\nfoo\nbar\nbaz
103 > EOF
97 > EOF
104
98
105 $ hg -q merge 1
99 $ hg -q merge 1
106 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
100 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
107 [1]
101 [1]
108
102
109 $ cat a
103 $ cat a
110 Small Mathematical Series.
104 Small Mathematical Series.
111 <<<<<<< local: test 2
112 1
105 1
113 2
106 2
114 3
107 3
108 <<<<<<< local: test 2
115 6
109 6
116 8
110 8
117 =======
111 =======
118 1
119 2
120 3
121 4
112 4
122 5
113 5
123 >>>>>>> other: test 1
114 >>>>>>> other: test 1
124 Hop we are done.
115 Hop we are done.
125
116
126 Verify line trimming of custom conflict marker using multi-byte characters
117 Verify line trimming of custom conflict marker using multi-byte characters
127
118
128 $ hg up -q --clean .
119 $ hg up -q --clean .
129 $ python <<EOF
120 $ python <<EOF
130 > fp = open('logfile', 'w')
121 > fp = open('logfile', 'w')
131 > fp.write('12345678901234567890123456789012345678901234567890' +
122 > fp.write('12345678901234567890123456789012345678901234567890' +
132 > '1234567890') # there are 5 more columns for 80 columns
123 > '1234567890') # there are 5 more columns for 80 columns
133 >
124 >
134 > # 2 x 4 = 8 columns, but 3 x 4 = 12 bytes
125 > # 2 x 4 = 8 columns, but 3 x 4 = 12 bytes
135 > fp.write(u'\u3042\u3044\u3046\u3048'.encode('utf-8'))
126 > fp.write(u'\u3042\u3044\u3046\u3048'.encode('utf-8'))
136 >
127 >
137 > fp.close()
128 > fp.close()
138 > EOF
129 > EOF
139 $ hg add logfile
130 $ hg add logfile
140 $ hg --encoding utf-8 commit --logfile logfile
131 $ hg --encoding utf-8 commit --logfile logfile
141
132
142 $ cat >> .hg/hgrc <<EOF
133 $ cat >> .hg/hgrc <<EOF
143 > [ui]
134 > [ui]
144 > mergemarkertemplate={desc|firstline}
135 > mergemarkertemplate={desc|firstline}
145 > EOF
136 > EOF
146
137
147 $ hg -q --encoding utf-8 merge 1
138 $ hg -q --encoding utf-8 merge 1
148 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
139 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
149 [1]
140 [1]
150
141
151 $ cat a
142 $ cat a
152 Small Mathematical Series.
143 Small Mathematical Series.
153 <<<<<<< local: 123456789012345678901234567890123456789012345678901234567890\xe3\x81\x82... (esc)
154 1
144 1
155 2
145 2
156 3
146 3
147 <<<<<<< local: 123456789012345678901234567890123456789012345678901234567890\xe3\x81\x82... (esc)
157 6
148 6
158 8
149 8
159 =======
150 =======
160 1
161 2
162 3
163 4
151 4
164 5
152 5
165 >>>>>>> other: branch1
153 >>>>>>> other: branch1
166 Hop we are done.
154 Hop we are done.
167
155
168 Verify basic conflict markers
156 Verify basic conflict markers
169
157
170 $ hg up -q --clean 2
158 $ hg up -q --clean 2
171 $ printf "\n[ui]\nmergemarkers=basic\n" >> .hg/hgrc
159 $ printf "\n[ui]\nmergemarkers=basic\n" >> .hg/hgrc
172
160
173 $ hg merge 1
161 $ hg merge 1
174 merging a
162 merging a
175 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
163 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
176 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
164 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
177 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
165 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
178 [1]
166 [1]
179
167
180 $ cat a
168 $ cat a
181 Small Mathematical Series.
169 Small Mathematical Series.
182 <<<<<<< local
183 1
170 1
184 2
171 2
185 3
172 3
173 <<<<<<< local
186 6
174 6
187 8
175 8
188 =======
176 =======
189 1
190 2
191 3
192 4
177 4
193 5
178 5
194 >>>>>>> other
179 >>>>>>> other
195 Hop we are done.
180 Hop we are done.
196
181
197 internal:merge3
182 internal:merge3
198
183
199 $ hg up -q --clean .
184 $ hg up -q --clean .
200
185
201 $ hg merge 1 --tool internal:merge3
186 $ hg merge 1 --tool internal:merge3
202 merging a
187 merging a
203 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
188 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
204 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
189 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
205 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
190 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
206 [1]
191 [1]
207 $ cat a
192 $ cat a
208 Small Mathematical Series.
193 Small Mathematical Series.
209 <<<<<<< local
194 <<<<<<< local
210 1
195 1
211 2
196 2
212 3
197 3
213 6
198 6
214 8
199 8
215 ||||||| base
200 ||||||| base
216 One
201 One
217 Two
202 Two
218 Three
203 Three
219 Four
204 Four
220 Five
205 Five
221 =======
206 =======
222 1
207 1
223 2
208 2
224 3
209 3
225 4
210 4
226 5
211 5
227 >>>>>>> other
212 >>>>>>> other
228 Hop we are done.
213 Hop we are done.
229
214
230 Add some unconflicting changes on each head, to make sure we really
215 Add some unconflicting changes on each head, to make sure we really
231 are merging, unlike :local and :other
216 are merging, unlike :local and :other
232
217
233 $ hg up -C
218 $ hg up -C
234 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
219 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
235 1 other heads for branch "default"
220 1 other heads for branch "default"
236 $ printf "\n\nEnd of file\n" >> a
221 $ printf "\n\nEnd of file\n" >> a
237 $ hg ci -m "Add some stuff at the end"
222 $ hg ci -m "Add some stuff at the end"
238 $ hg up -r 1
223 $ hg up -r 1
239 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
224 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
240 $ printf "Start of file\n\n\n" > tmp
225 $ printf "Start of file\n\n\n" > tmp
241 $ cat a >> tmp
226 $ cat a >> tmp
242 $ mv tmp a
227 $ mv tmp a
243 $ hg ci -m "Add some stuff at the beginning"
228 $ hg ci -m "Add some stuff at the beginning"
244
229
245 Now test :merge-other and :merge-local
230 Now test :merge-other and :merge-local
246
231
247 $ hg merge
232 $ hg merge
248 merging a
233 merging a
249 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
234 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
250 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
235 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
251 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
236 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
252 [1]
237 [1]
253 $ hg resolve --tool :merge-other a
238 $ hg resolve --tool :merge-other a
254 merging a
239 merging a
255 (no more unresolved files)
240 (no more unresolved files)
256 $ cat a
241 $ cat a
257 Start of file
242 Start of file
258
243
259
244
260 Small Mathematical Series.
245 Small Mathematical Series.
261 1
246 1
262 2
247 2
263 3
248 3
264 6
249 6
265 8
250 8
266 Hop we are done.
251 Hop we are done.
267
252
268
253
269 End of file
254 End of file
270
255
271 $ hg up -C
256 $ hg up -C
272 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
257 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
273 1 other heads for branch "default"
258 1 other heads for branch "default"
274 $ hg merge --tool :merge-local
259 $ hg merge --tool :merge-local
275 merging a
260 merging a
276 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
261 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
277 (branch merge, don't forget to commit)
262 (branch merge, don't forget to commit)
278 $ cat a
263 $ cat a
279 Start of file
264 Start of file
280
265
281
266
282 Small Mathematical Series.
267 Small Mathematical Series.
283 1
268 1
284 2
269 2
285 3
270 3
286 4
271 4
287 5
272 5
288 Hop we are done.
273 Hop we are done.
289
274
290
275
291 End of file
276 End of file
@@ -1,279 +1,276 b''
1 Set vars:
1 Set vars:
2
2
3 $ CONTRIBDIR="$TESTDIR/../contrib"
3 $ CONTRIBDIR="$TESTDIR/../contrib"
4
4
5 Prepare repo-a:
5 Prepare repo-a:
6
6
7 $ hg init repo-a
7 $ hg init repo-a
8 $ cd repo-a
8 $ cd repo-a
9
9
10 $ echo this is file a > a
10 $ echo this is file a > a
11 $ hg add a
11 $ hg add a
12 $ hg commit -m first
12 $ hg commit -m first
13
13
14 $ echo adding to file a >> a
14 $ echo adding to file a >> a
15 $ hg commit -m second
15 $ hg commit -m second
16
16
17 $ echo adding more to file a >> a
17 $ echo adding more to file a >> a
18 $ hg commit -m third
18 $ hg commit -m third
19
19
20 $ hg verify
20 $ hg verify
21 checking changesets
21 checking changesets
22 checking manifests
22 checking manifests
23 crosschecking files in changesets and manifests
23 crosschecking files in changesets and manifests
24 checking files
24 checking files
25 1 files, 3 changesets, 3 total revisions
25 1 files, 3 changesets, 3 total revisions
26
26
27 Dumping revlog of file a to stdout:
27 Dumping revlog of file a to stdout:
28
28
29 $ python "$CONTRIBDIR/dumprevlog" .hg/store/data/a.i
29 $ python "$CONTRIBDIR/dumprevlog" .hg/store/data/a.i
30 file: .hg/store/data/a.i
30 file: .hg/store/data/a.i
31 node: 183d2312b35066fb6b3b449b84efc370d50993d0
31 node: 183d2312b35066fb6b3b449b84efc370d50993d0
32 linkrev: 0
32 linkrev: 0
33 parents: 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
33 parents: 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
34 length: 15
34 length: 15
35 -start-
35 -start-
36 this is file a
36 this is file a
37
37
38 -end-
38 -end-
39 node: b1047953b6e6b633c0d8197eaa5116fbdfd3095b
39 node: b1047953b6e6b633c0d8197eaa5116fbdfd3095b
40 linkrev: 1
40 linkrev: 1
41 parents: 183d2312b35066fb6b3b449b84efc370d50993d0 0000000000000000000000000000000000000000
41 parents: 183d2312b35066fb6b3b449b84efc370d50993d0 0000000000000000000000000000000000000000
42 length: 32
42 length: 32
43 -start-
43 -start-
44 this is file a
44 this is file a
45 adding to file a
45 adding to file a
46
46
47 -end-
47 -end-
48 node: 8c4fd1f7129b8cdec6c7f58bf48fb5237a4030c1
48 node: 8c4fd1f7129b8cdec6c7f58bf48fb5237a4030c1
49 linkrev: 2
49 linkrev: 2
50 parents: b1047953b6e6b633c0d8197eaa5116fbdfd3095b 0000000000000000000000000000000000000000
50 parents: b1047953b6e6b633c0d8197eaa5116fbdfd3095b 0000000000000000000000000000000000000000
51 length: 54
51 length: 54
52 -start-
52 -start-
53 this is file a
53 this is file a
54 adding to file a
54 adding to file a
55 adding more to file a
55 adding more to file a
56
56
57 -end-
57 -end-
58
58
59 Dump all revlogs to file repo.dump:
59 Dump all revlogs to file repo.dump:
60
60
61 $ find .hg/store -name "*.i" | sort | xargs python "$CONTRIBDIR/dumprevlog" > ../repo.dump
61 $ find .hg/store -name "*.i" | sort | xargs python "$CONTRIBDIR/dumprevlog" > ../repo.dump
62 $ cd ..
62 $ cd ..
63
63
64 Undumping into repo-b:
64 Undumping into repo-b:
65
65
66 $ hg init repo-b
66 $ hg init repo-b
67 $ cd repo-b
67 $ cd repo-b
68 $ python "$CONTRIBDIR/undumprevlog" < ../repo.dump
68 $ python "$CONTRIBDIR/undumprevlog" < ../repo.dump
69 .hg/store/00changelog.i
69 .hg/store/00changelog.i
70 .hg/store/00manifest.i
70 .hg/store/00manifest.i
71 .hg/store/data/a.i
71 .hg/store/data/a.i
72 $ cd ..
72 $ cd ..
73
73
74 Rebuild fncache with clone --pull:
74 Rebuild fncache with clone --pull:
75
75
76 $ hg clone --pull -U repo-b repo-c
76 $ hg clone --pull -U repo-b repo-c
77 requesting all changes
77 requesting all changes
78 adding changesets
78 adding changesets
79 adding manifests
79 adding manifests
80 adding file changes
80 adding file changes
81 added 3 changesets with 3 changes to 1 files
81 added 3 changesets with 3 changes to 1 files
82
82
83 Verify:
83 Verify:
84
84
85 $ hg -R repo-c verify
85 $ hg -R repo-c verify
86 checking changesets
86 checking changesets
87 checking manifests
87 checking manifests
88 crosschecking files in changesets and manifests
88 crosschecking files in changesets and manifests
89 checking files
89 checking files
90 1 files, 3 changesets, 3 total revisions
90 1 files, 3 changesets, 3 total revisions
91
91
92 Compare repos:
92 Compare repos:
93
93
94 $ hg -R repo-c incoming repo-a
94 $ hg -R repo-c incoming repo-a
95 comparing with repo-a
95 comparing with repo-a
96 searching for changes
96 searching for changes
97 no changes found
97 no changes found
98 [1]
98 [1]
99
99
100 $ hg -R repo-a incoming repo-c
100 $ hg -R repo-a incoming repo-c
101 comparing with repo-c
101 comparing with repo-c
102 searching for changes
102 searching for changes
103 no changes found
103 no changes found
104 [1]
104 [1]
105
105
106 Test simplemerge command:
106 Test simplemerge command:
107
107
108 $ cp "$CONTRIBDIR/simplemerge" .
108 $ cp "$CONTRIBDIR/simplemerge" .
109 $ echo base > base
109 $ echo base > base
110 $ echo local > local
110 $ echo local > local
111 $ cat base >> local
111 $ cat base >> local
112 $ cp local orig
112 $ cp local orig
113 $ cat base > other
113 $ cat base > other
114 $ echo other >> other
114 $ echo other >> other
115
115
116 changing local directly
116 changing local directly
117
117
118 $ python simplemerge local base other && echo "merge succeeded"
118 $ python simplemerge local base other && echo "merge succeeded"
119 merge succeeded
119 merge succeeded
120 $ cat local
120 $ cat local
121 local
121 local
122 base
122 base
123 other
123 other
124 $ cp orig local
124 $ cp orig local
125
125
126 printing to stdout
126 printing to stdout
127
127
128 $ python simplemerge -p local base other
128 $ python simplemerge -p local base other
129 local
129 local
130 base
130 base
131 other
131 other
132
132
133 local:
133 local:
134
134
135 $ cat local
135 $ cat local
136 local
136 local
137 base
137 base
138
138
139 conflicts
139 conflicts
140
140
141 $ cp base conflict-local
141 $ cp base conflict-local
142 $ cp other conflict-other
142 $ cp other conflict-other
143 $ echo not other >> conflict-local
143 $ echo not other >> conflict-local
144 $ echo end >> conflict-local
144 $ echo end >> conflict-local
145 $ echo end >> conflict-other
145 $ echo end >> conflict-other
146
146
147 $ python simplemerge -p conflict-local base conflict-other
147 $ python simplemerge -p conflict-local base conflict-other
148 base
148 base
149 <<<<<<< conflict-local
149 <<<<<<< conflict-local
150 not other
150 not other
151 end
152 =======
151 =======
153 other
152 other
153 >>>>>>> conflict-other
154 end
154 end
155 >>>>>>> conflict-other
156 [1]
155 [1]
157
156
158 1 label
157 1 label
159
158
160 $ python simplemerge -p -L foo conflict-local base conflict-other
159 $ python simplemerge -p -L foo conflict-local base conflict-other
161 base
160 base
162 <<<<<<< foo
161 <<<<<<< foo
163 not other
162 not other
164 end
165 =======
163 =======
166 other
164 other
165 >>>>>>> conflict-other
167 end
166 end
168 >>>>>>> conflict-other
169 [1]
167 [1]
170
168
171 2 labels
169 2 labels
172
170
173 $ python simplemerge -p -L foo -L bar conflict-local base conflict-other
171 $ python simplemerge -p -L foo -L bar conflict-local base conflict-other
174 base
172 base
175 <<<<<<< foo
173 <<<<<<< foo
176 not other
174 not other
177 end
178 =======
175 =======
179 other
176 other
177 >>>>>>> bar
180 end
178 end
181 >>>>>>> bar
182 [1]
179 [1]
183
180
184 3 labels
181 3 labels
185
182
186 $ python simplemerge -p -L foo -L bar -L base conflict-local base conflict-other
183 $ python simplemerge -p -L foo -L bar -L base conflict-local base conflict-other
187 base
184 base
188 <<<<<<< foo
185 <<<<<<< foo
189 not other
186 not other
190 end
187 end
191 ||||||| base
188 ||||||| base
192 =======
189 =======
193 other
190 other
194 end
191 end
195 >>>>>>> bar
192 >>>>>>> bar
196 [1]
193 [1]
197
194
198 too many labels
195 too many labels
199
196
200 $ python simplemerge -p -L foo -L bar -L baz -L buz conflict-local base conflict-other
197 $ python simplemerge -p -L foo -L bar -L baz -L buz conflict-local base conflict-other
201 abort: can only specify three labels.
198 abort: can only specify three labels.
202 [255]
199 [255]
203
200
204 binary file
201 binary file
205
202
206 $ $PYTHON -c "f = file('binary-local', 'w'); f.write('\x00'); f.close()"
203 $ $PYTHON -c "f = file('binary-local', 'w'); f.write('\x00'); f.close()"
207 $ cat orig >> binary-local
204 $ cat orig >> binary-local
208 $ python simplemerge -p binary-local base other
205 $ python simplemerge -p binary-local base other
209 warning: binary-local looks like a binary file.
206 warning: binary-local looks like a binary file.
210 [1]
207 [1]
211
208
212 binary file --text
209 binary file --text
213
210
214 $ python simplemerge -a -p binary-local base other 2>&1
211 $ python simplemerge -a -p binary-local base other 2>&1
215 warning: binary-local looks like a binary file.
212 warning: binary-local looks like a binary file.
216 \x00local (esc)
213 \x00local (esc)
217 base
214 base
218 other
215 other
219
216
220 help
217 help
221
218
222 $ python simplemerge --help
219 $ python simplemerge --help
223 simplemerge [OPTS] LOCAL BASE OTHER
220 simplemerge [OPTS] LOCAL BASE OTHER
224
221
225 Simple three-way file merge utility with a minimal feature set.
222 Simple three-way file merge utility with a minimal feature set.
226
223
227 Apply to LOCAL the changes necessary to go from BASE to OTHER.
224 Apply to LOCAL the changes necessary to go from BASE to OTHER.
228
225
229 By default, LOCAL is overwritten with the results of this operation.
226 By default, LOCAL is overwritten with the results of this operation.
230
227
231 options:
228 options:
232 -L --label labels to use on conflict markers
229 -L --label labels to use on conflict markers
233 -a --text treat all files as text
230 -a --text treat all files as text
234 -p --print print results instead of overwriting LOCAL
231 -p --print print results instead of overwriting LOCAL
235 --no-minimal no effect (DEPRECATED)
232 --no-minimal no effect (DEPRECATED)
236 -h --help display help and exit
233 -h --help display help and exit
237 -q --quiet suppress output
234 -q --quiet suppress output
238
235
239 wrong number of arguments
236 wrong number of arguments
240
237
241 $ python simplemerge
238 $ python simplemerge
242 simplemerge: wrong number of arguments
239 simplemerge: wrong number of arguments
243 simplemerge [OPTS] LOCAL BASE OTHER
240 simplemerge [OPTS] LOCAL BASE OTHER
244
241
245 Simple three-way file merge utility with a minimal feature set.
242 Simple three-way file merge utility with a minimal feature set.
246
243
247 Apply to LOCAL the changes necessary to go from BASE to OTHER.
244 Apply to LOCAL the changes necessary to go from BASE to OTHER.
248
245
249 By default, LOCAL is overwritten with the results of this operation.
246 By default, LOCAL is overwritten with the results of this operation.
250
247
251 options:
248 options:
252 -L --label labels to use on conflict markers
249 -L --label labels to use on conflict markers
253 -a --text treat all files as text
250 -a --text treat all files as text
254 -p --print print results instead of overwriting LOCAL
251 -p --print print results instead of overwriting LOCAL
255 --no-minimal no effect (DEPRECATED)
252 --no-minimal no effect (DEPRECATED)
256 -h --help display help and exit
253 -h --help display help and exit
257 -q --quiet suppress output
254 -q --quiet suppress output
258 [1]
255 [1]
259
256
260 bad option
257 bad option
261
258
262 $ python simplemerge --foo -p local base other
259 $ python simplemerge --foo -p local base other
263 simplemerge: option --foo not recognized
260 simplemerge: option --foo not recognized
264 simplemerge [OPTS] LOCAL BASE OTHER
261 simplemerge [OPTS] LOCAL BASE OTHER
265
262
266 Simple three-way file merge utility with a minimal feature set.
263 Simple three-way file merge utility with a minimal feature set.
267
264
268 Apply to LOCAL the changes necessary to go from BASE to OTHER.
265 Apply to LOCAL the changes necessary to go from BASE to OTHER.
269
266
270 By default, LOCAL is overwritten with the results of this operation.
267 By default, LOCAL is overwritten with the results of this operation.
271
268
272 options:
269 options:
273 -L --label labels to use on conflict markers
270 -L --label labels to use on conflict markers
274 -a --text treat all files as text
271 -a --text treat all files as text
275 -p --print print results instead of overwriting LOCAL
272 -p --print print results instead of overwriting LOCAL
276 --no-minimal no effect (DEPRECATED)
273 --no-minimal no effect (DEPRECATED)
277 -h --help display help and exit
274 -h --help display help and exit
278 -q --quiet suppress output
275 -q --quiet suppress output
279 [1]
276 [1]
@@ -1,307 +1,359 b''
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [format]
2 > [format]
3 > usegeneraldelta=yes
3 > usegeneraldelta=yes
4 > [extensions]
4 > [extensions]
5 > rebase=
5 > rebase=
6 >
6 >
7 > [phases]
7 > [phases]
8 > publish=False
8 > publish=False
9 >
9 >
10 > [alias]
10 > [alias]
11 > tglog = log -G --template "{rev}:{phase} '{desc}' {branches} {bookmarks}\n"
11 > tglog = log -G --template "{rev}:{phase} '{desc}' {branches} {bookmarks}\n"
12 > EOF
12 > EOF
13
13
14 $ hg init a
14 $ hg init a
15 $ cd a
15 $ cd a
16 $ echo c1 >common
16 $ echo c1 >common
17 $ hg add common
17 $ hg add common
18 $ hg ci -m C1
18 $ hg ci -m C1
19
19
20 $ echo c2 >>common
20 $ echo c2 >>common
21 $ hg ci -m C2
21 $ hg ci -m C2
22
22
23 $ echo c3 >>common
23 $ echo c3 >>common
24 $ hg ci -m C3
24 $ hg ci -m C3
25
25
26 $ hg up -q -C 1
26 $ hg up -q -C 1
27
27
28 $ echo l1 >>extra
28 $ echo l1 >>extra
29 $ hg add extra
29 $ hg add extra
30 $ hg ci -m L1
30 $ hg ci -m L1
31 created new head
31 created new head
32
32
33 $ sed -e 's/c2/l2/' common > common.new
33 $ sed -e 's/c2/l2/' common > common.new
34 $ mv common.new common
34 $ mv common.new common
35 $ hg ci -m L2
35 $ hg ci -m L2
36
36
37 $ echo l3 >> extra2
37 $ echo l3 >> extra2
38 $ hg add extra2
38 $ hg add extra2
39 $ hg ci -m L3
39 $ hg ci -m L3
40 $ hg bookmark mybook
40 $ hg bookmark mybook
41
41
42 $ hg phase --force --secret 4
42 $ hg phase --force --secret 4
43
43
44 $ hg tglog
44 $ hg tglog
45 @ 5:secret 'L3' mybook
45 @ 5:secret 'L3' mybook
46 |
46 |
47 o 4:secret 'L2'
47 o 4:secret 'L2'
48 |
48 |
49 o 3:draft 'L1'
49 o 3:draft 'L1'
50 |
50 |
51 | o 2:draft 'C3'
51 | o 2:draft 'C3'
52 |/
52 |/
53 o 1:draft 'C2'
53 o 1:draft 'C2'
54 |
54 |
55 o 0:draft 'C1'
55 o 0:draft 'C1'
56
56
57 Try to call --continue:
57 Try to call --continue:
58
58
59 $ hg rebase --continue
59 $ hg rebase --continue
60 abort: no rebase in progress
60 abort: no rebase in progress
61 [255]
61 [255]
62
62
63 Conflicting rebase:
63 Conflicting rebase:
64
64
65 $ hg rebase -s 3 -d 2
65 $ hg rebase -s 3 -d 2
66 rebasing 3:3163e20567cc "L1"
66 rebasing 3:3163e20567cc "L1"
67 rebasing 4:46f0b057b5c0 "L2"
67 rebasing 4:46f0b057b5c0 "L2"
68 merging common
68 merging common
69 warning: conflicts while merging common! (edit, then use 'hg resolve --mark')
69 warning: conflicts while merging common! (edit, then use 'hg resolve --mark')
70 unresolved conflicts (see hg resolve, then hg rebase --continue)
70 unresolved conflicts (see hg resolve, then hg rebase --continue)
71 [1]
71 [1]
72
72
73 Try to continue without solving the conflict:
73 Try to continue without solving the conflict:
74
74
75 $ hg rebase --continue
75 $ hg rebase --continue
76 already rebased 3:3163e20567cc "L1" as 3e046f2ecedb
76 already rebased 3:3163e20567cc "L1" as 3e046f2ecedb
77 rebasing 4:46f0b057b5c0 "L2"
77 rebasing 4:46f0b057b5c0 "L2"
78 abort: unresolved merge conflicts (see "hg help resolve")
78 abort: unresolved merge conflicts (see "hg help resolve")
79 [255]
79 [255]
80
80
81 Conclude rebase:
81 Conclude rebase:
82
82
83 $ echo 'resolved merge' >common
83 $ echo 'resolved merge' >common
84 $ hg resolve -m common
84 $ hg resolve -m common
85 (no more unresolved files)
85 (no more unresolved files)
86 continue: hg rebase --continue
86 continue: hg rebase --continue
87 $ hg rebase --continue
87 $ hg rebase --continue
88 already rebased 3:3163e20567cc "L1" as 3e046f2ecedb
88 already rebased 3:3163e20567cc "L1" as 3e046f2ecedb
89 rebasing 4:46f0b057b5c0 "L2"
89 rebasing 4:46f0b057b5c0 "L2"
90 rebasing 5:8029388f38dc "L3" (mybook)
90 rebasing 5:8029388f38dc "L3" (mybook)
91 saved backup bundle to $TESTTMP/a/.hg/strip-backup/3163e20567cc-5ca4656e-backup.hg (glob)
91 saved backup bundle to $TESTTMP/a/.hg/strip-backup/3163e20567cc-5ca4656e-backup.hg (glob)
92
92
93 $ hg tglog
93 $ hg tglog
94 @ 5:secret 'L3' mybook
94 @ 5:secret 'L3' mybook
95 |
95 |
96 o 4:secret 'L2'
96 o 4:secret 'L2'
97 |
97 |
98 o 3:draft 'L1'
98 o 3:draft 'L1'
99 |
99 |
100 o 2:draft 'C3'
100 o 2:draft 'C3'
101 |
101 |
102 o 1:draft 'C2'
102 o 1:draft 'C2'
103 |
103 |
104 o 0:draft 'C1'
104 o 0:draft 'C1'
105
105
106 Check correctness:
106 Check correctness:
107
107
108 $ hg cat -r 0 common
108 $ hg cat -r 0 common
109 c1
109 c1
110
110
111 $ hg cat -r 1 common
111 $ hg cat -r 1 common
112 c1
112 c1
113 c2
113 c2
114
114
115 $ hg cat -r 2 common
115 $ hg cat -r 2 common
116 c1
116 c1
117 c2
117 c2
118 c3
118 c3
119
119
120 $ hg cat -r 3 common
120 $ hg cat -r 3 common
121 c1
121 c1
122 c2
122 c2
123 c3
123 c3
124
124
125 $ hg cat -r 4 common
125 $ hg cat -r 4 common
126 resolved merge
126 resolved merge
127
127
128 $ hg cat -r 5 common
128 $ hg cat -r 5 common
129 resolved merge
129 resolved merge
130
130
131 Bookmark stays active after --continue
131 Bookmark stays active after --continue
132 $ hg bookmarks
132 $ hg bookmarks
133 * mybook 5:d67b21408fc0
133 * mybook 5:d67b21408fc0
134
134
135 $ cd ..
135 $ cd ..
136
136
137 Check that the right ancestors is used while rebasing a merge (issue4041)
137 Check that the right ancestors is used while rebasing a merge (issue4041)
138
138
139 $ hg clone "$TESTDIR/bundles/issue4041.hg" issue4041
139 $ hg clone "$TESTDIR/bundles/issue4041.hg" issue4041
140 requesting all changes
140 requesting all changes
141 adding changesets
141 adding changesets
142 adding manifests
142 adding manifests
143 adding file changes
143 adding file changes
144 added 11 changesets with 8 changes to 3 files (+1 heads)
144 added 11 changesets with 8 changes to 3 files (+1 heads)
145 updating to branch default
145 updating to branch default
146 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
146 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
147 $ cd issue4041
147 $ cd issue4041
148 $ hg log -G
148 $ hg log -G
149 o changeset: 10:2f2496ddf49d
149 o changeset: 10:2f2496ddf49d
150 |\ branch: f1
150 |\ branch: f1
151 | | tag: tip
151 | | tag: tip
152 | | parent: 7:4c9fbe56a16f
152 | | parent: 7:4c9fbe56a16f
153 | | parent: 9:e31216eec445
153 | | parent: 9:e31216eec445
154 | | user: szhang
154 | | user: szhang
155 | | date: Thu Sep 05 12:59:39 2013 -0400
155 | | date: Thu Sep 05 12:59:39 2013 -0400
156 | | summary: merge
156 | | summary: merge
157 | |
157 | |
158 | o changeset: 9:e31216eec445
158 | o changeset: 9:e31216eec445
159 | | branch: f1
159 | | branch: f1
160 | | user: szhang
160 | | user: szhang
161 | | date: Thu Sep 05 12:59:10 2013 -0400
161 | | date: Thu Sep 05 12:59:10 2013 -0400
162 | | summary: more changes to f1
162 | | summary: more changes to f1
163 | |
163 | |
164 | o changeset: 8:8e4e2c1a07ae
164 | o changeset: 8:8e4e2c1a07ae
165 | |\ branch: f1
165 | |\ branch: f1
166 | | | parent: 2:4bc80088dc6b
166 | | | parent: 2:4bc80088dc6b
167 | | | parent: 6:400110238667
167 | | | parent: 6:400110238667
168 | | | user: szhang
168 | | | user: szhang
169 | | | date: Thu Sep 05 12:57:59 2013 -0400
169 | | | date: Thu Sep 05 12:57:59 2013 -0400
170 | | | summary: bad merge
170 | | | summary: bad merge
171 | | |
171 | | |
172 o | | changeset: 7:4c9fbe56a16f
172 o | | changeset: 7:4c9fbe56a16f
173 |/ / branch: f1
173 |/ / branch: f1
174 | | parent: 2:4bc80088dc6b
174 | | parent: 2:4bc80088dc6b
175 | | user: szhang
175 | | user: szhang
176 | | date: Thu Sep 05 12:54:00 2013 -0400
176 | | date: Thu Sep 05 12:54:00 2013 -0400
177 | | summary: changed f1
177 | | summary: changed f1
178 | |
178 | |
179 | o changeset: 6:400110238667
179 | o changeset: 6:400110238667
180 | | branch: f2
180 | | branch: f2
181 | | parent: 4:12e8ec6bb010
181 | | parent: 4:12e8ec6bb010
182 | | user: szhang
182 | | user: szhang
183 | | date: Tue Sep 03 13:58:02 2013 -0400
183 | | date: Tue Sep 03 13:58:02 2013 -0400
184 | | summary: changed f2 on f2
184 | | summary: changed f2 on f2
185 | |
185 | |
186 | | @ changeset: 5:d79e2059b5c0
186 | | @ changeset: 5:d79e2059b5c0
187 | | | parent: 3:8a951942e016
187 | | | parent: 3:8a951942e016
188 | | | user: szhang
188 | | | user: szhang
189 | | | date: Tue Sep 03 13:57:39 2013 -0400
189 | | | date: Tue Sep 03 13:57:39 2013 -0400
190 | | | summary: changed f2 on default
190 | | | summary: changed f2 on default
191 | | |
191 | | |
192 | o | changeset: 4:12e8ec6bb010
192 | o | changeset: 4:12e8ec6bb010
193 | |/ branch: f2
193 | |/ branch: f2
194 | | user: szhang
194 | | user: szhang
195 | | date: Tue Sep 03 13:57:18 2013 -0400
195 | | date: Tue Sep 03 13:57:18 2013 -0400
196 | | summary: created f2 branch
196 | | summary: created f2 branch
197 | |
197 | |
198 | o changeset: 3:8a951942e016
198 | o changeset: 3:8a951942e016
199 | | parent: 0:24797d4f68de
199 | | parent: 0:24797d4f68de
200 | | user: szhang
200 | | user: szhang
201 | | date: Tue Sep 03 13:57:11 2013 -0400
201 | | date: Tue Sep 03 13:57:11 2013 -0400
202 | | summary: added f2.txt
202 | | summary: added f2.txt
203 | |
203 | |
204 o | changeset: 2:4bc80088dc6b
204 o | changeset: 2:4bc80088dc6b
205 | | branch: f1
205 | | branch: f1
206 | | user: szhang
206 | | user: szhang
207 | | date: Tue Sep 03 13:56:20 2013 -0400
207 | | date: Tue Sep 03 13:56:20 2013 -0400
208 | | summary: added f1.txt
208 | | summary: added f1.txt
209 | |
209 | |
210 o | changeset: 1:ef53c9e6b608
210 o | changeset: 1:ef53c9e6b608
211 |/ branch: f1
211 |/ branch: f1
212 | user: szhang
212 | user: szhang
213 | date: Tue Sep 03 13:55:26 2013 -0400
213 | date: Tue Sep 03 13:55:26 2013 -0400
214 | summary: created f1 branch
214 | summary: created f1 branch
215 |
215 |
216 o changeset: 0:24797d4f68de
216 o changeset: 0:24797d4f68de
217 user: szhang
217 user: szhang
218 date: Tue Sep 03 13:55:08 2013 -0400
218 date: Tue Sep 03 13:55:08 2013 -0400
219 summary: added default.txt
219 summary: added default.txt
220
220
221 $ hg rebase -s9 -d2 --debug # use debug to really check merge base used
221 $ hg rebase -s9 -d2 --debug # use debug to really check merge base used
222 rebase onto 2 starting from e31216eec445
222 rebase onto 2 starting from e31216eec445
223 ignoring null merge rebase of 3
223 ignoring null merge rebase of 3
224 ignoring null merge rebase of 4
224 ignoring null merge rebase of 4
225 ignoring null merge rebase of 6
225 ignoring null merge rebase of 6
226 ignoring null merge rebase of 8
226 ignoring null merge rebase of 8
227 rebasing 9:e31216eec445 "more changes to f1"
227 rebasing 9:e31216eec445 "more changes to f1"
228 future parents are 2 and -1
228 future parents are 2 and -1
229 rebase status stored
229 rebase status stored
230 update to 2:4bc80088dc6b
230 update to 2:4bc80088dc6b
231 resolving manifests
231 resolving manifests
232 branchmerge: False, force: True, partial: False
232 branchmerge: False, force: True, partial: False
233 ancestor: d79e2059b5c0+, local: d79e2059b5c0+, remote: 4bc80088dc6b
233 ancestor: d79e2059b5c0+, local: d79e2059b5c0+, remote: 4bc80088dc6b
234 f2.txt: other deleted -> r
234 f2.txt: other deleted -> r
235 removing f2.txt
235 removing f2.txt
236 f1.txt: remote created -> g
236 f1.txt: remote created -> g
237 getting f1.txt
237 getting f1.txt
238 merge against 9:e31216eec445
238 merge against 9:e31216eec445
239 detach base 8:8e4e2c1a07ae
239 detach base 8:8e4e2c1a07ae
240 searching for copies back to rev 3
240 searching for copies back to rev 3
241 resolving manifests
241 resolving manifests
242 branchmerge: True, force: True, partial: False
242 branchmerge: True, force: True, partial: False
243 ancestor: 8e4e2c1a07ae, local: 4bc80088dc6b+, remote: e31216eec445
243 ancestor: 8e4e2c1a07ae, local: 4bc80088dc6b+, remote: e31216eec445
244 f1.txt: remote is newer -> g
244 f1.txt: remote is newer -> g
245 getting f1.txt
245 getting f1.txt
246 committing files:
246 committing files:
247 f1.txt
247 f1.txt
248 committing manifest
248 committing manifest
249 committing changelog
249 committing changelog
250 rebased as 19c888675e13
250 rebased as 19c888675e13
251 rebasing 10:2f2496ddf49d "merge" (tip)
251 rebasing 10:2f2496ddf49d "merge" (tip)
252 future parents are 11 and 7
252 future parents are 11 and 7
253 rebase status stored
253 rebase status stored
254 already in target
254 already in target
255 merge against 10:2f2496ddf49d
255 merge against 10:2f2496ddf49d
256 detach base 9:e31216eec445
256 detach base 9:e31216eec445
257 searching for copies back to rev 3
257 searching for copies back to rev 3
258 resolving manifests
258 resolving manifests
259 branchmerge: True, force: True, partial: False
259 branchmerge: True, force: True, partial: False
260 ancestor: e31216eec445, local: 19c888675e13+, remote: 2f2496ddf49d
260 ancestor: e31216eec445, local: 19c888675e13+, remote: 2f2496ddf49d
261 f1.txt: remote is newer -> g
261 f1.txt: remote is newer -> g
262 getting f1.txt
262 getting f1.txt
263 committing files:
263 committing files:
264 f1.txt
264 f1.txt
265 committing manifest
265 committing manifest
266 committing changelog
266 committing changelog
267 rebased as 2a7f09cac94c
267 rebased as 2a7f09cac94c
268 rebase merging completed
268 rebase merging completed
269 update back to initial working directory parent
269 update back to initial working directory parent
270 resolving manifests
270 resolving manifests
271 branchmerge: False, force: False, partial: False
271 branchmerge: False, force: False, partial: False
272 ancestor: 2a7f09cac94c, local: 2a7f09cac94c+, remote: d79e2059b5c0
272 ancestor: 2a7f09cac94c, local: 2a7f09cac94c+, remote: d79e2059b5c0
273 f1.txt: other deleted -> r
273 f1.txt: other deleted -> r
274 removing f1.txt
274 removing f1.txt
275 f2.txt: remote created -> g
275 f2.txt: remote created -> g
276 getting f2.txt
276 getting f2.txt
277 2 changesets found
277 2 changesets found
278 list of changesets:
278 list of changesets:
279 e31216eec445e44352c5f01588856059466a24c9
279 e31216eec445e44352c5f01588856059466a24c9
280 2f2496ddf49d69b5ef23ad8cf9fb2e0e4faf0ac2
280 2f2496ddf49d69b5ef23ad8cf9fb2e0e4faf0ac2
281 bundle2-output-bundle: "HG20", (1 params) 1 parts total
281 bundle2-output-bundle: "HG20", (1 params) 1 parts total
282 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
282 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
283 saved backup bundle to $TESTTMP/issue4041/.hg/strip-backup/e31216eec445-15f7a814-backup.hg (glob)
283 saved backup bundle to $TESTTMP/issue4041/.hg/strip-backup/e31216eec445-15f7a814-backup.hg (glob)
284 3 changesets found
284 3 changesets found
285 list of changesets:
285 list of changesets:
286 4c9fbe56a16f30c0d5dcc40ec1a97bbe3325209c
286 4c9fbe56a16f30c0d5dcc40ec1a97bbe3325209c
287 19c888675e133ab5dff84516926a65672eaf04d9
287 19c888675e133ab5dff84516926a65672eaf04d9
288 2a7f09cac94c7f4b73ebd5cd1a62d3b2e8e336bf
288 2a7f09cac94c7f4b73ebd5cd1a62d3b2e8e336bf
289 bundle2-output-bundle: "HG20", 1 parts total
289 bundle2-output-bundle: "HG20", 1 parts total
290 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
290 bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
291 adding branch
291 adding branch
292 bundle2-input-bundle: with-transaction
292 bundle2-input-bundle: with-transaction
293 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
293 bundle2-input-part: "changegroup" (params: 1 mandatory) supported
294 adding changesets
294 adding changesets
295 add changeset 4c9fbe56a16f
295 add changeset 4c9fbe56a16f
296 add changeset 19c888675e13
296 add changeset 19c888675e13
297 add changeset 2a7f09cac94c
297 add changeset 2a7f09cac94c
298 adding manifests
298 adding manifests
299 adding file changes
299 adding file changes
300 adding f1.txt revisions
300 adding f1.txt revisions
301 added 2 changesets with 2 changes to 1 files
301 added 2 changesets with 2 changes to 1 files
302 bundle2-input-part: total payload size 1713
302 bundle2-input-part: total payload size 1713
303 bundle2-input-bundle: 0 parts total
303 bundle2-input-bundle: 0 parts total
304 invalid branchheads cache (served): tip differs
304 invalid branchheads cache (served): tip differs
305 rebase completed
305 rebase completed
306 updating the branch cache
306 updating the branch cache
307 truncating cache/rbc-revs-v1 to 72
307 truncating cache/rbc-revs-v1 to 72
308
309 Test minimization of merge conflicts
310 $ hg up -q null
311 $ echo a > a
312 $ hg add a
313 $ hg commit -q -m 'a'
314 $ echo b >> a
315 $ hg commit -q -m 'ab'
316 $ hg bookmark ab
317 $ hg up -q '.^'
318 $ echo b >> a
319 $ echo c >> a
320 $ hg commit -q -m 'abc'
321 $ hg rebase -s 7bc217434fc1 -d ab --keep
322 rebasing 13:7bc217434fc1 "abc" (tip)
323 merging a
324 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
325 unresolved conflicts (see hg resolve, then hg rebase --continue)
326 [1]
327 $ hg diff
328 diff -r 328e4ab1f7cc a
329 --- a/a Thu Jan 01 00:00:00 1970 +0000
330 +++ b/a * (glob)
331 @@ -1,2 +1,6 @@
332 a
333 b
334 +<<<<<<< dest: 328e4ab1f7cc ab - test: ab
335 +=======
336 +c
337 +>>>>>>> source: 7bc217434fc1 - test: abc
338 $ hg rebase --abort
339 rebase aborted
340 $ hg up -q -C 7bc217434fc1
341 $ hg rebase -s . -d ab --keep -t internal:merge3
342 rebasing 13:7bc217434fc1 "abc" (tip)
343 merging a
344 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
345 unresolved conflicts (see hg resolve, then hg rebase --continue)
346 [1]
347 $ hg diff
348 diff -r 328e4ab1f7cc a
349 --- a/a Thu Jan 01 00:00:00 1970 +0000
350 +++ b/a * (glob)
351 @@ -1,2 +1,8 @@
352 a
353 +<<<<<<< dest: 328e4ab1f7cc ab - test: ab
354 b
355 +||||||| base
356 +=======
357 +b
358 +c
359 +>>>>>>> source: 7bc217434fc1 - test: abc
General Comments 0
You need to be logged in to leave comments. Login now