##// END OF EJS Templates
copies: print debug information about copies per side/branch...
Martin von Zweigbergk -
r44679:17e12938 default
parent child Browse files
Show More
@@ -1,1150 +1,1151 b''
1 1 # copies.py - copy detection for Mercurial
2 2 #
3 3 # Copyright 2008 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import collections
11 11 import multiprocessing
12 12 import os
13 13
14 14 from .i18n import _
15 15
16 16
17 17 from .revlogutils.flagutil import REVIDX_SIDEDATA
18 18
19 19 from . import (
20 20 error,
21 21 match as matchmod,
22 22 node,
23 23 pathutil,
24 24 pycompat,
25 25 util,
26 26 )
27 27
28 28 from .revlogutils import sidedata as sidedatamod
29 29
30 30 from .utils import stringutil
31 31
32 32
33 33 def _filter(src, dst, t):
34 34 """filters out invalid copies after chaining"""
35 35
36 36 # When _chain()'ing copies in 'a' (from 'src' via some other commit 'mid')
37 37 # with copies in 'b' (from 'mid' to 'dst'), we can get the different cases
38 38 # in the following table (not including trivial cases). For example, case 2
39 39 # is where a file existed in 'src' and remained under that name in 'mid' and
40 40 # then was renamed between 'mid' and 'dst'.
41 41 #
42 42 # case src mid dst result
43 43 # 1 x y - -
44 44 # 2 x y y x->y
45 45 # 3 x y x -
46 46 # 4 x y z x->z
47 47 # 5 - x y -
48 48 # 6 x x y x->y
49 49 #
50 50 # _chain() takes care of chaining the copies in 'a' and 'b', but it
51 51 # cannot tell the difference between cases 1 and 2, between 3 and 4, or
52 52 # between 5 and 6, so it includes all cases in its result.
53 53 # Cases 1, 3, and 5 are then removed by _filter().
54 54
55 55 for k, v in list(t.items()):
56 56 # remove copies from files that didn't exist
57 57 if v not in src:
58 58 del t[k]
59 59 # remove criss-crossed copies
60 60 elif k in src and v in dst:
61 61 del t[k]
62 62 # remove copies to files that were then removed
63 63 elif k not in dst:
64 64 del t[k]
65 65
66 66
67 67 def _chain(prefix, suffix):
68 68 """chain two sets of copies 'prefix' and 'suffix'"""
69 69 result = prefix.copy()
70 70 for key, value in pycompat.iteritems(suffix):
71 71 result[key] = prefix.get(value, value)
72 72 return result
73 73
74 74
75 75 def _tracefile(fctx, am, basemf):
76 76 """return file context that is the ancestor of fctx present in ancestor
77 77 manifest am
78 78
79 79 Note: we used to try and stop after a given limit, however checking if that
80 80 limit is reached turned out to be very expensive. we are better off
81 81 disabling that feature."""
82 82
83 83 for f in fctx.ancestors():
84 84 path = f.path()
85 85 if am.get(path, None) == f.filenode():
86 86 return path
87 87 if basemf and basemf.get(path, None) == f.filenode():
88 88 return path
89 89
90 90
91 91 def _dirstatecopies(repo, match=None):
92 92 ds = repo.dirstate
93 93 c = ds.copies().copy()
94 94 for k in list(c):
95 95 if ds[k] not in b'anm' or (match and not match(k)):
96 96 del c[k]
97 97 return c
98 98
99 99
100 100 def _computeforwardmissing(a, b, match=None):
101 101 """Computes which files are in b but not a.
102 102 This is its own function so extensions can easily wrap this call to see what
103 103 files _forwardcopies is about to process.
104 104 """
105 105 ma = a.manifest()
106 106 mb = b.manifest()
107 107 return mb.filesnotin(ma, match=match)
108 108
109 109
110 110 def usechangesetcentricalgo(repo):
111 111 """Checks if we should use changeset-centric copy algorithms"""
112 112 if repo.filecopiesmode == b'changeset-sidedata':
113 113 return True
114 114 readfrom = repo.ui.config(b'experimental', b'copies.read-from')
115 115 changesetsource = (b'changeset-only', b'compatibility')
116 116 return readfrom in changesetsource
117 117
118 118
119 119 def _committedforwardcopies(a, b, base, match):
120 120 """Like _forwardcopies(), but b.rev() cannot be None (working copy)"""
121 121 # files might have to be traced back to the fctx parent of the last
122 122 # one-side-only changeset, but not further back than that
123 123 repo = a._repo
124 124
125 125 if usechangesetcentricalgo(repo):
126 126 return _changesetforwardcopies(a, b, match)
127 127
128 128 debug = repo.ui.debugflag and repo.ui.configbool(b'devel', b'debug.copies')
129 129 dbg = repo.ui.debug
130 130 if debug:
131 131 dbg(b'debug.copies: looking into rename from %s to %s\n' % (a, b))
132 132 am = a.manifest()
133 133 basemf = None if base is None else base.manifest()
134 134
135 135 # find where new files came from
136 136 # we currently don't try to find where old files went, too expensive
137 137 # this means we can miss a case like 'hg rm b; hg cp a b'
138 138 cm = {}
139 139
140 140 # Computing the forward missing is quite expensive on large manifests, since
141 141 # it compares the entire manifests. We can optimize it in the common use
142 142 # case of computing what copies are in a commit versus its parent (like
143 143 # during a rebase or histedit). Note, we exclude merge commits from this
144 144 # optimization, since the ctx.files() for a merge commit is not correct for
145 145 # this comparison.
146 146 forwardmissingmatch = match
147 147 if b.p1() == a and b.p2().node() == node.nullid:
148 148 filesmatcher = matchmod.exact(b.files())
149 149 forwardmissingmatch = matchmod.intersectmatchers(match, filesmatcher)
150 150 missing = _computeforwardmissing(a, b, match=forwardmissingmatch)
151 151
152 152 ancestrycontext = a._repo.changelog.ancestors([b.rev()], inclusive=True)
153 153
154 154 if debug:
155 155 dbg(b'debug.copies: missing files to search: %d\n' % len(missing))
156 156
157 157 for f in sorted(missing):
158 158 if debug:
159 159 dbg(b'debug.copies: tracing file: %s\n' % f)
160 160 fctx = b[f]
161 161 fctx._ancestrycontext = ancestrycontext
162 162
163 163 if debug:
164 164 start = util.timer()
165 165 opath = _tracefile(fctx, am, basemf)
166 166 if opath:
167 167 if debug:
168 168 dbg(b'debug.copies: rename of: %s\n' % opath)
169 169 cm[f] = opath
170 170 if debug:
171 171 dbg(
172 172 b'debug.copies: time: %f seconds\n'
173 173 % (util.timer() - start)
174 174 )
175 175 return cm
176 176
177 177
178 178 def _revinfogetter(repo):
179 179 """return a function that return multiple data given a <rev>"i
180 180
181 181 * p1: revision number of first parent
182 182 * p2: revision number of first parent
183 183 * p1copies: mapping of copies from p1
184 184 * p2copies: mapping of copies from p2
185 185 * removed: a list of removed files
186 186 """
187 187 cl = repo.changelog
188 188 parents = cl.parentrevs
189 189
190 190 if repo.filecopiesmode == b'changeset-sidedata':
191 191 changelogrevision = cl.changelogrevision
192 192 flags = cl.flags
193 193
194 194 # A small cache to avoid doing the work twice for merges
195 195 #
196 196 # In the vast majority of cases, if we ask information for a revision
197 197 # about 1 parent, we'll later ask it for the other. So it make sense to
198 198 # keep the information around when reaching the first parent of a merge
199 199 # and dropping it after it was provided for the second parents.
200 200 #
201 201 # It exists cases were only one parent of the merge will be walked. It
202 202 # happens when the "destination" the copy tracing is descendant from a
203 203 # new root, not common with the "source". In that case, we will only walk
204 204 # through merge parents that are descendant of changesets common
205 205 # between "source" and "destination".
206 206 #
207 207 # With the current case implementation if such changesets have a copy
208 208 # information, we'll keep them in memory until the end of
209 209 # _changesetforwardcopies. We don't expect the case to be frequent
210 210 # enough to matters.
211 211 #
212 212 # In addition, it would be possible to reach pathological case, were
213 213 # many first parent are met before any second parent is reached. In
214 214 # that case the cache could grow. If this even become an issue one can
215 215 # safely introduce a maximum cache size. This would trade extra CPU/IO
216 216 # time to save memory.
217 217 merge_caches = {}
218 218
219 219 def revinfo(rev):
220 220 p1, p2 = parents(rev)
221 221 if flags(rev) & REVIDX_SIDEDATA:
222 222 e = merge_caches.pop(rev, None)
223 223 if e is not None:
224 224 return e
225 225 c = changelogrevision(rev)
226 226 p1copies = c.p1copies
227 227 p2copies = c.p2copies
228 228 removed = c.filesremoved
229 229 if p1 != node.nullrev and p2 != node.nullrev:
230 230 # XXX some case we over cache, IGNORE
231 231 merge_caches[rev] = (p1, p2, p1copies, p2copies, removed)
232 232 else:
233 233 p1copies = {}
234 234 p2copies = {}
235 235 removed = []
236 236 return p1, p2, p1copies, p2copies, removed
237 237
238 238 else:
239 239
240 240 def revinfo(rev):
241 241 p1, p2 = parents(rev)
242 242 ctx = repo[rev]
243 243 p1copies, p2copies = ctx._copies
244 244 removed = ctx.filesremoved()
245 245 return p1, p2, p1copies, p2copies, removed
246 246
247 247 return revinfo
248 248
249 249
250 250 def _changesetforwardcopies(a, b, match):
251 251 if a.rev() in (node.nullrev, b.rev()):
252 252 return {}
253 253
254 254 repo = a.repo().unfiltered()
255 255 children = {}
256 256 revinfo = _revinfogetter(repo)
257 257
258 258 cl = repo.changelog
259 259 missingrevs = cl.findmissingrevs(common=[a.rev()], heads=[b.rev()])
260 260 mrset = set(missingrevs)
261 261 roots = set()
262 262 for r in missingrevs:
263 263 for p in cl.parentrevs(r):
264 264 if p == node.nullrev:
265 265 continue
266 266 if p not in children:
267 267 children[p] = [r]
268 268 else:
269 269 children[p].append(r)
270 270 if p not in mrset:
271 271 roots.add(p)
272 272 if not roots:
273 273 # no common revision to track copies from
274 274 return {}
275 275 min_root = min(roots)
276 276
277 277 from_head = set(
278 278 cl.reachableroots(min_root, [b.rev()], list(roots), includepath=True)
279 279 )
280 280
281 281 iterrevs = set(from_head)
282 282 iterrevs &= mrset
283 283 iterrevs.update(roots)
284 284 iterrevs.remove(b.rev())
285 285 revs = sorted(iterrevs)
286 286 return _combinechangesetcopies(revs, children, b.rev(), revinfo, match)
287 287
288 288
289 289 def _combinechangesetcopies(revs, children, targetrev, revinfo, match):
290 290 """combine the copies information for each item of iterrevs
291 291
292 292 revs: sorted iterable of revision to visit
293 293 children: a {parent: [children]} mapping.
294 294 targetrev: the final copies destination revision (not in iterrevs)
295 295 revinfo(rev): a function that return (p1, p2, p1copies, p2copies, removed)
296 296 match: a matcher
297 297
298 298 It returns the aggregated copies information for `targetrev`.
299 299 """
300 300 all_copies = {}
301 301 alwaysmatch = match.always()
302 302 for r in revs:
303 303 copies = all_copies.pop(r, None)
304 304 if copies is None:
305 305 # this is a root
306 306 copies = {}
307 307 for i, c in enumerate(children[r]):
308 308 p1, p2, p1copies, p2copies, removed = revinfo(c)
309 309 if r == p1:
310 310 parent = 1
311 311 childcopies = p1copies
312 312 else:
313 313 assert r == p2
314 314 parent = 2
315 315 childcopies = p2copies
316 316 if not alwaysmatch:
317 317 childcopies = {
318 318 dst: src for dst, src in childcopies.items() if match(dst)
319 319 }
320 320 newcopies = copies
321 321 if childcopies:
322 322 newcopies = _chain(newcopies, childcopies)
323 323 # _chain makes a copies, we can avoid doing so in some
324 324 # simple/linear cases.
325 325 assert newcopies is not copies
326 326 for f in removed:
327 327 if f in newcopies:
328 328 if newcopies is copies:
329 329 # copy on write to avoid affecting potential other
330 330 # branches. when there are no other branches, this
331 331 # could be avoided.
332 332 newcopies = copies.copy()
333 333 del newcopies[f]
334 334 othercopies = all_copies.get(c)
335 335 if othercopies is None:
336 336 all_copies[c] = newcopies
337 337 else:
338 338 # we are the second parent to work on c, we need to merge our
339 339 # work with the other.
340 340 #
341 341 # Unlike when copies are stored in the filelog, we consider
342 342 # it a copy even if the destination already existed on the
343 343 # other branch. It's simply too expensive to check if the
344 344 # file existed in the manifest.
345 345 #
346 346 # In case of conflict, parent 1 take precedence over parent 2.
347 347 # This is an arbitrary choice made anew when implementing
348 348 # changeset based copies. It was made without regards with
349 349 # potential filelog related behavior.
350 350 if parent == 1:
351 351 othercopies.update(newcopies)
352 352 else:
353 353 newcopies.update(othercopies)
354 354 all_copies[c] = newcopies
355 355 return all_copies[targetrev]
356 356
357 357
358 358 def _forwardcopies(a, b, base=None, match=None):
359 359 """find {dst@b: src@a} copy mapping where a is an ancestor of b"""
360 360
361 361 if base is None:
362 362 base = a
363 363 match = a.repo().narrowmatch(match)
364 364 # check for working copy
365 365 if b.rev() is None:
366 366 cm = _committedforwardcopies(a, b.p1(), base, match)
367 367 # combine copies from dirstate if necessary
368 368 copies = _chain(cm, _dirstatecopies(b._repo, match))
369 369 else:
370 370 copies = _committedforwardcopies(a, b, base, match)
371 371 return copies
372 372
373 373
374 374 def _backwardrenames(a, b, match):
375 375 if a._repo.ui.config(b'experimental', b'copytrace') == b'off':
376 376 return {}
377 377
378 378 # Even though we're not taking copies into account, 1:n rename situations
379 379 # can still exist (e.g. hg cp a b; hg mv a c). In those cases we
380 380 # arbitrarily pick one of the renames.
381 381 # We don't want to pass in "match" here, since that would filter
382 382 # the destination by it. Since we're reversing the copies, we want
383 383 # to filter the source instead.
384 384 f = _forwardcopies(b, a)
385 385 r = {}
386 386 for k, v in sorted(pycompat.iteritems(f)):
387 387 if match and not match(v):
388 388 continue
389 389 # remove copies
390 390 if v in a:
391 391 continue
392 392 r[v] = k
393 393 return r
394 394
395 395
396 396 def pathcopies(x, y, match=None):
397 397 """find {dst@y: src@x} copy mapping for directed compare"""
398 398 repo = x._repo
399 399 debug = repo.ui.debugflag and repo.ui.configbool(b'devel', b'debug.copies')
400 400 if debug:
401 401 repo.ui.debug(
402 402 b'debug.copies: searching copies from %s to %s\n' % (x, y)
403 403 )
404 404 if x == y or not x or not y:
405 405 return {}
406 406 a = y.ancestor(x)
407 407 if a == x:
408 408 if debug:
409 409 repo.ui.debug(b'debug.copies: search mode: forward\n')
410 410 if y.rev() is None and x == y.p1():
411 411 # short-circuit to avoid issues with merge states
412 412 return _dirstatecopies(repo, match)
413 413 copies = _forwardcopies(x, y, match=match)
414 414 elif a == y:
415 415 if debug:
416 416 repo.ui.debug(b'debug.copies: search mode: backward\n')
417 417 copies = _backwardrenames(x, y, match=match)
418 418 else:
419 419 if debug:
420 420 repo.ui.debug(b'debug.copies: search mode: combined\n')
421 421 base = None
422 422 if a.rev() != node.nullrev:
423 423 base = x
424 424 copies = _chain(
425 425 _backwardrenames(x, a, match=match),
426 426 _forwardcopies(a, y, base, match=match),
427 427 )
428 428 _filter(x, y, copies)
429 429 return copies
430 430
431 431
432 432 def mergecopies(repo, c1, c2, base):
433 433 """
434 434 Finds moves and copies between context c1 and c2 that are relevant for
435 435 merging. 'base' will be used as the merge base.
436 436
437 437 Copytracing is used in commands like rebase, merge, unshelve, etc to merge
438 438 files that were moved/ copied in one merge parent and modified in another.
439 439 For example:
440 440
441 441 o ---> 4 another commit
442 442 |
443 443 | o ---> 3 commit that modifies a.txt
444 444 | /
445 445 o / ---> 2 commit that moves a.txt to b.txt
446 446 |/
447 447 o ---> 1 merge base
448 448
449 449 If we try to rebase revision 3 on revision 4, since there is no a.txt in
450 450 revision 4, and if user have copytrace disabled, we prints the following
451 451 message:
452 452
453 453 ```other changed <file> which local deleted```
454 454
455 455 Returns five dicts: "copy", "movewithdir", "diverge", "renamedelete" and
456 456 "dirmove".
457 457
458 458 "copy" is a mapping from destination name -> source name,
459 459 where source is in c1 and destination is in c2 or vice-versa.
460 460
461 461 "movewithdir" is a mapping from source name -> destination name,
462 462 where the file at source present in one context but not the other
463 463 needs to be moved to destination by the merge process, because the
464 464 other context moved the directory it is in.
465 465
466 466 "diverge" is a mapping of source name -> list of destination names
467 467 for divergent renames.
468 468
469 469 "renamedelete" is a mapping of source name -> list of destination
470 470 names for files deleted in c1 that were renamed in c2 or vice-versa.
471 471
472 472 "dirmove" is a mapping of detected source dir -> destination dir renames.
473 473 This is needed for handling changes to new files previously grafted into
474 474 renamed directories.
475 475
476 476 This function calls different copytracing algorithms based on config.
477 477 """
478 478 # avoid silly behavior for update from empty dir
479 479 if not c1 or not c2 or c1 == c2:
480 480 return {}, {}, {}, {}, {}
481 481
482 482 narrowmatch = c1.repo().narrowmatch()
483 483
484 484 # avoid silly behavior for parent -> working dir
485 485 if c2.node() is None and c1.node() == repo.dirstate.p1():
486 486 return _dirstatecopies(repo, narrowmatch), {}, {}, {}, {}
487 487
488 488 copytracing = repo.ui.config(b'experimental', b'copytrace')
489 489 if stringutil.parsebool(copytracing) is False:
490 490 # stringutil.parsebool() returns None when it is unable to parse the
491 491 # value, so we should rely on making sure copytracing is on such cases
492 492 return {}, {}, {}, {}, {}
493 493
494 494 if usechangesetcentricalgo(repo):
495 495 # The heuristics don't make sense when we need changeset-centric algos
496 496 return _fullcopytracing(repo, c1, c2, base)
497 497
498 498 # Copy trace disabling is explicitly below the node == p1 logic above
499 499 # because the logic above is required for a simple copy to be kept across a
500 500 # rebase.
501 501 if copytracing == b'heuristics':
502 502 # Do full copytracing if only non-public revisions are involved as
503 503 # that will be fast enough and will also cover the copies which could
504 504 # be missed by heuristics
505 505 if _isfullcopytraceable(repo, c1, base):
506 506 return _fullcopytracing(repo, c1, c2, base)
507 507 return _heuristicscopytracing(repo, c1, c2, base)
508 508 else:
509 509 return _fullcopytracing(repo, c1, c2, base)
510 510
511 511
512 512 def _isfullcopytraceable(repo, c1, base):
513 513 """ Checks that if base, source and destination are all no-public branches,
514 514 if yes let's use the full copytrace algorithm for increased capabilities
515 515 since it will be fast enough.
516 516
517 517 `experimental.copytrace.sourcecommitlimit` can be used to set a limit for
518 518 number of changesets from c1 to base such that if number of changesets are
519 519 more than the limit, full copytracing algorithm won't be used.
520 520 """
521 521 if c1.rev() is None:
522 522 c1 = c1.p1()
523 523 if c1.mutable() and base.mutable():
524 524 sourcecommitlimit = repo.ui.configint(
525 525 b'experimental', b'copytrace.sourcecommitlimit'
526 526 )
527 527 commits = len(repo.revs(b'%d::%d', base.rev(), c1.rev()))
528 528 return commits < sourcecommitlimit
529 529 return False
530 530
531 531
532 532 def _checksinglesidecopies(
533 533 src, dsts1, m1, m2, mb, c2, base, copy, renamedelete
534 534 ):
535 535 if src not in m2:
536 536 # deleted on side 2
537 537 if src not in m1:
538 538 # renamed on side 1, deleted on side 2
539 539 renamedelete[src] = dsts1
540 540 elif m2[src] != mb[src]:
541 541 if not _related(c2[src], base[src]):
542 542 return
543 543 # modified on side 2
544 544 for dst in dsts1:
545 545 if dst not in m2:
546 546 # dst not added on side 2 (handle as regular
547 547 # "both created" case in manifestmerge otherwise)
548 548 copy[dst] = src
549 549
550 550
551 551 def _fullcopytracing(repo, c1, c2, base):
552 552 """ The full copytracing algorithm which finds all the new files that were
553 553 added from merge base up to the top commit and for each file it checks if
554 554 this file was copied from another file.
555 555
556 556 This is pretty slow when a lot of changesets are involved but will track all
557 557 the copies.
558 558 """
559 559 m1 = c1.manifest()
560 560 m2 = c2.manifest()
561 561 mb = base.manifest()
562 562
563 563 copies1 = pathcopies(base, c1)
564 564 copies2 = pathcopies(base, c2)
565 565
566 566 if not (copies1 or copies2):
567 567 return {}, {}, {}, {}, {}
568 568
569 569 inversecopies1 = {}
570 570 inversecopies2 = {}
571 571 for dst, src in copies1.items():
572 572 inversecopies1.setdefault(src, []).append(dst)
573 573 for dst, src in copies2.items():
574 574 inversecopies2.setdefault(src, []).append(dst)
575 575
576 576 copy1 = {}
577 577 copy2 = {}
578 578 diverge = {}
579 579 renamedelete1 = {}
580 580 renamedelete2 = {}
581 581 allsources = set(inversecopies1) | set(inversecopies2)
582 582 for src in allsources:
583 583 dsts1 = inversecopies1.get(src)
584 584 dsts2 = inversecopies2.get(src)
585 585 if dsts1 and dsts2:
586 586 # copied/renamed on both sides
587 587 if src not in m1 and src not in m2:
588 588 # renamed on both sides
589 589 dsts1 = set(dsts1)
590 590 dsts2 = set(dsts2)
591 591 # If there's some overlap in the rename destinations, we
592 592 # consider it not divergent. For example, if side 1 copies 'a'
593 593 # to 'b' and 'c' and deletes 'a', and side 2 copies 'a' to 'c'
594 594 # and 'd' and deletes 'a'.
595 595 if dsts1 & dsts2:
596 596 for dst in dsts1 & dsts2:
597 597 copy1[dst] = src
598 598 copy2[dst] = src
599 599 else:
600 600 diverge[src] = sorted(dsts1 | dsts2)
601 601 elif src in m1 and src in m2:
602 602 # copied on both sides
603 603 dsts1 = set(dsts1)
604 604 dsts2 = set(dsts2)
605 605 for dst in dsts1 & dsts2:
606 606 copy1[dst] = src
607 607 copy2[dst] = src
608 608 # TODO: Handle cases where it was renamed on one side and copied
609 609 # on the other side
610 610 elif dsts1:
611 611 # copied/renamed only on side 1
612 612 _checksinglesidecopies(
613 613 src, dsts1, m1, m2, mb, c2, base, copy1, renamedelete1
614 614 )
615 615 elif dsts2:
616 616 # copied/renamed only on side 2
617 617 _checksinglesidecopies(
618 618 src, dsts2, m2, m1, mb, c1, base, copy2, renamedelete2
619 619 )
620 620
621 621 # find interesting file sets from manifests
622 622 addedinm1 = m1.filesnotin(mb, repo.narrowmatch())
623 623 addedinm2 = m2.filesnotin(mb, repo.narrowmatch())
624 624 u1 = sorted(addedinm1 - addedinm2)
625 625 u2 = sorted(addedinm2 - addedinm1)
626 626
627 627 header = b" unmatched files in %s"
628 628 if u1:
629 629 repo.ui.debug(b"%s:\n %s\n" % (header % b'local', b"\n ".join(u1)))
630 630 if u2:
631 631 repo.ui.debug(b"%s:\n %s\n" % (header % b'other', b"\n ".join(u2)))
632 632
633 fullcopy = copies1.copy()
634 fullcopy.update(copies2)
635
636 633 if repo.ui.debugflag:
637 634 renamedeleteset = set()
638 635 divergeset = set()
639 636 for dsts in diverge.values():
640 637 divergeset.update(dsts)
641 638 for dsts in renamedelete1.values():
642 639 renamedeleteset.update(dsts)
643 640 for dsts in renamedelete2.values():
644 641 renamedeleteset.update(dsts)
645 642
646 643 repo.ui.debug(
647 644 b" all copies found (* = to merge, ! = divergent, "
648 645 b"% = renamed and deleted):\n"
649 646 )
650 for f in sorted(fullcopy):
651 note = b""
652 if f in copy1 or f in copy2:
653 note += b"*"
654 if f in divergeset:
655 note += b"!"
656 if f in renamedeleteset:
657 note += b"%"
658 repo.ui.debug(
659 b" src: '%s' -> dst: '%s' %s\n" % (fullcopy[f], f, note)
660 )
647 for side, copies in ((b"local", copies1), (b"remote", copies2)):
648 if not copies:
649 continue
650 repo.ui.debug(b" on %s side:\n" % side)
651 for f in sorted(copies):
652 note = b""
653 if f in copy1 or f in copy2:
654 note += b"*"
655 if f in divergeset:
656 note += b"!"
657 if f in renamedeleteset:
658 note += b"%"
659 repo.ui.debug(
660 b" src: '%s' -> dst: '%s' %s\n" % (copies[f], f, note)
661 )
661 662 del renamedeleteset
662 663 del divergeset
663 664
664 665 repo.ui.debug(b" checking for directory renames\n")
665 666
666 667 dirmove1, movewithdir2 = _dir_renames(repo, c1, copy1, copies1, u2)
667 668 dirmove2, movewithdir1 = _dir_renames(repo, c2, copy2, copies2, u1)
668 669
669 670 copy1.update(copy2)
670 671 renamedelete1.update(renamedelete2)
671 672 movewithdir1.update(movewithdir2)
672 673 dirmove1.update(dirmove2)
673 674
674 675 return copy1, movewithdir1, diverge, renamedelete1, dirmove1
675 676
676 677
677 678 def _dir_renames(repo, ctx, copy, fullcopy, addedfiles):
678 679 """Finds moved directories and files that should move with them.
679 680
680 681 ctx: the context for one of the sides
681 682 copy: files copied on the same side (as ctx)
682 683 fullcopy: files copied on the same side (as ctx), including those that
683 684 merge.manifestmerge() won't care about
684 685 addedfiles: added files on the other side (compared to ctx)
685 686 """
686 687 # generate a directory move map
687 688 d = ctx.dirs()
688 689 invalid = set()
689 690 dirmove = {}
690 691
691 692 # examine each file copy for a potential directory move, which is
692 693 # when all the files in a directory are moved to a new directory
693 694 for dst, src in pycompat.iteritems(fullcopy):
694 695 dsrc, ddst = pathutil.dirname(src), pathutil.dirname(dst)
695 696 if dsrc in invalid:
696 697 # already seen to be uninteresting
697 698 continue
698 699 elif dsrc in d and ddst in d:
699 700 # directory wasn't entirely moved locally
700 701 invalid.add(dsrc)
701 702 elif dsrc in dirmove and dirmove[dsrc] != ddst:
702 703 # files from the same directory moved to two different places
703 704 invalid.add(dsrc)
704 705 else:
705 706 # looks good so far
706 707 dirmove[dsrc] = ddst
707 708
708 709 for i in invalid:
709 710 if i in dirmove:
710 711 del dirmove[i]
711 712 del d, invalid
712 713
713 714 if not dirmove:
714 715 return {}, {}
715 716
716 717 dirmove = {k + b"/": v + b"/" for k, v in pycompat.iteritems(dirmove)}
717 718
718 719 for d in dirmove:
719 720 repo.ui.debug(
720 721 b" discovered dir src: '%s' -> dst: '%s'\n" % (d, dirmove[d])
721 722 )
722 723
723 724 movewithdir = {}
724 725 # check unaccounted nonoverlapping files against directory moves
725 726 for f in addedfiles:
726 727 if f not in fullcopy:
727 728 for d in dirmove:
728 729 if f.startswith(d):
729 730 # new file added in a directory that was moved, move it
730 731 df = dirmove[d] + f[len(d) :]
731 732 if df not in copy:
732 733 movewithdir[f] = df
733 734 repo.ui.debug(
734 735 b" pending file src: '%s' -> dst: '%s'\n"
735 736 % (f, df)
736 737 )
737 738 break
738 739
739 740 return dirmove, movewithdir
740 741
741 742
742 743 def _heuristicscopytracing(repo, c1, c2, base):
743 744 """ Fast copytracing using filename heuristics
744 745
745 746 Assumes that moves or renames are of following two types:
746 747
747 748 1) Inside a directory only (same directory name but different filenames)
748 749 2) Move from one directory to another
749 750 (same filenames but different directory names)
750 751
751 752 Works only when there are no merge commits in the "source branch".
752 753 Source branch is commits from base up to c2 not including base.
753 754
754 755 If merge is involved it fallbacks to _fullcopytracing().
755 756
756 757 Can be used by setting the following config:
757 758
758 759 [experimental]
759 760 copytrace = heuristics
760 761
761 762 In some cases the copy/move candidates found by heuristics can be very large
762 763 in number and that will make the algorithm slow. The number of possible
763 764 candidates to check can be limited by using the config
764 765 `experimental.copytrace.movecandidateslimit` which defaults to 100.
765 766 """
766 767
767 768 if c1.rev() is None:
768 769 c1 = c1.p1()
769 770 if c2.rev() is None:
770 771 c2 = c2.p1()
771 772
772 773 copies = {}
773 774
774 775 changedfiles = set()
775 776 m1 = c1.manifest()
776 777 if not repo.revs(b'%d::%d', base.rev(), c2.rev()):
777 778 # If base is not in c2 branch, we switch to fullcopytracing
778 779 repo.ui.debug(
779 780 b"switching to full copytracing as base is not "
780 781 b"an ancestor of c2\n"
781 782 )
782 783 return _fullcopytracing(repo, c1, c2, base)
783 784
784 785 ctx = c2
785 786 while ctx != base:
786 787 if len(ctx.parents()) == 2:
787 788 # To keep things simple let's not handle merges
788 789 repo.ui.debug(b"switching to full copytracing because of merges\n")
789 790 return _fullcopytracing(repo, c1, c2, base)
790 791 changedfiles.update(ctx.files())
791 792 ctx = ctx.p1()
792 793
793 794 cp = _forwardcopies(base, c2)
794 795 for dst, src in pycompat.iteritems(cp):
795 796 if src in m1:
796 797 copies[dst] = src
797 798
798 799 # file is missing if it isn't present in the destination, but is present in
799 800 # the base and present in the source.
800 801 # Presence in the base is important to exclude added files, presence in the
801 802 # source is important to exclude removed files.
802 803 filt = lambda f: f not in m1 and f in base and f in c2
803 804 missingfiles = [f for f in changedfiles if filt(f)]
804 805
805 806 if missingfiles:
806 807 basenametofilename = collections.defaultdict(list)
807 808 dirnametofilename = collections.defaultdict(list)
808 809
809 810 for f in m1.filesnotin(base.manifest()):
810 811 basename = os.path.basename(f)
811 812 dirname = os.path.dirname(f)
812 813 basenametofilename[basename].append(f)
813 814 dirnametofilename[dirname].append(f)
814 815
815 816 for f in missingfiles:
816 817 basename = os.path.basename(f)
817 818 dirname = os.path.dirname(f)
818 819 samebasename = basenametofilename[basename]
819 820 samedirname = dirnametofilename[dirname]
820 821 movecandidates = samebasename + samedirname
821 822 # f is guaranteed to be present in c2, that's why
822 823 # c2.filectx(f) won't fail
823 824 f2 = c2.filectx(f)
824 825 # we can have a lot of candidates which can slow down the heuristics
825 826 # config value to limit the number of candidates moves to check
826 827 maxcandidates = repo.ui.configint(
827 828 b'experimental', b'copytrace.movecandidateslimit'
828 829 )
829 830
830 831 if len(movecandidates) > maxcandidates:
831 832 repo.ui.status(
832 833 _(
833 834 b"skipping copytracing for '%s', more "
834 835 b"candidates than the limit: %d\n"
835 836 )
836 837 % (f, len(movecandidates))
837 838 )
838 839 continue
839 840
840 841 for candidate in movecandidates:
841 842 f1 = c1.filectx(candidate)
842 843 if _related(f1, f2):
843 844 # if there are a few related copies then we'll merge
844 845 # changes into all of them. This matches the behaviour
845 846 # of upstream copytracing
846 847 copies[candidate] = f
847 848
848 849 return copies, {}, {}, {}, {}
849 850
850 851
851 852 def _related(f1, f2):
852 853 """return True if f1 and f2 filectx have a common ancestor
853 854
854 855 Walk back to common ancestor to see if the two files originate
855 856 from the same file. Since workingfilectx's rev() is None it messes
856 857 up the integer comparison logic, hence the pre-step check for
857 858 None (f1 and f2 can only be workingfilectx's initially).
858 859 """
859 860
860 861 if f1 == f2:
861 862 return True # a match
862 863
863 864 g1, g2 = f1.ancestors(), f2.ancestors()
864 865 try:
865 866 f1r, f2r = f1.linkrev(), f2.linkrev()
866 867
867 868 if f1r is None:
868 869 f1 = next(g1)
869 870 if f2r is None:
870 871 f2 = next(g2)
871 872
872 873 while True:
873 874 f1r, f2r = f1.linkrev(), f2.linkrev()
874 875 if f1r > f2r:
875 876 f1 = next(g1)
876 877 elif f2r > f1r:
877 878 f2 = next(g2)
878 879 else: # f1 and f2 point to files in the same linkrev
879 880 return f1 == f2 # true if they point to the same file
880 881 except StopIteration:
881 882 return False
882 883
883 884
884 885 def graftcopies(wctx, ctx, base):
885 886 """reproduce copies between base and ctx in the wctx
886 887
887 888 Unlike mergecopies(), this function will only consider copies between base
888 889 and ctx; it will ignore copies between base and wctx. Also unlike
889 890 mergecopies(), this function will apply copies to the working copy (instead
890 891 of just returning information about the copies). That makes it cheaper
891 892 (especially in the common case of base==ctx.p1()) and useful also when
892 893 experimental.copytrace=off.
893 894
894 895 merge.update() will have already marked most copies, but it will only
895 896 mark copies if it thinks the source files are related (see
896 897 merge._related()). It will also not mark copies if the file wasn't modified
897 898 on the local side. This function adds the copies that were "missed"
898 899 by merge.update().
899 900 """
900 901 new_copies = pathcopies(base, ctx)
901 902 _filter(wctx.p1(), wctx, new_copies)
902 903 for dst, src in pycompat.iteritems(new_copies):
903 904 wctx[dst].markcopied(src)
904 905
905 906
906 907 def computechangesetfilesadded(ctx):
907 908 """return the list of files added in a changeset
908 909 """
909 910 added = []
910 911 for f in ctx.files():
911 912 if not any(f in p for p in ctx.parents()):
912 913 added.append(f)
913 914 return added
914 915
915 916
916 917 def computechangesetfilesremoved(ctx):
917 918 """return the list of files removed in a changeset
918 919 """
919 920 removed = []
920 921 for f in ctx.files():
921 922 if f not in ctx:
922 923 removed.append(f)
923 924 return removed
924 925
925 926
926 927 def computechangesetcopies(ctx):
927 928 """return the copies data for a changeset
928 929
929 930 The copies data are returned as a pair of dictionnary (p1copies, p2copies).
930 931
931 932 Each dictionnary are in the form: `{newname: oldname}`
932 933 """
933 934 p1copies = {}
934 935 p2copies = {}
935 936 p1 = ctx.p1()
936 937 p2 = ctx.p2()
937 938 narrowmatch = ctx._repo.narrowmatch()
938 939 for dst in ctx.files():
939 940 if not narrowmatch(dst) or dst not in ctx:
940 941 continue
941 942 copied = ctx[dst].renamed()
942 943 if not copied:
943 944 continue
944 945 src, srcnode = copied
945 946 if src in p1 and p1[src].filenode() == srcnode:
946 947 p1copies[dst] = src
947 948 elif src in p2 and p2[src].filenode() == srcnode:
948 949 p2copies[dst] = src
949 950 return p1copies, p2copies
950 951
951 952
952 953 def encodecopies(files, copies):
953 954 items = []
954 955 for i, dst in enumerate(files):
955 956 if dst in copies:
956 957 items.append(b'%d\0%s' % (i, copies[dst]))
957 958 if len(items) != len(copies):
958 959 raise error.ProgrammingError(
959 960 b'some copy targets missing from file list'
960 961 )
961 962 return b"\n".join(items)
962 963
963 964
964 965 def decodecopies(files, data):
965 966 try:
966 967 copies = {}
967 968 if not data:
968 969 return copies
969 970 for l in data.split(b'\n'):
970 971 strindex, src = l.split(b'\0')
971 972 i = int(strindex)
972 973 dst = files[i]
973 974 copies[dst] = src
974 975 return copies
975 976 except (ValueError, IndexError):
976 977 # Perhaps someone had chosen the same key name (e.g. "p1copies") and
977 978 # used different syntax for the value.
978 979 return None
979 980
980 981
981 982 def encodefileindices(files, subset):
982 983 subset = set(subset)
983 984 indices = []
984 985 for i, f in enumerate(files):
985 986 if f in subset:
986 987 indices.append(b'%d' % i)
987 988 return b'\n'.join(indices)
988 989
989 990
990 991 def decodefileindices(files, data):
991 992 try:
992 993 subset = []
993 994 if not data:
994 995 return subset
995 996 for strindex in data.split(b'\n'):
996 997 i = int(strindex)
997 998 if i < 0 or i >= len(files):
998 999 return None
999 1000 subset.append(files[i])
1000 1001 return subset
1001 1002 except (ValueError, IndexError):
1002 1003 # Perhaps someone had chosen the same key name (e.g. "added") and
1003 1004 # used different syntax for the value.
1004 1005 return None
1005 1006
1006 1007
1007 1008 def _getsidedata(srcrepo, rev):
1008 1009 ctx = srcrepo[rev]
1009 1010 filescopies = computechangesetcopies(ctx)
1010 1011 filesadded = computechangesetfilesadded(ctx)
1011 1012 filesremoved = computechangesetfilesremoved(ctx)
1012 1013 sidedata = {}
1013 1014 if any([filescopies, filesadded, filesremoved]):
1014 1015 sortedfiles = sorted(ctx.files())
1015 1016 p1copies, p2copies = filescopies
1016 1017 p1copies = encodecopies(sortedfiles, p1copies)
1017 1018 p2copies = encodecopies(sortedfiles, p2copies)
1018 1019 filesadded = encodefileindices(sortedfiles, filesadded)
1019 1020 filesremoved = encodefileindices(sortedfiles, filesremoved)
1020 1021 if p1copies:
1021 1022 sidedata[sidedatamod.SD_P1COPIES] = p1copies
1022 1023 if p2copies:
1023 1024 sidedata[sidedatamod.SD_P2COPIES] = p2copies
1024 1025 if filesadded:
1025 1026 sidedata[sidedatamod.SD_FILESADDED] = filesadded
1026 1027 if filesremoved:
1027 1028 sidedata[sidedatamod.SD_FILESREMOVED] = filesremoved
1028 1029 return sidedata
1029 1030
1030 1031
1031 1032 def getsidedataadder(srcrepo, destrepo):
1032 1033 use_w = srcrepo.ui.configbool(b'experimental', b'worker.repository-upgrade')
1033 1034 if pycompat.iswindows or not use_w:
1034 1035 return _get_simple_sidedata_adder(srcrepo, destrepo)
1035 1036 else:
1036 1037 return _get_worker_sidedata_adder(srcrepo, destrepo)
1037 1038
1038 1039
1039 1040 def _sidedata_worker(srcrepo, revs_queue, sidedata_queue, tokens):
1040 1041 """The function used by worker precomputing sidedata
1041 1042
1042 1043 It read an input queue containing revision numbers
1043 1044 It write in an output queue containing (rev, <sidedata-map>)
1044 1045
1045 1046 The `None` input value is used as a stop signal.
1046 1047
1047 1048 The `tokens` semaphore is user to avoid having too many unprocessed
1048 1049 entries. The workers needs to acquire one token before fetching a task.
1049 1050 They will be released by the consumer of the produced data.
1050 1051 """
1051 1052 tokens.acquire()
1052 1053 rev = revs_queue.get()
1053 1054 while rev is not None:
1054 1055 data = _getsidedata(srcrepo, rev)
1055 1056 sidedata_queue.put((rev, data))
1056 1057 tokens.acquire()
1057 1058 rev = revs_queue.get()
1058 1059 # processing of `None` is completed, release the token.
1059 1060 tokens.release()
1060 1061
1061 1062
1062 1063 BUFF_PER_WORKER = 50
1063 1064
1064 1065
1065 1066 def _get_worker_sidedata_adder(srcrepo, destrepo):
1066 1067 """The parallel version of the sidedata computation
1067 1068
1068 1069 This code spawn a pool of worker that precompute a buffer of sidedata
1069 1070 before we actually need them"""
1070 1071 # avoid circular import copies -> scmutil -> worker -> copies
1071 1072 from . import worker
1072 1073
1073 1074 nbworkers = worker._numworkers(srcrepo.ui)
1074 1075
1075 1076 tokens = multiprocessing.BoundedSemaphore(nbworkers * BUFF_PER_WORKER)
1076 1077 revsq = multiprocessing.Queue()
1077 1078 sidedataq = multiprocessing.Queue()
1078 1079
1079 1080 assert srcrepo.filtername is None
1080 1081 # queue all tasks beforehand, revision numbers are small and it make
1081 1082 # synchronisation simpler
1082 1083 #
1083 1084 # Since the computation for each node can be quite expensive, the overhead
1084 1085 # of using a single queue is not revelant. In practice, most computation
1085 1086 # are fast but some are very expensive and dominate all the other smaller
1086 1087 # cost.
1087 1088 for r in srcrepo.changelog.revs():
1088 1089 revsq.put(r)
1089 1090 # queue the "no more tasks" markers
1090 1091 for i in range(nbworkers):
1091 1092 revsq.put(None)
1092 1093
1093 1094 allworkers = []
1094 1095 for i in range(nbworkers):
1095 1096 args = (srcrepo, revsq, sidedataq, tokens)
1096 1097 w = multiprocessing.Process(target=_sidedata_worker, args=args)
1097 1098 allworkers.append(w)
1098 1099 w.start()
1099 1100
1100 1101 # dictionnary to store results for revision higher than we one we are
1101 1102 # looking for. For example, if we need the sidedatamap for 42, and 43 is
1102 1103 # received, when shelve 43 for later use.
1103 1104 staging = {}
1104 1105
1105 1106 def sidedata_companion(revlog, rev):
1106 1107 sidedata = {}
1107 1108 if util.safehasattr(revlog, b'filteredrevs'): # this is a changelog
1108 1109 # Is the data previously shelved ?
1109 1110 sidedata = staging.pop(rev, None)
1110 1111 if sidedata is None:
1111 1112 # look at the queued result until we find the one we are lookig
1112 1113 # for (shelve the other ones)
1113 1114 r, sidedata = sidedataq.get()
1114 1115 while r != rev:
1115 1116 staging[r] = sidedata
1116 1117 r, sidedata = sidedataq.get()
1117 1118 tokens.release()
1118 1119 return False, (), sidedata
1119 1120
1120 1121 return sidedata_companion
1121 1122
1122 1123
1123 1124 def _get_simple_sidedata_adder(srcrepo, destrepo):
1124 1125 """The simple version of the sidedata computation
1125 1126
1126 1127 It just compute it in the same thread on request"""
1127 1128
1128 1129 def sidedatacompanion(revlog, rev):
1129 1130 sidedata = {}
1130 1131 if util.safehasattr(revlog, 'filteredrevs'): # this is a changelog
1131 1132 sidedata = _getsidedata(srcrepo, rev)
1132 1133 return False, (), sidedata
1133 1134
1134 1135 return sidedatacompanion
1135 1136
1136 1137
1137 1138 def getsidedataremover(srcrepo, destrepo):
1138 1139 def sidedatacompanion(revlog, rev):
1139 1140 f = ()
1140 1141 if util.safehasattr(revlog, 'filteredrevs'): # this is a changelog
1141 1142 if revlog.flags(rev) & REVIDX_SIDEDATA:
1142 1143 f = (
1143 1144 sidedatamod.SD_P1COPIES,
1144 1145 sidedatamod.SD_P2COPIES,
1145 1146 sidedatamod.SD_FILESADDED,
1146 1147 sidedatamod.SD_FILESREMOVED,
1147 1148 )
1148 1149 return False, f, {}
1149 1150
1150 1151 return sidedatacompanion
@@ -1,171 +1,172 b''
1 1 Test for the full copytracing algorithm
2 2 =======================================
3 3
4 4 $ hg init t
5 5 $ cd t
6 6
7 7 $ echo 1 > a
8 8 $ hg ci -qAm "first"
9 9
10 10 $ hg cp a b
11 11 $ hg mv a c
12 12 $ echo 2 >> b
13 13 $ echo 2 >> c
14 14
15 15 $ hg ci -qAm "second"
16 16
17 17 $ hg co -C 0
18 18 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
19 19
20 20 $ echo 0 > a
21 21 $ echo 1 >> a
22 22
23 23 $ hg ci -qAm "other"
24 24
25 25 $ hg merge --debug
26 26 unmatched files in other:
27 27 b
28 28 c
29 29 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
30 src: 'a' -> dst: 'b' *
31 src: 'a' -> dst: 'c' *
30 on remote side:
31 src: 'a' -> dst: 'b' *
32 src: 'a' -> dst: 'c' *
32 33 checking for directory renames
33 34 resolving manifests
34 35 branchmerge: True, force: False, partial: False
35 36 ancestor: b8bf91eeebbc, local: add3f11052fa+, remote: 17c05bb7fcb6
36 37 preserving a for resolve of b
37 38 preserving a for resolve of c
38 39 removing a
39 40 starting 4 threads for background file closing (?)
40 41 b: remote moved from a -> m (premerge)
41 42 picked tool ':merge' for b (binary False symlink False changedelete False)
42 43 merging a and b to b
43 44 my b@add3f11052fa+ other b@17c05bb7fcb6 ancestor a@b8bf91eeebbc
44 45 premerge successful
45 46 c: remote moved from a -> m (premerge)
46 47 picked tool ':merge' for c (binary False symlink False changedelete False)
47 48 merging a and c to c
48 49 my c@add3f11052fa+ other c@17c05bb7fcb6 ancestor a@b8bf91eeebbc
49 50 premerge successful
50 51 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
51 52 (branch merge, don't forget to commit)
52 53
53 54 file b
54 55 $ cat b
55 56 0
56 57 1
57 58 2
58 59
59 60 file c
60 61 $ cat c
61 62 0
62 63 1
63 64 2
64 65
65 66 Test disabling copy tracing
66 67
67 68 - first verify copy metadata was kept
68 69
69 70 $ hg up -qC 2
70 71 $ hg rebase --keep -d 1 -b 2 --config extensions.rebase=
71 72 rebasing 2:add3f11052fa "other" (tip)
72 73 merging b and a to b
73 74 merging c and a to c
74 75
75 76 $ cat b
76 77 0
77 78 1
78 79 2
79 80
80 81 - next verify copy metadata is lost when disabled
81 82
82 83 $ hg strip -r . --config extensions.strip=
83 84 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
84 85 saved backup bundle to $TESTTMP/t/.hg/strip-backup/550bd84c0cd3-fc575957-backup.hg
85 86 $ hg up -qC 2
86 87 $ hg rebase --keep -d 1 -b 2 --config extensions.rebase= --config experimental.copytrace=off --config ui.interactive=True << EOF
87 88 > c
88 89 > EOF
89 90 rebasing 2:add3f11052fa "other" (tip)
90 91 file 'a' was deleted in local [dest] but was modified in other [source].
91 92 You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.
92 93 What do you want to do? c
93 94
94 95 $ cat b
95 96 1
96 97 2
97 98
98 99 $ cd ..
99 100
100 101 Verify disabling copy tracing still keeps copies from rebase source
101 102
102 103 $ hg init copydisable
103 104 $ cd copydisable
104 105 $ touch a
105 106 $ hg ci -Aqm 'add a'
106 107 $ touch b
107 108 $ hg ci -Aqm 'add b, c'
108 109 $ hg cp b x
109 110 $ echo x >> x
110 111 $ hg ci -qm 'copy b->x'
111 112 $ hg up -q 1
112 113 $ touch z
113 114 $ hg ci -Aqm 'add z'
114 115 $ hg log -G -T '{rev} {desc}\n'
115 116 @ 3 add z
116 117 |
117 118 | o 2 copy b->x
118 119 |/
119 120 o 1 add b, c
120 121 |
121 122 o 0 add a
122 123
123 124 $ hg rebase -d . -b 2 --config extensions.rebase= --config experimental.copytrace=off
124 125 rebasing 2:6adcf8c12e7d "copy b->x"
125 126 saved backup bundle to $TESTTMP/copydisable/.hg/strip-backup/6adcf8c12e7d-ce4b3e75-rebase.hg
126 127 $ hg up -q 3
127 128 $ hg log -f x -T '{rev} {desc}\n'
128 129 3 copy b->x
129 130 1 add b, c
130 131
131 132 $ cd ../
132 133
133 134 Verify we duplicate existing copies, instead of detecting them
134 135
135 136 $ hg init copydisable3
136 137 $ cd copydisable3
137 138 $ touch a
138 139 $ hg ci -Aqm 'add a'
139 140 $ hg cp a b
140 141 $ hg ci -Aqm 'copy a->b'
141 142 $ hg mv b c
142 143 $ hg ci -Aqm 'move b->c'
143 144 $ hg up -q 0
144 145 $ hg cp a b
145 146 $ echo b >> b
146 147 $ hg ci -Aqm 'copy a->b (2)'
147 148 $ hg log -G -T '{rev} {desc}\n'
148 149 @ 3 copy a->b (2)
149 150 |
150 151 | o 2 move b->c
151 152 | |
152 153 | o 1 copy a->b
153 154 |/
154 155 o 0 add a
155 156
156 157 $ hg rebase -d 2 -s 3 --config extensions.rebase= --config experimental.copytrace=off
157 158 rebasing 3:47e1a9e6273b "copy a->b (2)" (tip)
158 159 saved backup bundle to $TESTTMP/copydisable3/.hg/strip-backup/47e1a9e6273b-2d099c59-rebase.hg
159 160
160 161 $ hg log -G -f b
161 162 @ changeset: 3:76024fb4b05b
162 163 : tag: tip
163 164 : user: test
164 165 : date: Thu Jan 01 00:00:00 1970 +0000
165 166 : summary: copy a->b (2)
166 167 :
167 168 o changeset: 0:ac82d8b1f7c4
168 169 user: test
169 170 date: Thu Jan 01 00:00:00 1970 +0000
170 171 summary: add a
171 172
@@ -1,65 +1,66 b''
1 1 $ hg init repo
2 2 $ cd repo
3 3
4 4 $ echo line 1 > foo
5 5 $ hg ci -qAm 'add foo'
6 6
7 7 copy foo to bar and change both files
8 8 $ hg cp foo bar
9 9 $ echo line 2-1 >> foo
10 10 $ echo line 2-2 >> bar
11 11 $ hg ci -m 'cp foo bar; change both'
12 12
13 13 in another branch, change foo in a way that doesn't conflict with
14 14 the other changes
15 15 $ hg up -qC 0
16 16 $ echo line 0 > foo
17 17 $ hg cat foo >> foo
18 18 $ hg ci -m 'change foo'
19 19 created new head
20 20
21 21 we get conflicts that shouldn't be there
22 22 $ hg merge -P
23 23 changeset: 1:484bf6903104
24 24 user: test
25 25 date: Thu Jan 01 00:00:00 1970 +0000
26 26 summary: cp foo bar; change both
27 27
28 28 $ hg merge --debug
29 29 unmatched files in other:
30 30 bar
31 31 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
32 src: 'foo' -> dst: 'bar' *
32 on remote side:
33 src: 'foo' -> dst: 'bar' *
33 34 checking for directory renames
34 35 resolving manifests
35 36 branchmerge: True, force: False, partial: False
36 37 ancestor: e6dc8efe11cc, local: 6a0df1dad128+, remote: 484bf6903104
37 38 preserving foo for resolve of bar
38 39 preserving foo for resolve of foo
39 40 starting 4 threads for background file closing (?)
40 41 bar: remote copied from foo -> m (premerge)
41 42 picked tool ':merge' for bar (binary False symlink False changedelete False)
42 43 merging foo and bar to bar
43 44 my bar@6a0df1dad128+ other bar@484bf6903104 ancestor foo@e6dc8efe11cc
44 45 premerge successful
45 46 foo: versions differ -> m (premerge)
46 47 picked tool ':merge' for foo (binary False symlink False changedelete False)
47 48 merging foo
48 49 my foo@6a0df1dad128+ other foo@484bf6903104 ancestor foo@e6dc8efe11cc
49 50 premerge successful
50 51 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
51 52 (branch merge, don't forget to commit)
52 53
53 54 contents of foo
54 55 $ cat foo
55 56 line 0
56 57 line 1
57 58 line 2-1
58 59
59 60 contents of bar
60 61 $ cat bar
61 62 line 0
62 63 line 1
63 64 line 2-2
64 65
65 66 $ cd ..
@@ -1,906 +1,912 b''
1 1 $ cat >> $HGRCPATH <<EOF
2 2 > [extdiff]
3 3 > # for portability:
4 4 > pdiff = sh "$RUNTESTDIR/pdiff"
5 5 > EOF
6 6
7 7 Create a repo with some stuff in it:
8 8
9 9 $ hg init a
10 10 $ cd a
11 11 $ echo a > a
12 12 $ echo a > d
13 13 $ echo a > e
14 14 $ hg ci -qAm0
15 15 $ echo b > a
16 16 $ hg ci -m1 -u bar
17 17 $ hg mv a b
18 18 $ hg ci -m2
19 19 $ hg cp b c
20 20 $ hg ci -m3 -u baz
21 21 $ echo b > d
22 22 $ echo f > e
23 23 $ hg ci -m4
24 24 $ hg up -q 3
25 25 $ echo b > e
26 26 $ hg branch -q stable
27 27 $ hg ci -m5
28 28 $ hg merge -q default --tool internal:local # for conflicts in e, choose 5 and ignore 4
29 29 $ hg branch -q default
30 30 $ hg ci -m6
31 31 $ hg phase --public 3
32 32 $ hg phase --force --secret 6
33 33
34 34 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
35 35 @ test@6.secret: 6
36 36 |\
37 37 | o test@5.draft: 5
38 38 | |
39 39 o | test@4.draft: 4
40 40 |/
41 41 o baz@3.public: 3
42 42 |
43 43 o test@2.public: 2
44 44 |
45 45 o bar@1.public: 1
46 46 |
47 47 o test@0.public: 0
48 48
49 49 Test --base for grafting the merge of 4 from the perspective of 5, thus only getting the change to d
50 50
51 51 $ hg up -cqr 3
52 52 $ hg graft -r 6 --base 5
53 53 grafting 6:25a2b029d3ae "6" (tip)
54 54 merging e
55 55 $ hg st --change .
56 56 M d
57 57
58 58 $ hg -q strip . --config extensions.strip=
59 59
60 60 Test --base for collapsing changesets 2 and 3, thus getting both b and c
61 61
62 62 $ hg up -cqr 0
63 63 $ hg graft -r 3 --base 1
64 64 grafting 3:4c60f11aa304 "3"
65 65 merging a and b to b
66 66 merging a and c to c
67 67 $ hg st --change .
68 68 A b
69 69 A c
70 70 R a
71 71
72 72 $ hg -q strip . --config extensions.strip=
73 73
74 74 Specifying child as --base revision fails safely (perhaps slightly confusing, but consistent)
75 75
76 76 $ hg graft -r 2 --base 3
77 77 grafting 2:5c095ad7e90f "2"
78 78 note: possible conflict - c was deleted and renamed to:
79 79 a
80 80 note: graft of 2:5c095ad7e90f created no changes to commit
81 81
82 82 Can't continue without starting:
83 83
84 84 $ hg -q up -cr tip
85 85 $ hg rm -q e
86 86 $ hg graft --continue
87 87 abort: no graft in progress
88 88 [255]
89 89 $ hg revert -r . -q e
90 90
91 91 Need to specify a rev:
92 92
93 93 $ hg graft
94 94 abort: no revisions specified
95 95 [255]
96 96
97 97 Can't graft ancestor:
98 98
99 99 $ hg graft 1 2
100 100 skipping ancestor revision 1:5d205f8b35b6
101 101 skipping ancestor revision 2:5c095ad7e90f
102 102 [255]
103 103
104 104 Specify revisions with -r:
105 105
106 106 $ hg graft -r 1 -r 2
107 107 skipping ancestor revision 1:5d205f8b35b6
108 108 skipping ancestor revision 2:5c095ad7e90f
109 109 [255]
110 110
111 111 $ hg graft -r 1 2
112 112 warning: inconsistent use of --rev might give unexpected revision ordering!
113 113 skipping ancestor revision 2:5c095ad7e90f
114 114 skipping ancestor revision 1:5d205f8b35b6
115 115 [255]
116 116
117 117 Conflicting date/user options:
118 118
119 119 $ hg up -q 0
120 120 $ hg graft -U --user foo 2
121 121 abort: cannot specify both --user and --currentuser
122 122 [255]
123 123 $ hg graft -D --date '0 0' 2
124 124 abort: cannot specify both --date and --currentdate
125 125 [255]
126 126
127 127 Can't graft with dirty wd:
128 128
129 129 $ hg up -q 0
130 130 $ echo foo > a
131 131 $ hg graft 1
132 132 abort: uncommitted changes
133 133 [255]
134 134 $ hg revert a
135 135
136 136 Graft a rename:
137 137 (this also tests that editor is invoked if '--edit' is specified)
138 138
139 139 $ hg status --rev "2^1" --rev 2
140 140 A b
141 141 R a
142 142 $ HGEDITOR=cat hg graft 2 -u foo --edit
143 143 grafting 2:5c095ad7e90f "2"
144 144 merging a and b to b
145 145 2
146 146
147 147
148 148 HG: Enter commit message. Lines beginning with 'HG:' are removed.
149 149 HG: Leave message empty to abort commit.
150 150 HG: --
151 151 HG: user: foo
152 152 HG: branch 'default'
153 153 HG: added b
154 154 HG: removed a
155 155 $ hg export tip --git
156 156 # HG changeset patch
157 157 # User foo
158 158 # Date 0 0
159 159 # Thu Jan 01 00:00:00 1970 +0000
160 160 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
161 161 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
162 162 2
163 163
164 164 diff --git a/a b/b
165 165 rename from a
166 166 rename to b
167 167
168 168 Look for extra:source
169 169
170 170 $ hg log --debug -r tip
171 171 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
172 172 tag: tip
173 173 phase: draft
174 174 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
175 175 parent: -1:0000000000000000000000000000000000000000
176 176 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
177 177 user: foo
178 178 date: Thu Jan 01 00:00:00 1970 +0000
179 179 files+: b
180 180 files-: a
181 181 extra: branch=default
182 182 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
183 183 description:
184 184 2
185 185
186 186
187 187
188 188 Graft out of order, skipping a merge and a duplicate
189 189 (this also tests that editor is not invoked if '--edit' is not specified)
190 190
191 191 $ hg graft 1 5 4 3 'merge()' 2 -n
192 192 skipping ungraftable merge revision 6
193 193 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
194 194 grafting 1:5d205f8b35b6 "1"
195 195 grafting 5:97f8bfe72746 "5"
196 196 grafting 4:9c233e8e184d "4"
197 197 grafting 3:4c60f11aa304 "3"
198 198
199 199 $ HGEDITOR=cat hg graft 1 5 'merge()' 2 --debug
200 200 skipping ungraftable merge revision 6
201 201 scanning for duplicate grafts
202 202 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
203 203 grafting 1:5d205f8b35b6 "1"
204 204 unmatched files in local:
205 205 b
206 206 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
207 src: 'a' -> dst: 'b' *
207 on local side:
208 src: 'a' -> dst: 'b' *
208 209 checking for directory renames
209 210 resolving manifests
210 211 branchmerge: True, force: True, partial: False
211 212 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
212 213 preserving b for resolve of b
213 214 starting 4 threads for background file closing (?)
214 215 b: local copied/moved from a -> m (premerge)
215 216 picked tool ':merge' for b (binary False symlink False changedelete False)
216 217 merging b and a to b
217 218 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
218 219 premerge successful
219 220 committing files:
220 221 b
221 222 committing manifest
222 223 committing changelog
223 224 updating the branch cache
224 225 grafting 5:97f8bfe72746 "5"
225 226 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
226 src: 'c' -> dst: 'b'
227 on local side:
228 src: 'c' -> dst: 'b'
227 229 checking for directory renames
228 230 resolving manifests
229 231 branchmerge: True, force: True, partial: False
230 232 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
231 233 e: remote is newer -> g
232 234 getting e
233 235 committing files:
234 236 e
235 237 committing manifest
236 238 committing changelog
237 239 updating the branch cache
238 240 $ HGEDITOR=cat hg graft 4 3 --log --debug
239 241 scanning for duplicate grafts
240 242 grafting 4:9c233e8e184d "4"
241 243 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
242 src: 'c' -> dst: 'b'
244 on local side:
245 src: 'c' -> dst: 'b'
243 246 checking for directory renames
244 247 resolving manifests
245 248 branchmerge: True, force: True, partial: False
246 249 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
247 250 preserving e for resolve of e
248 251 d: remote is newer -> g
249 252 getting d
250 253 e: versions differ -> m (premerge)
251 254 picked tool ':merge' for e (binary False symlink False changedelete False)
252 255 merging e
253 256 my e@1905859650ec+ other e@9c233e8e184d ancestor e@4c60f11aa304
254 257 e: versions differ -> m (merge)
255 258 picked tool ':merge' for e (binary False symlink False changedelete False)
256 259 my e@1905859650ec+ other e@9c233e8e184d ancestor e@4c60f11aa304
257 260 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
258 261 abort: unresolved conflicts, can't continue
259 262 (use 'hg resolve' and 'hg graft --continue')
260 263 [255]
261 264
262 265 Summary should mention graft:
263 266
264 267 $ hg summary |grep graft
265 268 commit: 2 modified, 2 unknown, 1 unresolved (graft in progress)
266 269
267 270 Using status to get more context
268 271
269 272 $ hg status --verbose
270 273 M d
271 274 M e
272 275 ? a.orig
273 276 ? e.orig
274 277 # The repository is in an unfinished *graft* state.
275 278
276 279 # Unresolved merge conflicts:
277 280 #
278 281 # e
279 282 #
280 283 # To mark files as resolved: hg resolve --mark FILE
281 284
282 285 # To continue: hg graft --continue
283 286 # To abort: hg graft --abort
284 287 # To stop: hg graft --stop
285 288
286 289
287 290 Commit while interrupted should fail:
288 291
289 292 $ hg ci -m 'commit interrupted graft'
290 293 abort: graft in progress
291 294 (use 'hg graft --continue' or 'hg graft --stop' to stop)
292 295 [255]
293 296
294 297 Abort the graft and try committing:
295 298
296 299 $ hg up -C .
297 300 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
298 301 $ echo c >> e
299 302 $ hg ci -mtest
300 303
301 304 $ hg strip . --config extensions.strip=
302 305 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
303 306 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
304 307
305 308 Graft again:
306 309
307 310 $ hg graft 1 5 4 3 'merge()' 2
308 311 skipping ungraftable merge revision 6
309 312 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
310 313 skipping revision 1:5d205f8b35b6 (already grafted to 8:6b9e5368ca4e)
311 314 skipping revision 5:97f8bfe72746 (already grafted to 9:1905859650ec)
312 315 grafting 4:9c233e8e184d "4"
313 316 merging e
314 317 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
315 318 abort: unresolved conflicts, can't continue
316 319 (use 'hg resolve' and 'hg graft --continue')
317 320 [255]
318 321
319 322 Continue without resolve should fail:
320 323
321 324 $ hg graft -c
322 325 grafting 4:9c233e8e184d "4"
323 326 abort: unresolved merge conflicts (see 'hg help resolve')
324 327 [255]
325 328
326 329 Fix up:
327 330
328 331 $ echo b > e
329 332 $ hg resolve -m e
330 333 (no more unresolved files)
331 334 continue: hg graft --continue
332 335
333 336 Continue with a revision should fail:
334 337
335 338 $ hg graft -c 6
336 339 abort: can't specify --continue and revisions
337 340 [255]
338 341
339 342 $ hg graft -c -r 6
340 343 abort: can't specify --continue and revisions
341 344 [255]
342 345
343 346 Continue for real, clobber usernames
344 347
345 348 $ hg graft -c -U
346 349 grafting 4:9c233e8e184d "4"
347 350 grafting 3:4c60f11aa304 "3"
348 351
349 352 Compare with original:
350 353
351 354 $ hg diff -r 6
352 355 $ hg status --rev 0:. -C
353 356 M d
354 357 M e
355 358 A b
356 359 a
357 360 A c
358 361 a
359 362 R a
360 363
361 364 View graph:
362 365
363 366 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
364 367 @ test@11.draft: 3
365 368 |
366 369 o test@10.draft: 4
367 370 |
368 371 o test@9.draft: 5
369 372 |
370 373 o bar@8.draft: 1
371 374 |
372 375 o foo@7.draft: 2
373 376 |
374 377 | o test@6.secret: 6
375 378 | |\
376 379 | | o test@5.draft: 5
377 380 | | |
378 381 | o | test@4.draft: 4
379 382 | |/
380 383 | o baz@3.public: 3
381 384 | |
382 385 | o test@2.public: 2
383 386 | |
384 387 | o bar@1.public: 1
385 388 |/
386 389 o test@0.public: 0
387 390
388 391 Graft again onto another branch should preserve the original source
389 392 $ hg up -q 0
390 393 $ echo 'g'>g
391 394 $ hg add g
392 395 $ hg ci -m 7
393 396 created new head
394 397 $ hg graft 7
395 398 grafting 7:ef0ef43d49e7 "2"
396 399
397 400 $ hg log -r 7 --template '{rev}:{node}\n'
398 401 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
399 402 $ hg log -r 2 --template '{rev}:{node}\n'
400 403 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
401 404
402 405 $ hg log --debug -r tip
403 406 changeset: 13:7a4785234d87ec1aa420ed6b11afe40fa73e12a9
404 407 tag: tip
405 408 phase: draft
406 409 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
407 410 parent: -1:0000000000000000000000000000000000000000
408 411 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
409 412 user: foo
410 413 date: Thu Jan 01 00:00:00 1970 +0000
411 414 files+: b
412 415 files-: a
413 416 extra: branch=default
414 417 extra: intermediate-source=ef0ef43d49e79e81ddafdc7997401ba0041efc82
415 418 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
416 419 description:
417 420 2
418 421
419 422
420 423 Disallow grafting an already grafted cset onto its original branch
421 424 $ hg up -q 6
422 425 $ hg graft 7
423 426 skipping already grafted revision 7:ef0ef43d49e7 (was grafted from 2:5c095ad7e90f)
424 427 [255]
425 428
426 429 $ hg pdiff --config extensions.extdiff= --patch -r 2 -r 13
427 430 --- */hg-5c095ad7e90f.patch * (glob)
428 431 +++ */hg-7a4785234d87.patch * (glob)
429 432 @@ -1,18 +1,18 @@
430 433 # HG changeset patch
431 434 -# User test
432 435 +# User foo
433 436 # Date 0 0
434 437 # Thu Jan 01 00:00:00 1970 +0000
435 438 -# Node ID 5c095ad7e90f871700f02dd1fa5012cb4498a2d4
436 439 -# Parent 5d205f8b35b66bc36375c9534ffd3237730e8f04
437 440 +# Node ID 7a4785234d87ec1aa420ed6b11afe40fa73e12a9
438 441 +# Parent b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
439 442 2
440 443
441 444 -diff -r 5d205f8b35b6 -r 5c095ad7e90f a
442 445 +diff -r b592ea63bb0c -r 7a4785234d87 a
443 446 --- a/a Thu Jan 01 00:00:00 1970 +0000
444 447 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
445 448 @@ -1,1 +0,0 @@
446 449 --b
447 450 -diff -r 5d205f8b35b6 -r 5c095ad7e90f b
448 451 +-a
449 452 +diff -r b592ea63bb0c -r 7a4785234d87 b
450 453 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
451 454 +++ b/b Thu Jan 01 00:00:00 1970 +0000
452 455 @@ -0,0 +1,1 @@
453 456 -+b
454 457 ++a
455 458 [1]
456 459
457 460 $ hg pdiff --config extensions.extdiff= --patch -r 2 -r 13 -X .
458 461 --- */hg-5c095ad7e90f.patch * (glob)
459 462 +++ */hg-7a4785234d87.patch * (glob)
460 463 @@ -1,8 +1,8 @@
461 464 # HG changeset patch
462 465 -# User test
463 466 +# User foo
464 467 # Date 0 0
465 468 # Thu Jan 01 00:00:00 1970 +0000
466 469 -# Node ID 5c095ad7e90f871700f02dd1fa5012cb4498a2d4
467 470 -# Parent 5d205f8b35b66bc36375c9534ffd3237730e8f04
468 471 +# Node ID 7a4785234d87ec1aa420ed6b11afe40fa73e12a9
469 472 +# Parent b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
470 473 2
471 474
472 475 [1]
473 476
474 477 Disallow grafting already grafted csets with the same origin onto each other
475 478 $ hg up -q 13
476 479 $ hg graft 2
477 480 skipping revision 2:5c095ad7e90f (already grafted to 13:7a4785234d87)
478 481 [255]
479 482 $ hg graft 7
480 483 skipping already grafted revision 7:ef0ef43d49e7 (13:7a4785234d87 also has origin 2:5c095ad7e90f)
481 484 [255]
482 485
483 486 $ hg up -q 7
484 487 $ hg graft 2
485 488 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
486 489 [255]
487 490 $ hg graft tip
488 491 skipping already grafted revision 13:7a4785234d87 (7:ef0ef43d49e7 also has origin 2:5c095ad7e90f)
489 492 [255]
490 493
491 494 Graft with --log
492 495
493 496 $ hg up -Cq 1
494 497 $ hg graft 3 --log -u foo
495 498 grafting 3:4c60f11aa304 "3"
496 499 $ hg log --template '{rev}:{node|short} {parents} {desc}\n' -r tip
497 500 14:0c921c65ef1e 1:5d205f8b35b6 3
498 501 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
499 502
500 503 Resolve conflicted graft
501 504 $ hg up -q 0
502 505 $ echo b > a
503 506 $ hg ci -m 8
504 507 created new head
505 508 $ echo c > a
506 509 $ hg ci -m 9
507 510 $ hg graft 1 --tool internal:fail
508 511 grafting 1:5d205f8b35b6 "1"
509 512 abort: unresolved conflicts, can't continue
510 513 (use 'hg resolve' and 'hg graft --continue')
511 514 [255]
512 515 $ hg resolve --all
513 516 merging a
514 517 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
515 518 [1]
516 519 $ cat a
517 520 <<<<<<< local: aaa4406d4f0a - test: 9
518 521 c
519 522 =======
520 523 b
521 524 >>>>>>> graft: 5d205f8b35b6 - bar: 1
522 525 $ echo b > a
523 526 $ hg resolve -m a
524 527 (no more unresolved files)
525 528 continue: hg graft --continue
526 529 $ hg graft -c
527 530 grafting 1:5d205f8b35b6 "1"
528 531 $ hg export tip --git
529 532 # HG changeset patch
530 533 # User bar
531 534 # Date 0 0
532 535 # Thu Jan 01 00:00:00 1970 +0000
533 536 # Node ID f67661df0c4804d301f064f332b57e7d5ddaf2be
534 537 # Parent aaa4406d4f0ae9befd6e58c82ec63706460cbca6
535 538 1
536 539
537 540 diff --git a/a b/a
538 541 --- a/a
539 542 +++ b/a
540 543 @@ -1,1 +1,1 @@
541 544 -c
542 545 +b
543 546
544 547 Resolve conflicted graft with rename
545 548 $ echo c > a
546 549 $ hg ci -m 10
547 550 $ hg graft 2 --tool internal:fail
548 551 grafting 2:5c095ad7e90f "2"
549 552 abort: unresolved conflicts, can't continue
550 553 (use 'hg resolve' and 'hg graft --continue')
551 554 [255]
552 555 $ hg resolve --all
553 556 merging a and b to b
554 557 (no more unresolved files)
555 558 continue: hg graft --continue
556 559 $ hg graft -c
557 560 grafting 2:5c095ad7e90f "2"
558 561 $ hg export tip --git
559 562 # HG changeset patch
560 563 # User test
561 564 # Date 0 0
562 565 # Thu Jan 01 00:00:00 1970 +0000
563 566 # Node ID 9627f653b421c61fc1ea4c4e366745070fa3d2bc
564 567 # Parent ee295f490a40b97f3d18dd4c4f1c8936c233b612
565 568 2
566 569
567 570 diff --git a/a b/b
568 571 rename from a
569 572 rename to b
570 573
571 574 Test simple origin(), with and without args
572 575 $ hg log -r 'origin()'
573 576 changeset: 1:5d205f8b35b6
574 577 user: bar
575 578 date: Thu Jan 01 00:00:00 1970 +0000
576 579 summary: 1
577 580
578 581 changeset: 2:5c095ad7e90f
579 582 user: test
580 583 date: Thu Jan 01 00:00:00 1970 +0000
581 584 summary: 2
582 585
583 586 changeset: 3:4c60f11aa304
584 587 user: baz
585 588 date: Thu Jan 01 00:00:00 1970 +0000
586 589 summary: 3
587 590
588 591 changeset: 4:9c233e8e184d
589 592 user: test
590 593 date: Thu Jan 01 00:00:00 1970 +0000
591 594 summary: 4
592 595
593 596 changeset: 5:97f8bfe72746
594 597 branch: stable
595 598 parent: 3:4c60f11aa304
596 599 user: test
597 600 date: Thu Jan 01 00:00:00 1970 +0000
598 601 summary: 5
599 602
600 603 $ hg log -r 'origin(7)'
601 604 changeset: 2:5c095ad7e90f
602 605 user: test
603 606 date: Thu Jan 01 00:00:00 1970 +0000
604 607 summary: 2
605 608
606 609 Now transplant a graft to test following through copies
607 610 $ hg up -q 0
608 611 $ hg branch -q dev
609 612 $ hg ci -qm "dev branch"
610 613 $ hg --config extensions.transplant= transplant -q 7
611 614 $ hg log -r 'origin(.)'
612 615 changeset: 2:5c095ad7e90f
613 616 user: test
614 617 date: Thu Jan 01 00:00:00 1970 +0000
615 618 summary: 2
616 619
617 620 Test that the graft and transplant markers in extra are converted, allowing
618 621 origin() to still work. Note that these recheck the immediately preceeding two
619 622 tests.
620 623 $ hg --quiet --config extensions.convert= --config convert.hg.saverev=True convert . ../converted
621 624
622 625 The graft case
623 626 $ hg -R ../converted log -r 7 --template "{rev}: {node}\n{join(extras, '\n')}\n"
624 627 7: 7ae846e9111fc8f57745634250c7b9ac0a60689b
625 628 branch=default
626 629 convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
627 630 source=e0213322b2c1a5d5d236c74e79666441bee67a7d
628 631 $ hg -R ../converted log -r 'origin(7)'
629 632 changeset: 2:e0213322b2c1
630 633 user: test
631 634 date: Thu Jan 01 00:00:00 1970 +0000
632 635 summary: 2
633 636
634 637 Test that template correctly expands more than one 'extra' (issue4362), and that
635 638 'intermediate-source' is converted.
636 639 $ hg -R ../converted log -r 13 --template "{extras % ' Extra: {extra}\n'}"
637 640 Extra: branch=default
638 641 Extra: convert_revision=7a4785234d87ec1aa420ed6b11afe40fa73e12a9
639 642 Extra: intermediate-source=7ae846e9111fc8f57745634250c7b9ac0a60689b
640 643 Extra: source=e0213322b2c1a5d5d236c74e79666441bee67a7d
641 644
642 645 The transplant case
643 646 $ hg -R ../converted log -r tip --template "{rev}: {node}\n{join(extras, '\n')}\n"
644 647 21: fbb6c5cc81002f2b4b49c9d731404688bcae5ade
645 648 branch=dev
646 649 convert_revision=7e61b508e709a11d28194a5359bc3532d910af21
647 650 transplant_source=z\xe8F\xe9\x11\x1f\xc8\xf5wEcBP\xc7\xb9\xac\n`h\x9b
648 651 $ hg -R ../converted log -r 'origin(tip)'
649 652 changeset: 2:e0213322b2c1
650 653 user: test
651 654 date: Thu Jan 01 00:00:00 1970 +0000
652 655 summary: 2
653 656
654 657
655 658 Test simple destination
656 659 $ hg log -r 'destination()'
657 660 changeset: 7:ef0ef43d49e7
658 661 parent: 0:68795b066622
659 662 user: foo
660 663 date: Thu Jan 01 00:00:00 1970 +0000
661 664 summary: 2
662 665
663 666 changeset: 8:6b9e5368ca4e
664 667 user: bar
665 668 date: Thu Jan 01 00:00:00 1970 +0000
666 669 summary: 1
667 670
668 671 changeset: 9:1905859650ec
669 672 user: test
670 673 date: Thu Jan 01 00:00:00 1970 +0000
671 674 summary: 5
672 675
673 676 changeset: 10:52dc0b4c6907
674 677 user: test
675 678 date: Thu Jan 01 00:00:00 1970 +0000
676 679 summary: 4
677 680
678 681 changeset: 11:882b35362a6b
679 682 user: test
680 683 date: Thu Jan 01 00:00:00 1970 +0000
681 684 summary: 3
682 685
683 686 changeset: 13:7a4785234d87
684 687 user: foo
685 688 date: Thu Jan 01 00:00:00 1970 +0000
686 689 summary: 2
687 690
688 691 changeset: 14:0c921c65ef1e
689 692 parent: 1:5d205f8b35b6
690 693 user: foo
691 694 date: Thu Jan 01 00:00:00 1970 +0000
692 695 summary: 3
693 696
694 697 changeset: 17:f67661df0c48
695 698 user: bar
696 699 date: Thu Jan 01 00:00:00 1970 +0000
697 700 summary: 1
698 701
699 702 changeset: 19:9627f653b421
700 703 user: test
701 704 date: Thu Jan 01 00:00:00 1970 +0000
702 705 summary: 2
703 706
704 707 changeset: 21:7e61b508e709
705 708 branch: dev
706 709 tag: tip
707 710 user: foo
708 711 date: Thu Jan 01 00:00:00 1970 +0000
709 712 summary: 2
710 713
711 714 $ hg log -r 'destination(2)'
712 715 changeset: 7:ef0ef43d49e7
713 716 parent: 0:68795b066622
714 717 user: foo
715 718 date: Thu Jan 01 00:00:00 1970 +0000
716 719 summary: 2
717 720
718 721 changeset: 13:7a4785234d87
719 722 user: foo
720 723 date: Thu Jan 01 00:00:00 1970 +0000
721 724 summary: 2
722 725
723 726 changeset: 19:9627f653b421
724 727 user: test
725 728 date: Thu Jan 01 00:00:00 1970 +0000
726 729 summary: 2
727 730
728 731 changeset: 21:7e61b508e709
729 732 branch: dev
730 733 tag: tip
731 734 user: foo
732 735 date: Thu Jan 01 00:00:00 1970 +0000
733 736 summary: 2
734 737
735 738 Transplants of grafts can find a destination...
736 739 $ hg log -r 'destination(7)'
737 740 changeset: 21:7e61b508e709
738 741 branch: dev
739 742 tag: tip
740 743 user: foo
741 744 date: Thu Jan 01 00:00:00 1970 +0000
742 745 summary: 2
743 746
744 747 ... grafts of grafts unfortunately can't
745 748 $ hg graft -q 13 --debug
746 749 scanning for duplicate grafts
747 750 grafting 13:7a4785234d87 "2"
748 751 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
749 src: 'a' -> dst: 'b' *
752 on local side:
753 src: 'a' -> dst: 'b' *
754 on remote side:
755 src: 'a' -> dst: 'b' *
750 756 checking for directory renames
751 757 resolving manifests
752 758 branchmerge: True, force: True, partial: False
753 759 ancestor: b592ea63bb0c, local: 7e61b508e709+, remote: 7a4785234d87
754 760 starting 4 threads for background file closing (?)
755 761 note: graft of 13:7a4785234d87 created no changes to commit
756 762 $ hg log -r 'destination(13)'
757 763 All copies of a cset
758 764 $ hg log -r 'origin(13) or destination(origin(13))'
759 765 changeset: 2:5c095ad7e90f
760 766 user: test
761 767 date: Thu Jan 01 00:00:00 1970 +0000
762 768 summary: 2
763 769
764 770 changeset: 7:ef0ef43d49e7
765 771 parent: 0:68795b066622
766 772 user: foo
767 773 date: Thu Jan 01 00:00:00 1970 +0000
768 774 summary: 2
769 775
770 776 changeset: 13:7a4785234d87
771 777 user: foo
772 778 date: Thu Jan 01 00:00:00 1970 +0000
773 779 summary: 2
774 780
775 781 changeset: 19:9627f653b421
776 782 user: test
777 783 date: Thu Jan 01 00:00:00 1970 +0000
778 784 summary: 2
779 785
780 786 changeset: 21:7e61b508e709
781 787 branch: dev
782 788 tag: tip
783 789 user: foo
784 790 date: Thu Jan 01 00:00:00 1970 +0000
785 791 summary: 2
786 792
787 793
788 794 graft skips ancestors
789 795
790 796 $ hg graft 21 3
791 797 skipping ancestor revision 21:7e61b508e709
792 798 grafting 3:4c60f11aa304 "3"
793 799 merging b and c to c
794 800
795 801 graft with --force (still doesn't graft merges)
796 802
797 803 $ hg graft 19 0 6
798 804 skipping ungraftable merge revision 6
799 805 skipping ancestor revision 0:68795b066622
800 806 grafting 19:9627f653b421 "2"
801 807 merging b
802 808 note: graft of 19:9627f653b421 created no changes to commit
803 809 $ hg graft 19 0 6 --force
804 810 skipping ungraftable merge revision 6
805 811 grafting 19:9627f653b421 "2"
806 812 merging b
807 813 note: graft of 19:9627f653b421 created no changes to commit
808 814 grafting 0:68795b066622 "0"
809 815
810 816 graft --force after backout
811 817
812 818 $ echo abc > a
813 819 $ hg ci -m 24
814 820 $ hg backout 24
815 821 reverting a
816 822 changeset 25:71c4e63d4f98 backs out changeset 24:2e7ea477be26
817 823 $ hg graft 24
818 824 skipping ancestor revision 24:2e7ea477be26
819 825 [255]
820 826 $ hg graft 24 --force
821 827 grafting 24:2e7ea477be26 "24"
822 828 merging a
823 829 $ cat a
824 830 abc
825 831
826 832 graft --continue after --force
827 833
828 834 $ echo def > a
829 835 $ hg ci -m 27
830 836 $ hg graft 24 --force --tool internal:fail
831 837 grafting 24:2e7ea477be26 "24"
832 838 abort: unresolved conflicts, can't continue
833 839 (use 'hg resolve' and 'hg graft --continue')
834 840 [255]
835 841 $ hg resolve --all
836 842 merging a
837 843 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
838 844 [1]
839 845 $ echo abc > a
840 846 $ hg resolve -m a
841 847 (no more unresolved files)
842 848 continue: hg graft --continue
843 849 $ hg graft -c
844 850 grafting 24:2e7ea477be26 "24"
845 851 $ cat a
846 852 abc
847 853
848 854 Continue testing same origin policy, using revision numbers from test above
849 855 but do some destructive editing of the repo:
850 856
851 857 $ hg up -qC 7
852 858 $ hg tag -l -r 13 tmp
853 859 $ hg --config extensions.strip= strip 2
854 860 saved backup bundle to $TESTTMP/a/.hg/strip-backup/5c095ad7e90f-d323a1e4-backup.hg
855 861 $ hg graft tmp
856 862 skipping already grafted revision 8:7a4785234d87 (2:ef0ef43d49e7 also has unknown origin 5c095ad7e90f)
857 863 [255]
858 864
859 865 Empty graft
860 866
861 867 $ hg up -qr 22
862 868 $ hg tag -f something
863 869 $ hg graft -qr 23
864 870 $ hg graft -f 23
865 871 grafting 23:72d9c7c75bcc "24"
866 872 note: graft of 23:72d9c7c75bcc created no changes to commit
867 873
868 874 $ cd ..
869 875
870 876 Graft to duplicate a commit
871 877
872 878 $ hg init graftsibling
873 879 $ cd graftsibling
874 880 $ touch a
875 881 $ hg commit -qAm a
876 882 $ touch b
877 883 $ hg commit -qAm b
878 884 $ hg log -G -T '{rev}\n'
879 885 @ 1
880 886 |
881 887 o 0
882 888
883 889 $ hg up -q 0
884 890 $ hg graft -r 1
885 891 grafting 1:0e067c57feba "b" (tip)
886 892 $ hg log -G -T '{rev}\n'
887 893 @ 2
888 894 |
889 895 | o 1
890 896 |/
891 897 o 0
892 898
893 899 Graft to duplicate a commit twice
894 900
895 901 $ hg up -q 0
896 902 $ hg graft -r 2
897 903 grafting 2:044ec77f6389 "b" (tip)
898 904 $ hg log -G -T '{rev}\n'
899 905 @ 3
900 906 |
901 907 | o 2
902 908 |/
903 909 | o 1
904 910 |/
905 911 o 0
906 912
@@ -1,96 +1,99 b''
1 1 https://bz.mercurial-scm.org/672
2 2
3 3 # 0-2-4
4 4 # \ \ \
5 5 # 1-3-5
6 6 #
7 7 # rename in #1, content change in #4.
8 8
9 9 $ hg init
10 10
11 11 $ touch 1
12 12 $ touch 2
13 13 $ hg commit -Am init # 0
14 14 adding 1
15 15 adding 2
16 16
17 17 $ hg rename 1 1a
18 18 $ hg commit -m rename # 1
19 19
20 20 $ hg co -C 0
21 21 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
22 22
23 23 $ echo unrelated >> 2
24 24 $ hg ci -m unrelated1 # 2
25 25 created new head
26 26
27 27 $ hg merge --debug 1
28 28 unmatched files in other:
29 29 1a
30 30 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
31 src: '1' -> dst: '1a'
31 on remote side:
32 src: '1' -> dst: '1a'
32 33 checking for directory renames
33 34 resolving manifests
34 35 branchmerge: True, force: False, partial: False
35 36 ancestor: 81f4b099af3d, local: c64f439569a9+, remote: c12dcd37c90a
36 37 1: other deleted -> r
37 38 removing 1
38 39 1a: remote created -> g
39 40 getting 1a
40 41 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
41 42 (branch merge, don't forget to commit)
42 43
43 44 $ hg ci -m merge1 # 3
44 45
45 46 $ hg co -C 2
46 47 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
47 48
48 49 $ echo hello >> 1
49 50 $ hg ci -m unrelated2 # 4
50 51 created new head
51 52
52 53 $ hg co -C 3
53 54 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
54 55
55 56 $ hg merge -y --debug 4
56 57 unmatched files in local:
57 58 1a
58 59 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
59 src: '1' -> dst: '1a' *
60 on local side:
61 src: '1' -> dst: '1a' *
60 62 checking for directory renames
61 63 resolving manifests
62 64 branchmerge: True, force: False, partial: False
63 65 ancestor: c64f439569a9, local: f4a9cff3cd0b+, remote: 746e9549ea96
64 66 preserving 1a for resolve of 1a
65 67 starting 4 threads for background file closing (?)
66 68 1a: local copied/moved from 1 -> m (premerge)
67 69 picked tool ':merge' for 1a (binary False symlink False changedelete False)
68 70 merging 1a and 1 to 1a
69 71 my 1a@f4a9cff3cd0b+ other 1@746e9549ea96 ancestor 1@c64f439569a9
70 72 premerge successful
71 73 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
72 74 (branch merge, don't forget to commit)
73 75
74 76 $ hg co -C 4
75 77 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
76 78
77 79 $ hg merge -y --debug 3
78 80 unmatched files in other:
79 81 1a
80 82 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
81 src: '1' -> dst: '1a' *
83 on remote side:
84 src: '1' -> dst: '1a' *
82 85 checking for directory renames
83 86 resolving manifests
84 87 branchmerge: True, force: False, partial: False
85 88 ancestor: c64f439569a9, local: 746e9549ea96+, remote: f4a9cff3cd0b
86 89 preserving 1 for resolve of 1a
87 90 removing 1
88 91 starting 4 threads for background file closing (?)
89 92 1a: remote moved from 1 -> m (premerge)
90 93 picked tool ':merge' for 1a (binary False symlink False changedelete False)
91 94 merging 1 and 1a to 1a
92 95 my 1a@746e9549ea96+ other 1a@f4a9cff3cd0b ancestor 1@c64f439569a9
93 96 premerge successful
94 97 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
95 98 (branch merge, don't forget to commit)
96 99
@@ -1,445 +1,446 b''
1 1 Criss cross merging
2 2
3 3 $ hg init criss-cross
4 4 $ cd criss-cross
5 5 $ echo '0 base' > f1
6 6 $ echo '0 base' > f2
7 7 $ hg ci -Aqm '0 base'
8 8
9 9 $ echo '1 first change' > f1
10 10 $ hg ci -m '1 first change f1'
11 11
12 12 $ hg up -qr0
13 13 $ echo '2 first change' > f2
14 14 $ hg ci -qm '2 first change f2'
15 15
16 16 $ hg merge -qr 1
17 17 $ hg ci -m '3 merge'
18 18
19 19 $ hg up -qr2
20 20 $ hg merge -qr1
21 21 $ hg ci -qm '4 merge'
22 22
23 23 $ echo '5 second change' > f1
24 24 $ hg ci -m '5 second change f1'
25 25
26 26 $ hg up -r3
27 27 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
28 28 $ echo '6 second change' > f2
29 29 $ hg ci -m '6 second change f2'
30 30
31 31 $ hg log -G
32 32 @ changeset: 6:3b08d01b0ab5
33 33 | tag: tip
34 34 | parent: 3:cf89f02107e5
35 35 | user: test
36 36 | date: Thu Jan 01 00:00:00 1970 +0000
37 37 | summary: 6 second change f2
38 38 |
39 39 | o changeset: 5:adfe50279922
40 40 | | user: test
41 41 | | date: Thu Jan 01 00:00:00 1970 +0000
42 42 | | summary: 5 second change f1
43 43 | |
44 44 | o changeset: 4:7d3e55501ae6
45 45 | |\ parent: 2:40663881a6dd
46 46 | | | parent: 1:0f6b37dbe527
47 47 | | | user: test
48 48 | | | date: Thu Jan 01 00:00:00 1970 +0000
49 49 | | | summary: 4 merge
50 50 | | |
51 51 o---+ changeset: 3:cf89f02107e5
52 52 | | | parent: 2:40663881a6dd
53 53 |/ / parent: 1:0f6b37dbe527
54 54 | | user: test
55 55 | | date: Thu Jan 01 00:00:00 1970 +0000
56 56 | | summary: 3 merge
57 57 | |
58 58 | o changeset: 2:40663881a6dd
59 59 | | parent: 0:40494bf2444c
60 60 | | user: test
61 61 | | date: Thu Jan 01 00:00:00 1970 +0000
62 62 | | summary: 2 first change f2
63 63 | |
64 64 o | changeset: 1:0f6b37dbe527
65 65 |/ user: test
66 66 | date: Thu Jan 01 00:00:00 1970 +0000
67 67 | summary: 1 first change f1
68 68 |
69 69 o changeset: 0:40494bf2444c
70 70 user: test
71 71 date: Thu Jan 01 00:00:00 1970 +0000
72 72 summary: 0 base
73 73
74 74
75 75 $ hg merge -v --debug --tool internal:dump 5 --config merge.preferancestor='!'
76 76 note: using 0f6b37dbe527 as ancestor of 3b08d01b0ab5 and adfe50279922
77 77 alternatively, use --config merge.preferancestor=40663881a6dd
78 78 resolving manifests
79 79 branchmerge: True, force: False, partial: False
80 80 ancestor: 0f6b37dbe527, local: 3b08d01b0ab5+, remote: adfe50279922
81 81 preserving f2 for resolve of f2
82 82 f1: remote is newer -> g
83 83 getting f1
84 84 f2: versions differ -> m (premerge)
85 85 picked tool ':dump' for f2 (binary False symlink False changedelete False)
86 86 merging f2
87 87 my f2@3b08d01b0ab5+ other f2@adfe50279922 ancestor f2@0f6b37dbe527
88 88 f2: versions differ -> m (merge)
89 89 picked tool ':dump' for f2 (binary False symlink False changedelete False)
90 90 my f2@3b08d01b0ab5+ other f2@adfe50279922 ancestor f2@0f6b37dbe527
91 91 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
92 92 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
93 93 [1]
94 94
95 95 $ f --dump *
96 96 f1:
97 97 >>>
98 98 5 second change
99 99 <<<
100 100 f2:
101 101 >>>
102 102 6 second change
103 103 <<<
104 104 f2.base:
105 105 >>>
106 106 0 base
107 107 <<<
108 108 f2.local:
109 109 >>>
110 110 6 second change
111 111 <<<
112 112 f2.orig:
113 113 >>>
114 114 6 second change
115 115 <<<
116 116 f2.other:
117 117 >>>
118 118 2 first change
119 119 <<<
120 120
121 121 $ hg up -qC .
122 122 $ hg merge -v --tool internal:dump 5 --config merge.preferancestor="null 40663881 3b08d"
123 123 note: using 40663881a6dd as ancestor of 3b08d01b0ab5 and adfe50279922
124 124 alternatively, use --config merge.preferancestor=0f6b37dbe527
125 125 resolving manifests
126 126 merging f1
127 127 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
128 128 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
129 129 [1]
130 130
131 131 Redo merge with merge.preferancestor="*" to enable bid merge
132 132
133 133 $ rm f*
134 134 $ hg up -qC .
135 135 $ hg merge -v --debug --tool internal:dump 5 --config merge.preferancestor="*"
136 136 note: merging 3b08d01b0ab5+ and adfe50279922 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
137 137
138 138 calculating bids for ancestor 0f6b37dbe527
139 139 resolving manifests
140 140 branchmerge: True, force: False, partial: False
141 141 ancestor: 0f6b37dbe527, local: 3b08d01b0ab5+, remote: adfe50279922
142 142 f1: remote is newer -> g
143 143 f2: versions differ -> m
144 144
145 145 calculating bids for ancestor 40663881a6dd
146 146 resolving manifests
147 147 branchmerge: True, force: False, partial: False
148 148 ancestor: 40663881a6dd, local: 3b08d01b0ab5+, remote: adfe50279922
149 149 f1: versions differ -> m
150 150 f2: remote unchanged -> k
151 151
152 152 auction for merging merge bids
153 153 f1: picking 'get' action
154 154 f2: picking 'keep' action
155 155 end of auction
156 156
157 157 f1: remote is newer -> g
158 158 getting f1
159 159 f2: remote unchanged -> k
160 160 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
161 161 (branch merge, don't forget to commit)
162 162
163 163 $ f --dump *
164 164 f1:
165 165 >>>
166 166 5 second change
167 167 <<<
168 168 f2:
169 169 >>>
170 170 6 second change
171 171 <<<
172 172
173 173
174 174 The other way around:
175 175
176 176 $ hg up -C -r5
177 177 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
178 178 $ hg merge -v --debug --config merge.preferancestor="*"
179 179 note: merging adfe50279922+ and 3b08d01b0ab5 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
180 180
181 181 calculating bids for ancestor 0f6b37dbe527
182 182 resolving manifests
183 183 branchmerge: True, force: False, partial: False
184 184 ancestor: 0f6b37dbe527, local: adfe50279922+, remote: 3b08d01b0ab5
185 185 f1: remote unchanged -> k
186 186 f2: versions differ -> m
187 187
188 188 calculating bids for ancestor 40663881a6dd
189 189 resolving manifests
190 190 branchmerge: True, force: False, partial: False
191 191 ancestor: 40663881a6dd, local: adfe50279922+, remote: 3b08d01b0ab5
192 192 f1: versions differ -> m
193 193 f2: remote is newer -> g
194 194
195 195 auction for merging merge bids
196 196 f1: picking 'keep' action
197 197 f2: picking 'get' action
198 198 end of auction
199 199
200 200 f2: remote is newer -> g
201 201 getting f2
202 202 f1: remote unchanged -> k
203 203 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
204 204 (branch merge, don't forget to commit)
205 205
206 206 $ f --dump *
207 207 f1:
208 208 >>>
209 209 5 second change
210 210 <<<
211 211 f2:
212 212 >>>
213 213 6 second change
214 214 <<<
215 215
216 216 Verify how the output looks and and how verbose it is:
217 217
218 218 $ hg up -qC
219 219 $ hg merge
220 220 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
221 221 (branch merge, don't forget to commit)
222 222
223 223 $ hg up -qC tip
224 224 $ hg merge -v
225 225 note: merging 3b08d01b0ab5+ and adfe50279922 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
226 226
227 227 calculating bids for ancestor 0f6b37dbe527
228 228 resolving manifests
229 229
230 230 calculating bids for ancestor 40663881a6dd
231 231 resolving manifests
232 232
233 233 auction for merging merge bids
234 234 f1: picking 'get' action
235 235 f2: picking 'keep' action
236 236 end of auction
237 237
238 238 getting f1
239 239 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
240 240 (branch merge, don't forget to commit)
241 241
242 242 $ hg up -qC
243 243 $ hg merge -v --debug --config merge.preferancestor="*"
244 244 note: merging 3b08d01b0ab5+ and adfe50279922 using bids from ancestors 0f6b37dbe527 and 40663881a6dd
245 245
246 246 calculating bids for ancestor 0f6b37dbe527
247 247 resolving manifests
248 248 branchmerge: True, force: False, partial: False
249 249 ancestor: 0f6b37dbe527, local: 3b08d01b0ab5+, remote: adfe50279922
250 250 f1: remote is newer -> g
251 251 f2: versions differ -> m
252 252
253 253 calculating bids for ancestor 40663881a6dd
254 254 resolving manifests
255 255 branchmerge: True, force: False, partial: False
256 256 ancestor: 40663881a6dd, local: 3b08d01b0ab5+, remote: adfe50279922
257 257 f1: versions differ -> m
258 258 f2: remote unchanged -> k
259 259
260 260 auction for merging merge bids
261 261 f1: picking 'get' action
262 262 f2: picking 'keep' action
263 263 end of auction
264 264
265 265 f1: remote is newer -> g
266 266 getting f1
267 267 f2: remote unchanged -> k
268 268 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
269 269 (branch merge, don't forget to commit)
270 270
271 271 Test the greatest common ancestor returning multiple changesets
272 272
273 273 $ hg log -r 'heads(commonancestors(head()))'
274 274 changeset: 1:0f6b37dbe527
275 275 user: test
276 276 date: Thu Jan 01 00:00:00 1970 +0000
277 277 summary: 1 first change f1
278 278
279 279 changeset: 2:40663881a6dd
280 280 parent: 0:40494bf2444c
281 281 user: test
282 282 date: Thu Jan 01 00:00:00 1970 +0000
283 283 summary: 2 first change f2
284 284
285 285
286 286 $ cd ..
287 287
288 288 http://stackoverflow.com/questions/9350005/how-do-i-specify-a-merge-base-to-use-in-a-hg-merge/9430810
289 289
290 290 $ hg init ancestor-merging
291 291 $ cd ancestor-merging
292 292 $ echo a > x
293 293 $ hg commit -A -m a x
294 294 $ hg update -q 0
295 295 $ echo b >> x
296 296 $ hg commit -m b
297 297 $ hg update -q 0
298 298 $ echo c >> x
299 299 $ hg commit -qm c
300 300 $ hg update -q 1
301 301 $ hg merge -q --tool internal:local 2
302 302 $ echo c >> x
303 303 $ hg commit -m bc
304 304 $ hg update -q 2
305 305 $ hg merge -q --tool internal:local 1
306 306 $ echo b >> x
307 307 $ hg commit -qm cb
308 308
309 309 $ hg merge --config merge.preferancestor='!'
310 310 note: using 70008a2163f6 as ancestor of 0d355fdef312 and 4b8b546a3eef
311 311 alternatively, use --config merge.preferancestor=b211bbc6eb3c
312 312 merging x
313 313 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
314 314 (branch merge, don't forget to commit)
315 315 $ cat x
316 316 a
317 317 c
318 318 b
319 319 c
320 320
321 321 $ hg up -qC .
322 322
323 323 $ hg merge --config merge.preferancestor=b211bbc6eb3c
324 324 note: using b211bbc6eb3c as ancestor of 0d355fdef312 and 4b8b546a3eef
325 325 alternatively, use --config merge.preferancestor=70008a2163f6
326 326 merging x
327 327 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
328 328 (branch merge, don't forget to commit)
329 329 $ cat x
330 330 a
331 331 b
332 332 c
333 333 b
334 334
335 335 $ hg up -qC .
336 336
337 337 $ hg merge -v --config merge.preferancestor="*"
338 338 note: merging 0d355fdef312+ and 4b8b546a3eef using bids from ancestors 70008a2163f6 and b211bbc6eb3c
339 339
340 340 calculating bids for ancestor 70008a2163f6
341 341 resolving manifests
342 342
343 343 calculating bids for ancestor b211bbc6eb3c
344 344 resolving manifests
345 345
346 346 auction for merging merge bids
347 347 x: multiple bids for merge action:
348 348 versions differ -> m
349 349 versions differ -> m
350 350 x: ambiguous merge - picked m action
351 351 end of auction
352 352
353 353 merging x
354 354 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
355 355 (branch merge, don't forget to commit)
356 356 $ cat x
357 357 a
358 358 c
359 359 b
360 360 c
361 361
362 362 Verify that the old context ancestor works with / despite preferancestor:
363 363
364 364 $ hg log -r 'ancestor(head())' --config merge.preferancestor=1 -T '{rev}\n'
365 365 1
366 366 $ hg log -r 'ancestor(head())' --config merge.preferancestor=2 -T '{rev}\n'
367 367 2
368 368 $ hg log -r 'ancestor(head())' --config merge.preferancestor=3 -T '{rev}\n'
369 369 1
370 370 $ hg log -r 'ancestor(head())' --config merge.preferancestor='1337 * - 2' -T '{rev}\n'
371 371 2
372 372
373 373 $ cd ..
374 374
375 375 $ hg init issue5020
376 376 $ cd issue5020
377 377
378 378 $ echo a > noop
379 379 $ hg ci -qAm initial
380 380
381 381 $ echo b > noop
382 382 $ hg ci -qAm 'uninteresting change'
383 383
384 384 $ hg up -q 0
385 385 $ mkdir d1
386 386 $ echo a > d1/a
387 387 $ echo b > d1/b
388 388 $ hg ci -qAm 'add d1/a and d1/b'
389 389
390 390 $ hg merge -q 1
391 391 $ hg rm d1/a
392 392 $ hg mv -q d1 d2
393 393 $ hg ci -qm 'merge while removing d1/a and moving d1/b to d2/b'
394 394
395 395 $ hg up -q 1
396 396 $ hg merge -q 2
397 397 $ hg ci -qm 'merge (no changes while merging)'
398 398 $ hg log -G -T '{rev}:{node|short} {desc}'
399 399 @ 4:c0ef19750a22 merge (no changes while merging)
400 400 |\
401 401 +---o 3:6ca01f7342b9 merge while removing d1/a and moving d1/b to d2/b
402 402 | |/
403 403 | o 2:154e6000f54e add d1/a and d1/b
404 404 | |
405 405 o | 1:11b5b303e36c uninteresting change
406 406 |/
407 407 o 0:7b54db1ebf33 initial
408 408
409 409 $ hg merge 3 --debug
410 410 note: merging c0ef19750a22+ and 6ca01f7342b9 using bids from ancestors 11b5b303e36c and 154e6000f54e
411 411
412 412 calculating bids for ancestor 11b5b303e36c
413 413 resolving manifests
414 414 branchmerge: True, force: False, partial: False
415 415 ancestor: 11b5b303e36c, local: c0ef19750a22+, remote: 6ca01f7342b9
416 416 d2/b: remote created -> g
417 417
418 418 calculating bids for ancestor 154e6000f54e
419 419 unmatched files in other:
420 420 d2/b
421 421 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
422 src: 'd1/b' -> dst: 'd2/b'
422 on remote side:
423 src: 'd1/b' -> dst: 'd2/b'
423 424 checking for directory renames
424 425 discovered dir src: 'd1/' -> dst: 'd2/'
425 426 resolving manifests
426 427 branchmerge: True, force: False, partial: False
427 428 ancestor: 154e6000f54e, local: c0ef19750a22+, remote: 6ca01f7342b9
428 429 d1/a: other deleted -> r
429 430 d1/b: other deleted -> r
430 431 d2/b: remote created -> g
431 432
432 433 auction for merging merge bids
433 434 d1/a: consensus for r
434 435 d1/b: consensus for r
435 436 d2/b: consensus for g
436 437 end of auction
437 438
438 439 d1/a: other deleted -> r
439 440 removing d1/a
440 441 d1/b: other deleted -> r
441 442 removing d1/b
442 443 d2/b: remote created -> g
443 444 getting d2/b
444 445 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
445 446 (branch merge, don't forget to commit)
@@ -1,294 +1,296 b''
1 1 $ hg init t
2 2 $ cd t
3 3
4 4 $ mkdir a
5 5 $ echo foo > a/a
6 6 $ echo bar > a/b
7 7 $ hg ci -Am "0"
8 8 adding a/a
9 9 adding a/b
10 10
11 11 $ hg co -C 0
12 12 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
13 13 $ hg mv a b
14 14 moving a/a to b/a
15 15 moving a/b to b/b
16 16 $ hg ci -m "1 mv a/ b/"
17 17
18 18 $ hg co -C 0
19 19 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
20 20 $ echo baz > a/c
21 21 $ echo quux > a/d
22 22 $ hg add a/c
23 23 $ hg ci -m "2 add a/c"
24 24 created new head
25 25
26 26 $ hg merge --debug 1
27 27 unmatched files in local:
28 28 a/c
29 29 unmatched files in other:
30 30 b/a
31 31 b/b
32 32 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
33 src: 'a/a' -> dst: 'b/a'
34 src: 'a/b' -> dst: 'b/b'
33 on remote side:
34 src: 'a/a' -> dst: 'b/a'
35 src: 'a/b' -> dst: 'b/b'
35 36 checking for directory renames
36 37 discovered dir src: 'a/' -> dst: 'b/'
37 38 pending file src: 'a/c' -> dst: 'b/c'
38 39 resolving manifests
39 40 branchmerge: True, force: False, partial: False
40 41 ancestor: f9b20c0d4c51, local: ce36d17b18fb+, remote: 397f8b00a740
41 42 a/a: other deleted -> r
42 43 removing a/a
43 44 a/b: other deleted -> r
44 45 removing a/b
45 46 b/a: remote created -> g
46 47 getting b/a
47 48 b/b: remote created -> g
48 49 getting b/b
49 50 b/c: remote directory rename - move from a/c -> dm
50 51 moving a/c to b/c
51 52 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
52 53 (branch merge, don't forget to commit)
53 54
54 55 $ echo a/* b/*
55 56 a/d b/a b/b b/c
56 57 $ hg st -C
57 58 M b/a
58 59 M b/b
59 60 A b/c
60 61 a/c
61 62 R a/a
62 63 R a/b
63 64 R a/c
64 65 ? a/d
65 66 $ hg ci -m "3 merge 2+1"
66 67 $ hg debugrename b/c
67 68 b/c renamed from a/c:354ae8da6e890359ef49ade27b68bbc361f3ca88
68 69
69 70 $ hg co -C 1
70 71 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
71 72 $ hg merge --debug 2
72 73 unmatched files in local:
73 74 b/a
74 75 b/b
75 76 unmatched files in other:
76 77 a/c
77 78 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
78 src: 'a/a' -> dst: 'b/a'
79 src: 'a/b' -> dst: 'b/b'
79 on local side:
80 src: 'a/a' -> dst: 'b/a'
81 src: 'a/b' -> dst: 'b/b'
80 82 checking for directory renames
81 83 discovered dir src: 'a/' -> dst: 'b/'
82 84 pending file src: 'a/c' -> dst: 'b/c'
83 85 resolving manifests
84 86 branchmerge: True, force: False, partial: False
85 87 ancestor: f9b20c0d4c51, local: 397f8b00a740+, remote: ce36d17b18fb
86 88 starting 4 threads for background file closing (?)
87 89 b/c: local directory rename - get from a/c -> dg
88 90 getting a/c to b/c
89 91 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 92 (branch merge, don't forget to commit)
91 93
92 94 $ echo a/* b/*
93 95 a/d b/a b/b b/c
94 96 $ hg st -C
95 97 A b/c
96 98 a/c
97 99 ? a/d
98 100 $ hg ci -m "4 merge 1+2"
99 101 created new head
100 102 $ hg debugrename b/c
101 103 b/c renamed from a/c:354ae8da6e890359ef49ade27b68bbc361f3ca88
102 104
103 105 Local directory rename with conflicting file added in remote source directory
104 106 and untracked in local target directory.
105 107
106 108 $ hg co -qC 1
107 109 $ echo target > b/c
108 110 $ hg merge 2
109 111 b/c: untracked file differs
110 112 abort: untracked files in working directory differ from files in requested revision
111 113 [255]
112 114 $ cat b/c
113 115 target
114 116 but it should succeed if the content matches
115 117 $ hg cat -r 2 a/c > b/c
116 118 $ hg merge 2
117 119 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
118 120 (branch merge, don't forget to commit)
119 121 $ hg st -C
120 122 A b/c
121 123 a/c
122 124 ? a/d
123 125
124 126 Local directory rename with conflicting file added in remote source directory
125 127 and committed in local target directory.
126 128
127 129 $ hg co -qC 1
128 130 $ echo target > b/c
129 131 $ hg add b/c
130 132 $ hg commit -qm 'new file in target directory'
131 133 $ hg merge 2
132 134 merging b/c and a/c to b/c
133 135 warning: conflicts while merging b/c! (edit, then use 'hg resolve --mark')
134 136 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
135 137 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
136 138 [1]
137 139 $ hg st -A
138 140 M b/c
139 141 a/c
140 142 ? a/d
141 143 ? b/c.orig
142 144 C b/a
143 145 C b/b
144 146 $ cat b/c
145 147 <<<<<<< working copy: f1c50ca4f127 - test: new file in target directory
146 148 target
147 149 =======
148 150 baz
149 151 >>>>>>> merge rev: ce36d17b18fb - test: 2 add a/c
150 152 $ rm b/c.orig
151 153
152 154 Remote directory rename with conflicting file added in remote target directory
153 155 and committed in local source directory.
154 156
155 157 $ hg co -qC 2
156 158 $ hg st -A
157 159 ? a/d
158 160 C a/a
159 161 C a/b
160 162 C a/c
161 163 $ hg merge 5
162 164 merging a/c and b/c to b/c
163 165 warning: conflicts while merging b/c! (edit, then use 'hg resolve --mark')
164 166 2 files updated, 0 files merged, 2 files removed, 1 files unresolved
165 167 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
166 168 [1]
167 169 $ hg st -A
168 170 M b/a
169 171 M b/b
170 172 M b/c
171 173 a/c
172 174 R a/a
173 175 R a/b
174 176 R a/c
175 177 ? a/d
176 178 ? b/c.orig
177 179 $ cat b/c
178 180 <<<<<<< working copy: ce36d17b18fb - test: 2 add a/c
179 181 baz
180 182 =======
181 183 target
182 184 >>>>>>> merge rev: f1c50ca4f127 - test: new file in target directory
183 185
184 186 Second scenario with two repos:
185 187
186 188 $ cd ..
187 189 $ hg init r1
188 190 $ cd r1
189 191 $ mkdir a
190 192 $ echo foo > a/f
191 193 $ hg add a
192 194 adding a/f
193 195 $ hg ci -m "a/f == foo"
194 196 $ cd ..
195 197
196 198 $ hg clone r1 r2
197 199 updating to branch default
198 200 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
199 201 $ cd r2
200 202 $ hg mv a b
201 203 moving a/f to b/f
202 204 $ echo foo1 > b/f
203 205 $ hg ci -m" a -> b, b/f == foo1"
204 206 $ cd ..
205 207
206 208 $ cd r1
207 209 $ mkdir a/aa
208 210 $ echo bar > a/aa/g
209 211 $ hg add a/aa
210 212 adding a/aa/g
211 213 $ hg ci -m "a/aa/g"
212 214 $ hg pull ../r2
213 215 pulling from ../r2
214 216 searching for changes
215 217 adding changesets
216 218 adding manifests
217 219 adding file changes
218 220 added 1 changesets with 1 changes to 1 files (+1 heads)
219 221 new changesets 7d51ed18da25
220 222 1 local changesets published
221 223 (run 'hg heads' to see heads, 'hg merge' to merge)
222 224
223 225 $ hg merge
224 226 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
225 227 (branch merge, don't forget to commit)
226 228
227 229 $ hg st -C
228 230 M b/f
229 231 A b/aa/g
230 232 a/aa/g
231 233 R a/aa/g
232 234 R a/f
233 235
234 236 $ cd ..
235 237
236 238 Test renames to separate directories
237 239
238 240 $ hg init a
239 241 $ cd a
240 242 $ mkdir a
241 243 $ touch a/s
242 244 $ touch a/t
243 245 $ hg ci -Am0
244 246 adding a/s
245 247 adding a/t
246 248
247 249 Add more files
248 250
249 251 $ touch a/s2
250 252 $ touch a/t2
251 253 $ hg ci -Am1
252 254 adding a/s2
253 255 adding a/t2
254 256
255 257 Do moves on a branch
256 258
257 259 $ hg up 0
258 260 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
259 261 $ mkdir s
260 262 $ mkdir t
261 263 $ hg mv a/s s
262 264 $ hg mv a/t t
263 265 $ hg ci -Am2
264 266 created new head
265 267 $ hg st --copies --change .
266 268 A s/s
267 269 a/s
268 270 A t/t
269 271 a/t
270 272 R a/s
271 273 R a/t
272 274
273 275 Merge shouldn't move s2, t2
274 276
275 277 $ hg merge
276 278 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
277 279 (branch merge, don't forget to commit)
278 280 $ hg st --copies
279 281 M a/s2
280 282 M a/t2
281 283
282 284 Try the merge in the other direction. It may or may not be appropriate for
283 285 status to list copies here.
284 286
285 287 $ hg up -C 1
286 288 4 files updated, 0 files merged, 2 files removed, 0 files unresolved
287 289 $ hg merge
288 290 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
289 291 (branch merge, don't forget to commit)
290 292 $ hg st --copies
291 293 M s/s
292 294 M t/t
293 295 R a/s
294 296 R a/t
@@ -1,256 +1,262 b''
1 1 $ hg init
2 2
3 3 $ echo "[merge]" >> .hg/hgrc
4 4 $ echo "followcopies = 1" >> .hg/hgrc
5 5
6 6 $ echo foo > a
7 7 $ echo foo > a2
8 8 $ hg add a a2
9 9 $ hg ci -m "start"
10 10
11 11 $ hg mv a b
12 12 $ hg mv a2 b2
13 13 $ hg ci -m "rename"
14 14
15 15 $ hg co 0
16 16 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
17 17
18 18 $ echo blahblah > a
19 19 $ echo blahblah > a2
20 20 $ hg mv a2 c2
21 21 $ hg ci -m "modify"
22 22 created new head
23 23
24 24 $ hg merge -y --debug
25 25 unmatched files in local:
26 26 c2
27 27 unmatched files in other:
28 28 b
29 29 b2
30 30 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
31 src: 'a' -> dst: 'b' *
32 src: 'a2' -> dst: 'b2' !
33 src: 'a2' -> dst: 'c2' !
31 on local side:
32 src: 'a2' -> dst: 'c2' !
33 on remote side:
34 src: 'a' -> dst: 'b' *
35 src: 'a2' -> dst: 'b2' !
34 36 checking for directory renames
35 37 resolving manifests
36 38 branchmerge: True, force: False, partial: False
37 39 ancestor: af1939970a1c, local: 044f8520aeeb+, remote: 85c198ef2f6c
38 40 note: possible conflict - a2 was renamed multiple times to:
39 41 b2
40 42 c2
41 43 preserving a for resolve of b
42 44 removing a
43 45 b2: remote created -> g
44 46 getting b2
45 47 b: remote moved from a -> m (premerge)
46 48 picked tool ':merge' for b (binary False symlink False changedelete False)
47 49 merging a and b to b
48 50 my b@044f8520aeeb+ other b@85c198ef2f6c ancestor a@af1939970a1c
49 51 premerge successful
50 52 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
51 53 (branch merge, don't forget to commit)
52 54
53 55 $ hg status -AC
54 56 M b
55 57 a
56 58 M b2
57 59 R a
58 60 C c2
59 61
60 62 $ cat b
61 63 blahblah
62 64
63 65 $ hg ci -m "merge"
64 66
65 67 $ hg debugindex b
66 68 rev linkrev nodeid p1 p2
67 69 0 1 57eacc201a7f 000000000000 000000000000
68 70 1 3 4727ba907962 000000000000 57eacc201a7f
69 71
70 72 $ hg debugrename b
71 73 b renamed from a:dd03b83622e78778b403775d0d074b9ac7387a66
72 74
73 75 This used to trigger a "divergent renames" warning, despite no renames
74 76
75 77 $ hg cp b b3
76 78 $ hg cp b b4
77 79 $ hg ci -A -m 'copy b twice'
78 80 $ hg up '.^'
79 81 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
80 82 $ hg up
81 83 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
82 84 $ hg rm b3 b4
83 85 $ hg ci -m 'clean up a bit of our mess'
84 86
85 87 We'd rather not warn on divergent renames done in the same changeset (issue2113)
86 88
87 89 $ hg cp b b3
88 90 $ hg mv b b4
89 91 $ hg ci -A -m 'divergent renames in same changeset'
90 92 $ hg up '.^'
91 93 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
92 94 $ hg up
93 95 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
94 96
95 97 Check for issue2642
96 98
97 99 $ hg init t
98 100 $ cd t
99 101
100 102 $ echo c0 > f1
101 103 $ hg ci -Aqm0
102 104
103 105 $ hg up null -q
104 106 $ echo c1 > f1 # backport
105 107 $ hg ci -Aqm1
106 108 $ hg mv f1 f2
107 109 $ hg ci -qm2
108 110
109 111 $ hg up 0 -q
110 112 $ hg merge 1 -q --tool internal:local
111 113 $ hg ci -qm3
112 114
113 115 $ hg merge 2
114 116 merging f1 and f2 to f2
115 117 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
116 118 (branch merge, don't forget to commit)
117 119
118 120 $ cat f2
119 121 c0
120 122
121 123 $ cd ..
122 124
123 125 Check for issue2089
124 126
125 127 $ hg init repo2089
126 128 $ cd repo2089
127 129
128 130 $ echo c0 > f1
129 131 $ hg ci -Aqm0
130 132
131 133 $ hg up null -q
132 134 $ echo c1 > f1
133 135 $ hg ci -Aqm1
134 136
135 137 $ hg up 0 -q
136 138 $ hg merge 1 -q --tool internal:local
137 139 $ echo c2 > f1
138 140 $ hg ci -qm2
139 141
140 142 $ hg up 1 -q
141 143 $ hg mv f1 f2
142 144 $ hg ci -Aqm3
143 145
144 146 $ hg up 2 -q
145 147 $ hg merge 3
146 148 merging f1 and f2 to f2
147 149 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
148 150 (branch merge, don't forget to commit)
149 151
150 152 $ cat f2
151 153 c2
152 154
153 155 $ cd ..
154 156
155 157 Check for issue3074
156 158
157 159 $ hg init repo3074
158 160 $ cd repo3074
159 161 $ echo foo > file
160 162 $ hg add file
161 163 $ hg commit -m "added file"
162 164 $ hg mv file newfile
163 165 $ hg commit -m "renamed file"
164 166 $ hg update 0
165 167 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
166 168 $ hg rm file
167 169 $ hg commit -m "deleted file"
168 170 created new head
169 171 $ hg merge --debug
170 172 unmatched files in other:
171 173 newfile
172 174 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
173 src: 'file' -> dst: 'newfile' %
175 on remote side:
176 src: 'file' -> dst: 'newfile' %
174 177 checking for directory renames
175 178 resolving manifests
176 179 branchmerge: True, force: False, partial: False
177 180 ancestor: 19d7f95df299, local: 0084274f6b67+, remote: 5d32493049f0
178 181 note: possible conflict - file was deleted and renamed to:
179 182 newfile
180 183 newfile: remote created -> g
181 184 getting newfile
182 185 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
183 186 (branch merge, don't forget to commit)
184 187 $ hg status
185 188 M newfile
186 189 $ cd ..
187 190
188 191 Create x and y, then modify y and rename x to z on one side of merge, and
189 192 modify x and rename y to z on the other side.
190 193 $ hg init conflicting-target
191 194 $ cd conflicting-target
192 195 $ echo x > x
193 196 $ echo y > y
194 197 $ hg ci -Aqm 'add x and y'
195 198 $ hg mv x z
196 199 $ echo foo >> y
197 200 $ hg ci -qm 'modify y, rename x to z'
198 201 $ hg co -q 0
199 202 $ hg mv y z
200 203 $ echo foo >> x
201 204 $ hg ci -qm 'modify x, rename y to z'
202 205 # We should probably tell the user about the conflicting rename sources.
203 206 # Depending on which side they pick, we should take that rename and get
204 207 # the changes to the source from the other side. The unchanged file should
205 208 # remain.
206 209 # we should not get the prompts about modify/delete conflicts
207 210 $ hg merge --debug 1 -t :merge3
208 211 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
209 src: 'x' -> dst: 'z'
212 on local side:
213 src: 'y' -> dst: 'z'
214 on remote side:
215 src: 'x' -> dst: 'z'
210 216 checking for directory renames
211 217 resolving manifests
212 218 branchmerge: True, force: False, partial: False
213 219 ancestor: 5151c134577e, local: 07fcbc9a74ed+, remote: f21419739508
214 220 preserving x for resolve of x
215 221 preserving z for resolve of z
216 222 starting 4 threads for background file closing (?)
217 223 x: prompt changed/deleted -> m (premerge)
218 224 picked tool ':prompt' for x (binary False symlink False changedelete True)
219 225 file 'x' was deleted in other [merge rev] but was modified in local [working copy].
220 226 You can use (c)hanged version, (d)elete, or leave (u)nresolved.
221 227 What do you want to do? u
222 228 y: prompt deleted/changed -> m (premerge)
223 229 picked tool ':prompt' for y (binary False symlink False changedelete True)
224 230 file 'y' was deleted in local [working copy] but was modified in other [merge rev].
225 231 You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.
226 232 What do you want to do? u
227 233 z: both created -> m (premerge)
228 234 picked tool ':merge3' for z (binary False symlink False changedelete False)
229 235 merging z
230 236 my z@07fcbc9a74ed+ other z@f21419739508 ancestor z@000000000000
231 237 z: both created -> m (merge)
232 238 picked tool ':merge3' for z (binary False symlink False changedelete False)
233 239 my z@07fcbc9a74ed+ other z@f21419739508 ancestor z@000000000000
234 240 warning: conflicts while merging z! (edit, then use 'hg resolve --mark')
235 241 0 files updated, 0 files merged, 0 files removed, 3 files unresolved
236 242 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
237 243 [1]
238 244 $ ls
239 245 x
240 246 y
241 247 z
242 248 z.orig
243 249 $ cat x
244 250 x
245 251 foo
246 252 $ cat y
247 253 y
248 254 foo
249 255 # 'z' should have had the added 'foo' line
250 256 $ cat z
251 257 <<<<<<< working copy: 07fcbc9a74ed - test: modify x, rename y to z
252 258 y
253 259 ||||||| base
254 260 =======
255 261 x
256 262 >>>>>>> merge rev: f21419739508 - test: modify y, rename x to z
@@ -1,1055 +1,1082 b''
1 1
2 2 $ mkdir -p t
3 3 $ cd t
4 4 $ cat <<EOF > merge
5 5 > import sys, os
6 6 > f = open(sys.argv[1], "w")
7 7 > f.write("merge %s %s %s" % (sys.argv[1], sys.argv[2], sys.argv[3]))
8 8 > f.close()
9 9 > EOF
10 10
11 11 perform a test merge with possible renaming
12 12 args:
13 13 $1 = action in local branch
14 14 $2 = action in remote branch
15 15 $3 = action in working dir
16 16 $4 = expected result
17 17
18 18 $ tm()
19 19 > {
20 20 > hg init t
21 21 > cd t
22 22 > echo "[merge]" >> .hg/hgrc
23 23 > echo "followcopies = 1" >> .hg/hgrc
24 24 >
25 25 > # base
26 26 > echo base > a
27 27 > echo base > rev # used to force commits
28 28 > hg add a rev
29 29 > hg ci -m "base"
30 30 >
31 31 > # remote
32 32 > echo remote > rev
33 33 > if [ "$2" != "" ] ; then $2 ; fi
34 34 > hg ci -m "remote"
35 35 >
36 36 > # local
37 37 > hg co -q 0
38 38 > echo local > rev
39 39 > if [ "$1" != "" ] ; then $1 ; fi
40 40 > hg ci -m "local"
41 41 >
42 42 > # working dir
43 43 > echo local > rev
44 44 > if [ "$3" != "" ] ; then $3 ; fi
45 45 >
46 46 > # merge
47 47 > echo "--------------"
48 48 > echo "test L:$1 R:$2 W:$3 - $4"
49 49 > echo "--------------"
50 50 > hg merge -y --debug --traceback --tool="\"$PYTHON\" ../merge"
51 51 >
52 52 > echo "--------------"
53 53 > hg status -camC -X rev
54 54 >
55 55 > hg ci -m "merge"
56 56 >
57 57 > echo "--------------"
58 58 > echo
59 59 >
60 60 > cd ..
61 61 > rm -r t
62 62 > }
63 63 $ up() {
64 64 > cp rev $1
65 65 > hg add $1 2> /dev/null
66 66 > if [ "$2" != "" ] ; then
67 67 > cp rev $2
68 68 > hg add $2 2> /dev/null
69 69 > fi
70 70 > }
71 71 $ um() { up $1; hg mv $1 $2; }
72 72 $ nc() { hg cp $1 $2; } # just copy
73 73 $ nm() { hg mv $1 $2; } # just move
74 74 $ tm "up a " "nc a b" " " "1 get local a to b"
75 75 created new head
76 76 --------------
77 77 test L:up a R:nc a b W: - 1 get local a to b
78 78 --------------
79 79 unmatched files in other:
80 80 b
81 81 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
82 src: 'a' -> dst: 'b' *
82 on remote side:
83 src: 'a' -> dst: 'b' *
83 84 checking for directory renames
84 85 resolving manifests
85 86 branchmerge: True, force: False, partial: False
86 87 ancestor: 924404dff337, local: e300d1c794ec+, remote: 4ce40f5aca24
87 88 preserving a for resolve of b
88 89 preserving rev for resolve of rev
89 90 starting 4 threads for background file closing (?)
90 91 b: remote copied from a -> m (premerge)
91 92 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
92 93 merging a and b to b
93 94 my b@e300d1c794ec+ other b@4ce40f5aca24 ancestor a@924404dff337
94 95 premerge successful
95 96 rev: versions differ -> m (premerge)
96 97 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
97 98 merging rev
98 99 my rev@e300d1c794ec+ other rev@4ce40f5aca24 ancestor rev@924404dff337
99 100 rev: versions differ -> m (merge)
100 101 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
101 102 my rev@e300d1c794ec+ other rev@4ce40f5aca24 ancestor rev@924404dff337
102 103 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
103 104 merge tool returned: 0
104 105 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
105 106 (branch merge, don't forget to commit)
106 107 --------------
107 108 M b
108 109 a
109 110 C a
110 111 --------------
111 112
112 113 $ tm "nc a b" "up a " " " "2 get rem change to a and b"
113 114 created new head
114 115 --------------
115 116 test L:nc a b R:up a W: - 2 get rem change to a and b
116 117 --------------
117 118 unmatched files in local:
118 119 b
119 120 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
120 src: 'a' -> dst: 'b' *
121 on local side:
122 src: 'a' -> dst: 'b' *
121 123 checking for directory renames
122 124 resolving manifests
123 125 branchmerge: True, force: False, partial: False
124 126 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: f4db7e329e71
125 127 preserving b for resolve of b
126 128 preserving rev for resolve of rev
127 129 a: remote is newer -> g
128 130 getting a
129 131 b: local copied/moved from a -> m (premerge)
130 132 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
131 133 merging b and a to b
132 134 my b@86a2aa42fc76+ other a@f4db7e329e71 ancestor a@924404dff337
133 135 premerge successful
134 136 rev: versions differ -> m (premerge)
135 137 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
136 138 merging rev
137 139 my rev@86a2aa42fc76+ other rev@f4db7e329e71 ancestor rev@924404dff337
138 140 rev: versions differ -> m (merge)
139 141 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
140 142 my rev@86a2aa42fc76+ other rev@f4db7e329e71 ancestor rev@924404dff337
141 143 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
142 144 merge tool returned: 0
143 145 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
144 146 (branch merge, don't forget to commit)
145 147 --------------
146 148 M a
147 149 M b
148 150 a
149 151 --------------
150 152
151 153 $ tm "up a " "nm a b" " " "3 get local a change to b, remove a"
152 154 created new head
153 155 --------------
154 156 test L:up a R:nm a b W: - 3 get local a change to b, remove a
155 157 --------------
156 158 unmatched files in other:
157 159 b
158 160 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
159 src: 'a' -> dst: 'b' *
161 on remote side:
162 src: 'a' -> dst: 'b' *
160 163 checking for directory renames
161 164 resolving manifests
162 165 branchmerge: True, force: False, partial: False
163 166 ancestor: 924404dff337, local: e300d1c794ec+, remote: bdb19105162a
164 167 preserving a for resolve of b
165 168 preserving rev for resolve of rev
166 169 removing a
167 170 starting 4 threads for background file closing (?)
168 171 b: remote moved from a -> m (premerge)
169 172 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
170 173 merging a and b to b
171 174 my b@e300d1c794ec+ other b@bdb19105162a ancestor a@924404dff337
172 175 premerge successful
173 176 rev: versions differ -> m (premerge)
174 177 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
175 178 merging rev
176 179 my rev@e300d1c794ec+ other rev@bdb19105162a ancestor rev@924404dff337
177 180 rev: versions differ -> m (merge)
178 181 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
179 182 my rev@e300d1c794ec+ other rev@bdb19105162a ancestor rev@924404dff337
180 183 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
181 184 merge tool returned: 0
182 185 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
183 186 (branch merge, don't forget to commit)
184 187 --------------
185 188 M b
186 189 a
187 190 --------------
188 191
189 192 $ tm "nm a b" "up a " " " "4 get remote change to b"
190 193 created new head
191 194 --------------
192 195 test L:nm a b R:up a W: - 4 get remote change to b
193 196 --------------
194 197 unmatched files in local:
195 198 b
196 199 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
197 src: 'a' -> dst: 'b' *
200 on local side:
201 src: 'a' -> dst: 'b' *
198 202 checking for directory renames
199 203 resolving manifests
200 204 branchmerge: True, force: False, partial: False
201 205 ancestor: 924404dff337, local: 02963e448370+, remote: f4db7e329e71
202 206 preserving b for resolve of b
203 207 preserving rev for resolve of rev
204 208 starting 4 threads for background file closing (?)
205 209 b: local copied/moved from a -> m (premerge)
206 210 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
207 211 merging b and a to b
208 212 my b@02963e448370+ other a@f4db7e329e71 ancestor a@924404dff337
209 213 premerge successful
210 214 rev: versions differ -> m (premerge)
211 215 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
212 216 merging rev
213 217 my rev@02963e448370+ other rev@f4db7e329e71 ancestor rev@924404dff337
214 218 rev: versions differ -> m (merge)
215 219 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
216 220 my rev@02963e448370+ other rev@f4db7e329e71 ancestor rev@924404dff337
217 221 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
218 222 merge tool returned: 0
219 223 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
220 224 (branch merge, don't forget to commit)
221 225 --------------
222 226 M b
223 227 a
224 228 --------------
225 229
226 230 $ tm " " "nc a b" " " "5 get b"
227 231 created new head
228 232 --------------
229 233 test L: R:nc a b W: - 5 get b
230 234 --------------
231 235 unmatched files in other:
232 236 b
233 237 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
234 src: 'a' -> dst: 'b'
238 on remote side:
239 src: 'a' -> dst: 'b'
235 240 checking for directory renames
236 241 resolving manifests
237 242 branchmerge: True, force: False, partial: False
238 243 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: 4ce40f5aca24
239 244 preserving rev for resolve of rev
240 245 b: remote created -> g
241 246 getting b
242 247 rev: versions differ -> m (premerge)
243 248 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
244 249 merging rev
245 250 my rev@94b33a1b7f2d+ other rev@4ce40f5aca24 ancestor rev@924404dff337
246 251 rev: versions differ -> m (merge)
247 252 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
248 253 my rev@94b33a1b7f2d+ other rev@4ce40f5aca24 ancestor rev@924404dff337
249 254 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
250 255 merge tool returned: 0
251 256 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
252 257 (branch merge, don't forget to commit)
253 258 --------------
254 259 M b
255 260 C a
256 261 --------------
257 262
258 263 $ tm "nc a b" " " " " "6 nothing"
259 264 created new head
260 265 --------------
261 266 test L:nc a b R: W: - 6 nothing
262 267 --------------
263 268 unmatched files in local:
264 269 b
265 270 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
266 src: 'a' -> dst: 'b'
271 on local side:
272 src: 'a' -> dst: 'b'
267 273 checking for directory renames
268 274 resolving manifests
269 275 branchmerge: True, force: False, partial: False
270 276 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 97c705ade336
271 277 preserving rev for resolve of rev
272 278 starting 4 threads for background file closing (?)
273 279 rev: versions differ -> m (premerge)
274 280 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
275 281 merging rev
276 282 my rev@86a2aa42fc76+ other rev@97c705ade336 ancestor rev@924404dff337
277 283 rev: versions differ -> m (merge)
278 284 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
279 285 my rev@86a2aa42fc76+ other rev@97c705ade336 ancestor rev@924404dff337
280 286 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
281 287 merge tool returned: 0
282 288 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
283 289 (branch merge, don't forget to commit)
284 290 --------------
285 291 C a
286 292 C b
287 293 --------------
288 294
289 295 $ tm " " "nm a b" " " "7 get b"
290 296 created new head
291 297 --------------
292 298 test L: R:nm a b W: - 7 get b
293 299 --------------
294 300 unmatched files in other:
295 301 b
296 302 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
297 src: 'a' -> dst: 'b'
303 on remote side:
304 src: 'a' -> dst: 'b'
298 305 checking for directory renames
299 306 resolving manifests
300 307 branchmerge: True, force: False, partial: False
301 308 ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: bdb19105162a
302 309 preserving rev for resolve of rev
303 310 a: other deleted -> r
304 311 removing a
305 312 b: remote created -> g
306 313 getting b
307 314 rev: versions differ -> m (premerge)
308 315 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
309 316 merging rev
310 317 my rev@94b33a1b7f2d+ other rev@bdb19105162a ancestor rev@924404dff337
311 318 rev: versions differ -> m (merge)
312 319 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
313 320 my rev@94b33a1b7f2d+ other rev@bdb19105162a ancestor rev@924404dff337
314 321 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
315 322 merge tool returned: 0
316 323 1 files updated, 1 files merged, 1 files removed, 0 files unresolved
317 324 (branch merge, don't forget to commit)
318 325 --------------
319 326 M b
320 327 --------------
321 328
322 329 $ tm "nm a b" " " " " "8 nothing"
323 330 created new head
324 331 --------------
325 332 test L:nm a b R: W: - 8 nothing
326 333 --------------
327 334 unmatched files in local:
328 335 b
329 336 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
330 src: 'a' -> dst: 'b'
337 on local side:
338 src: 'a' -> dst: 'b'
331 339 checking for directory renames
332 340 resolving manifests
333 341 branchmerge: True, force: False, partial: False
334 342 ancestor: 924404dff337, local: 02963e448370+, remote: 97c705ade336
335 343 preserving rev for resolve of rev
336 344 starting 4 threads for background file closing (?)
337 345 rev: versions differ -> m (premerge)
338 346 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
339 347 merging rev
340 348 my rev@02963e448370+ other rev@97c705ade336 ancestor rev@924404dff337
341 349 rev: versions differ -> m (merge)
342 350 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
343 351 my rev@02963e448370+ other rev@97c705ade336 ancestor rev@924404dff337
344 352 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
345 353 merge tool returned: 0
346 354 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
347 355 (branch merge, don't forget to commit)
348 356 --------------
349 357 C b
350 358 --------------
351 359
352 360 $ tm "um a b" "um a b" " " "9 do merge with ancestor in a"
353 361 created new head
354 362 --------------
355 363 test L:um a b R:um a b W: - 9 do merge with ancestor in a
356 364 --------------
357 365 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
358 src: 'a' -> dst: 'b' *
366 on local side:
367 src: 'a' -> dst: 'b' *
368 on remote side:
369 src: 'a' -> dst: 'b' *
359 370 checking for directory renames
360 371 resolving manifests
361 372 branchmerge: True, force: False, partial: False
362 373 ancestor: 924404dff337, local: 62e7bf090eba+, remote: 49b6d8032493
363 374 preserving b for resolve of b
364 375 preserving rev for resolve of rev
365 376 starting 4 threads for background file closing (?)
366 377 b: both renamed from a -> m (premerge)
367 378 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
368 379 merging b
369 380 my b@62e7bf090eba+ other b@49b6d8032493 ancestor a@924404dff337
370 381 rev: versions differ -> m (premerge)
371 382 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
372 383 merging rev
373 384 my rev@62e7bf090eba+ other rev@49b6d8032493 ancestor rev@924404dff337
374 385 b: both renamed from a -> m (merge)
375 386 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
376 387 my b@62e7bf090eba+ other b@49b6d8032493 ancestor a@924404dff337
377 388 launching merge tool: * ../merge *$TESTTMP/t/t/b* * * (glob)
378 389 merge tool returned: 0
379 390 rev: versions differ -> m (merge)
380 391 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
381 392 my rev@62e7bf090eba+ other rev@49b6d8032493 ancestor rev@924404dff337
382 393 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
383 394 merge tool returned: 0
384 395 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
385 396 (branch merge, don't forget to commit)
386 397 --------------
387 398 M b
388 399 --------------
389 400
390 401
391 402 m "um a c" "um x c" " " "10 do merge with no ancestor"
392 403
393 404 $ tm "nm a b" "nm a c" " " "11 get c, keep b"
394 405 created new head
395 406 --------------
396 407 test L:nm a b R:nm a c W: - 11 get c, keep b
397 408 --------------
398 409 unmatched files in local:
399 410 b
400 411 unmatched files in other:
401 412 c
402 413 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
403 src: 'a' -> dst: 'b' !
404 src: 'a' -> dst: 'c' !
414 on local side:
415 src: 'a' -> dst: 'b' !
416 on remote side:
417 src: 'a' -> dst: 'c' !
405 418 checking for directory renames
406 419 resolving manifests
407 420 branchmerge: True, force: False, partial: False
408 421 ancestor: 924404dff337, local: 02963e448370+, remote: fe905ef2c33e
409 422 note: possible conflict - a was renamed multiple times to:
410 423 b
411 424 c
412 425 preserving rev for resolve of rev
413 426 c: remote created -> g
414 427 getting c
415 428 rev: versions differ -> m (premerge)
416 429 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
417 430 merging rev
418 431 my rev@02963e448370+ other rev@fe905ef2c33e ancestor rev@924404dff337
419 432 rev: versions differ -> m (merge)
420 433 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
421 434 my rev@02963e448370+ other rev@fe905ef2c33e ancestor rev@924404dff337
422 435 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
423 436 merge tool returned: 0
424 437 1 files updated, 1 files merged, 0 files removed, 0 files unresolved
425 438 (branch merge, don't forget to commit)
426 439 --------------
427 440 M c
428 441 C b
429 442 --------------
430 443
431 444 $ tm "nc a b" "up b " " " "12 merge b no ancestor"
432 445 created new head
433 446 --------------
434 447 test L:nc a b R:up b W: - 12 merge b no ancestor
435 448 --------------
436 449 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
437 src: 'a' -> dst: 'b'
450 on local side:
451 src: 'a' -> dst: 'b'
438 452 checking for directory renames
439 453 resolving manifests
440 454 branchmerge: True, force: False, partial: False
441 455 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: af30c7647fc7
442 456 preserving b for resolve of b
443 457 preserving rev for resolve of rev
444 458 starting 4 threads for background file closing (?)
445 459 b: both created -> m (premerge)
446 460 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
447 461 merging b
448 462 my b@86a2aa42fc76+ other b@af30c7647fc7 ancestor b@000000000000
449 463 rev: versions differ -> m (premerge)
450 464 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
451 465 merging rev
452 466 my rev@86a2aa42fc76+ other rev@af30c7647fc7 ancestor rev@924404dff337
453 467 b: both created -> m (merge)
454 468 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
455 469 my b@86a2aa42fc76+ other b@af30c7647fc7 ancestor b@000000000000
456 470 launching merge tool: * ../merge *$TESTTMP/t/t/b* * * (glob)
457 471 merge tool returned: 0
458 472 rev: versions differ -> m (merge)
459 473 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
460 474 my rev@86a2aa42fc76+ other rev@af30c7647fc7 ancestor rev@924404dff337
461 475 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
462 476 merge tool returned: 0
463 477 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
464 478 (branch merge, don't forget to commit)
465 479 --------------
466 480 M b
467 481 C a
468 482 --------------
469 483
470 484 $ tm "up b " "nm a b" " " "13 merge b no ancestor"
471 485 created new head
472 486 --------------
473 487 test L:up b R:nm a b W: - 13 merge b no ancestor
474 488 --------------
475 489 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
476 src: 'a' -> dst: 'b'
490 on remote side:
491 src: 'a' -> dst: 'b'
477 492 checking for directory renames
478 493 resolving manifests
479 494 branchmerge: True, force: False, partial: False
480 495 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
481 496 preserving b for resolve of b
482 497 preserving rev for resolve of rev
483 498 a: other deleted -> r
484 499 removing a
485 500 starting 4 threads for background file closing (?)
486 501 b: both created -> m (premerge)
487 502 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
488 503 merging b
489 504 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
490 505 rev: versions differ -> m (premerge)
491 506 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
492 507 merging rev
493 508 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
494 509 b: both created -> m (merge)
495 510 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
496 511 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
497 512 launching merge tool: * ../merge *$TESTTMP/t/t/b* * * (glob)
498 513 merge tool returned: 0
499 514 rev: versions differ -> m (merge)
500 515 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
501 516 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
502 517 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
503 518 merge tool returned: 0
504 519 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
505 520 (branch merge, don't forget to commit)
506 521 --------------
507 522 M b
508 523 --------------
509 524
510 525 $ tm "nc a b" "up a b" " " "14 merge b no ancestor"
511 526 created new head
512 527 --------------
513 528 test L:nc a b R:up a b W: - 14 merge b no ancestor
514 529 --------------
515 530 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
516 src: 'a' -> dst: 'b'
531 on local side:
532 src: 'a' -> dst: 'b'
517 533 checking for directory renames
518 534 resolving manifests
519 535 branchmerge: True, force: False, partial: False
520 536 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
521 537 preserving b for resolve of b
522 538 preserving rev for resolve of rev
523 539 a: remote is newer -> g
524 540 getting a
525 541 b: both created -> m (premerge)
526 542 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
527 543 merging b
528 544 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
529 545 rev: versions differ -> m (premerge)
530 546 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
531 547 merging rev
532 548 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
533 549 b: both created -> m (merge)
534 550 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
535 551 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
536 552 launching merge tool: * ../merge *$TESTTMP/t/t/b* * * (glob)
537 553 merge tool returned: 0
538 554 rev: versions differ -> m (merge)
539 555 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
540 556 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
541 557 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
542 558 merge tool returned: 0
543 559 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
544 560 (branch merge, don't forget to commit)
545 561 --------------
546 562 M a
547 563 M b
548 564 --------------
549 565
550 566 $ tm "up b " "nm a b" " " "15 merge b no ancestor, remove a"
551 567 created new head
552 568 --------------
553 569 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a
554 570 --------------
555 571 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
556 src: 'a' -> dst: 'b'
572 on remote side:
573 src: 'a' -> dst: 'b'
557 574 checking for directory renames
558 575 resolving manifests
559 576 branchmerge: True, force: False, partial: False
560 577 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
561 578 preserving b for resolve of b
562 579 preserving rev for resolve of rev
563 580 a: other deleted -> r
564 581 removing a
565 582 starting 4 threads for background file closing (?)
566 583 b: both created -> m (premerge)
567 584 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
568 585 merging b
569 586 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
570 587 rev: versions differ -> m (premerge)
571 588 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
572 589 merging rev
573 590 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
574 591 b: both created -> m (merge)
575 592 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
576 593 my b@59318016310c+ other b@bdb19105162a ancestor b@000000000000
577 594 launching merge tool: * ../merge *$TESTTMP/t/t/b* * * (glob)
578 595 merge tool returned: 0
579 596 rev: versions differ -> m (merge)
580 597 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
581 598 my rev@59318016310c+ other rev@bdb19105162a ancestor rev@924404dff337
582 599 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
583 600 merge tool returned: 0
584 601 0 files updated, 2 files merged, 1 files removed, 0 files unresolved
585 602 (branch merge, don't forget to commit)
586 603 --------------
587 604 M b
588 605 --------------
589 606
590 607 $ tm "nc a b" "up a b" " " "16 get a, merge b no ancestor"
591 608 created new head
592 609 --------------
593 610 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor
594 611 --------------
595 612 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
596 src: 'a' -> dst: 'b'
613 on local side:
614 src: 'a' -> dst: 'b'
597 615 checking for directory renames
598 616 resolving manifests
599 617 branchmerge: True, force: False, partial: False
600 618 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
601 619 preserving b for resolve of b
602 620 preserving rev for resolve of rev
603 621 a: remote is newer -> g
604 622 getting a
605 623 b: both created -> m (premerge)
606 624 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
607 625 merging b
608 626 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
609 627 rev: versions differ -> m (premerge)
610 628 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
611 629 merging rev
612 630 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
613 631 b: both created -> m (merge)
614 632 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
615 633 my b@86a2aa42fc76+ other b@8dbce441892a ancestor b@000000000000
616 634 launching merge tool: * ../merge *$TESTTMP/t/t/b* * * (glob)
617 635 merge tool returned: 0
618 636 rev: versions differ -> m (merge)
619 637 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
620 638 my rev@86a2aa42fc76+ other rev@8dbce441892a ancestor rev@924404dff337
621 639 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
622 640 merge tool returned: 0
623 641 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
624 642 (branch merge, don't forget to commit)
625 643 --------------
626 644 M a
627 645 M b
628 646 --------------
629 647
630 648 $ tm "up a b" "nc a b" " " "17 keep a, merge b no ancestor"
631 649 created new head
632 650 --------------
633 651 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor
634 652 --------------
635 653 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
636 src: 'a' -> dst: 'b'
654 on remote side:
655 src: 'a' -> dst: 'b'
637 656 checking for directory renames
638 657 resolving manifests
639 658 branchmerge: True, force: False, partial: False
640 659 ancestor: 924404dff337, local: 0b76e65c8289+, remote: 4ce40f5aca24
641 660 preserving b for resolve of b
642 661 preserving rev for resolve of rev
643 662 starting 4 threads for background file closing (?)
644 663 b: both created -> m (premerge)
645 664 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
646 665 merging b
647 666 my b@0b76e65c8289+ other b@4ce40f5aca24 ancestor b@000000000000
648 667 rev: versions differ -> m (premerge)
649 668 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
650 669 merging rev
651 670 my rev@0b76e65c8289+ other rev@4ce40f5aca24 ancestor rev@924404dff337
652 671 b: both created -> m (merge)
653 672 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
654 673 my b@0b76e65c8289+ other b@4ce40f5aca24 ancestor b@000000000000
655 674 launching merge tool: * ../merge *$TESTTMP/t/t/b* * * (glob)
656 675 merge tool returned: 0
657 676 rev: versions differ -> m (merge)
658 677 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
659 678 my rev@0b76e65c8289+ other rev@4ce40f5aca24 ancestor rev@924404dff337
660 679 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
661 680 merge tool returned: 0
662 681 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
663 682 (branch merge, don't forget to commit)
664 683 --------------
665 684 M b
666 685 C a
667 686 --------------
668 687
669 688 $ tm "nm a b" "up a b" " " "18 merge b no ancestor"
670 689 created new head
671 690 --------------
672 691 test L:nm a b R:up a b W: - 18 merge b no ancestor
673 692 --------------
674 693 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
675 src: 'a' -> dst: 'b'
694 on local side:
695 src: 'a' -> dst: 'b'
676 696 checking for directory renames
677 697 resolving manifests
678 698 branchmerge: True, force: False, partial: False
679 699 ancestor: 924404dff337, local: 02963e448370+, remote: 8dbce441892a
680 700 preserving b for resolve of b
681 701 preserving rev for resolve of rev
682 702 starting 4 threads for background file closing (?)
683 703 a: prompt deleted/changed -> m (premerge)
684 704 picked tool ':prompt' for a (binary False symlink False changedelete True)
685 705 file 'a' was deleted in local [working copy] but was modified in other [merge rev].
686 706 You can use (c)hanged version, leave (d)eleted, or leave (u)nresolved.
687 707 What do you want to do? u
688 708 b: both created -> m (premerge)
689 709 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
690 710 merging b
691 711 my b@02963e448370+ other b@8dbce441892a ancestor b@000000000000
692 712 rev: versions differ -> m (premerge)
693 713 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
694 714 merging rev
695 715 my rev@02963e448370+ other rev@8dbce441892a ancestor rev@924404dff337
696 716 b: both created -> m (merge)
697 717 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
698 718 my b@02963e448370+ other b@8dbce441892a ancestor b@000000000000
699 719 launching merge tool: * ../merge *$TESTTMP/t/t/b* * * (glob)
700 720 merge tool returned: 0
701 721 rev: versions differ -> m (merge)
702 722 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
703 723 my rev@02963e448370+ other rev@8dbce441892a ancestor rev@924404dff337
704 724 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
705 725 merge tool returned: 0
706 726 0 files updated, 2 files merged, 0 files removed, 1 files unresolved
707 727 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
708 728 --------------
709 729 M a
710 730 M b
711 731 abort: unresolved merge conflicts (see 'hg help resolve')
712 732 --------------
713 733
714 734 $ tm "up a b" "nm a b" " " "19 merge b no ancestor, prompt remove a"
715 735 created new head
716 736 --------------
717 737 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a
718 738 --------------
719 739 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
720 src: 'a' -> dst: 'b'
740 on remote side:
741 src: 'a' -> dst: 'b'
721 742 checking for directory renames
722 743 resolving manifests
723 744 branchmerge: True, force: False, partial: False
724 745 ancestor: 924404dff337, local: 0b76e65c8289+, remote: bdb19105162a
725 746 preserving a for resolve of a
726 747 preserving b for resolve of b
727 748 preserving rev for resolve of rev
728 749 starting 4 threads for background file closing (?)
729 750 a: prompt changed/deleted -> m (premerge)
730 751 picked tool ':prompt' for a (binary False symlink False changedelete True)
731 752 file 'a' was deleted in other [merge rev] but was modified in local [working copy].
732 753 You can use (c)hanged version, (d)elete, or leave (u)nresolved.
733 754 What do you want to do? u
734 755 b: both created -> m (premerge)
735 756 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
736 757 merging b
737 758 my b@0b76e65c8289+ other b@bdb19105162a ancestor b@000000000000
738 759 rev: versions differ -> m (premerge)
739 760 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
740 761 merging rev
741 762 my rev@0b76e65c8289+ other rev@bdb19105162a ancestor rev@924404dff337
742 763 b: both created -> m (merge)
743 764 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
744 765 my b@0b76e65c8289+ other b@bdb19105162a ancestor b@000000000000
745 766 launching merge tool: * ../merge *$TESTTMP/t/t/b* * * (glob)
746 767 merge tool returned: 0
747 768 rev: versions differ -> m (merge)
748 769 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
749 770 my rev@0b76e65c8289+ other rev@bdb19105162a ancestor rev@924404dff337
750 771 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
751 772 merge tool returned: 0
752 773 0 files updated, 2 files merged, 0 files removed, 1 files unresolved
753 774 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
754 775 --------------
755 776 M b
756 777 C a
757 778 abort: unresolved merge conflicts (see 'hg help resolve')
758 779 --------------
759 780
760 781 $ tm "up a " "um a b" " " "20 merge a and b to b, remove a"
761 782 created new head
762 783 --------------
763 784 test L:up a R:um a b W: - 20 merge a and b to b, remove a
764 785 --------------
765 786 unmatched files in other:
766 787 b
767 788 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
768 src: 'a' -> dst: 'b' *
789 on remote side:
790 src: 'a' -> dst: 'b' *
769 791 checking for directory renames
770 792 resolving manifests
771 793 branchmerge: True, force: False, partial: False
772 794 ancestor: 924404dff337, local: e300d1c794ec+, remote: 49b6d8032493
773 795 preserving a for resolve of b
774 796 preserving rev for resolve of rev
775 797 removing a
776 798 starting 4 threads for background file closing (?)
777 799 b: remote moved from a -> m (premerge)
778 800 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
779 801 merging a and b to b
780 802 my b@e300d1c794ec+ other b@49b6d8032493 ancestor a@924404dff337
781 803 rev: versions differ -> m (premerge)
782 804 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
783 805 merging rev
784 806 my rev@e300d1c794ec+ other rev@49b6d8032493 ancestor rev@924404dff337
785 807 b: remote moved from a -> m (merge)
786 808 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
787 809 my b@e300d1c794ec+ other b@49b6d8032493 ancestor a@924404dff337
788 810 launching merge tool: * ../merge *$TESTTMP/t/t/b* * * (glob)
789 811 merge tool returned: 0
790 812 rev: versions differ -> m (merge)
791 813 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
792 814 my rev@e300d1c794ec+ other rev@49b6d8032493 ancestor rev@924404dff337
793 815 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
794 816 merge tool returned: 0
795 817 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
796 818 (branch merge, don't forget to commit)
797 819 --------------
798 820 M b
799 821 a
800 822 --------------
801 823
802 824 $ tm "um a b" "up a " " " "21 merge a and b to b"
803 825 created new head
804 826 --------------
805 827 test L:um a b R:up a W: - 21 merge a and b to b
806 828 --------------
807 829 unmatched files in local:
808 830 b
809 831 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
810 src: 'a' -> dst: 'b' *
832 on local side:
833 src: 'a' -> dst: 'b' *
811 834 checking for directory renames
812 835 resolving manifests
813 836 branchmerge: True, force: False, partial: False
814 837 ancestor: 924404dff337, local: 62e7bf090eba+, remote: f4db7e329e71
815 838 preserving b for resolve of b
816 839 preserving rev for resolve of rev
817 840 starting 4 threads for background file closing (?)
818 841 b: local copied/moved from a -> m (premerge)
819 842 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
820 843 merging b and a to b
821 844 my b@62e7bf090eba+ other a@f4db7e329e71 ancestor a@924404dff337
822 845 rev: versions differ -> m (premerge)
823 846 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
824 847 merging rev
825 848 my rev@62e7bf090eba+ other rev@f4db7e329e71 ancestor rev@924404dff337
826 849 b: local copied/moved from a -> m (merge)
827 850 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
828 851 my b@62e7bf090eba+ other a@f4db7e329e71 ancestor a@924404dff337
829 852 launching merge tool: * ../merge *$TESTTMP/t/t/b* * * (glob)
830 853 merge tool returned: 0
831 854 rev: versions differ -> m (merge)
832 855 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
833 856 my rev@62e7bf090eba+ other rev@f4db7e329e71 ancestor rev@924404dff337
834 857 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
835 858 merge tool returned: 0
836 859 0 files updated, 2 files merged, 0 files removed, 0 files unresolved
837 860 (branch merge, don't forget to commit)
838 861 --------------
839 862 M b
840 863 a
841 864 --------------
842 865
843 866
844 867 m "nm a b" "um x a" " " "22 get a, keep b"
845 868
846 869 $ tm "nm a b" "up a c" " " "23 get c, keep b"
847 870 created new head
848 871 --------------
849 872 test L:nm a b R:up a c W: - 23 get c, keep b
850 873 --------------
851 874 unmatched files in local:
852 875 b
853 876 unmatched files in other:
854 877 c
855 878 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
856 src: 'a' -> dst: 'b' *
879 on local side:
880 src: 'a' -> dst: 'b' *
857 881 checking for directory renames
858 882 resolving manifests
859 883 branchmerge: True, force: False, partial: False
860 884 ancestor: 924404dff337, local: 02963e448370+, remote: 2b958612230f
861 885 preserving b for resolve of b
862 886 preserving rev for resolve of rev
863 887 c: remote created -> g
864 888 getting c
865 889 b: local copied/moved from a -> m (premerge)
866 890 picked tool '* ../merge' for b (binary False symlink False changedelete False) (glob)
867 891 merging b and a to b
868 892 my b@02963e448370+ other a@2b958612230f ancestor a@924404dff337
869 893 premerge successful
870 894 rev: versions differ -> m (premerge)
871 895 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
872 896 merging rev
873 897 my rev@02963e448370+ other rev@2b958612230f ancestor rev@924404dff337
874 898 rev: versions differ -> m (merge)
875 899 picked tool '* ../merge' for rev (binary False symlink False changedelete False) (glob)
876 900 my rev@02963e448370+ other rev@2b958612230f ancestor rev@924404dff337
877 901 launching merge tool: * ../merge *$TESTTMP/t/t/rev* * * (glob)
878 902 merge tool returned: 0
879 903 1 files updated, 2 files merged, 0 files removed, 0 files unresolved
880 904 (branch merge, don't forget to commit)
881 905 --------------
882 906 M b
883 907 a
884 908 M c
885 909 --------------
886 910
887 911
888 912 $ cd ..
889 913
890 914
891 915 Systematic and terse testing of merge merges and ancestor calculation:
892 916
893 917 Expected result:
894 918
895 919 \ a m1 m2 dst
896 920 0 - f f f "versions differ"
897 921 1 f g g g "versions differ"
898 922 2 f f f f "versions differ"
899 923 3 f f g f+g "remote copied to " + f
900 924 4 f f g g "remote moved to " + f
901 925 5 f g f f+g "local copied to " + f2
902 926 6 f g f g "local moved to " + f2
903 927 7 - (f) f f "remote differs from untracked local"
904 928 8 f (f) f f "remote differs from untracked local"
905 929
906 930 $ hg init ancestortest
907 931 $ cd ancestortest
908 932 $ for x in 1 2 3 4 5 6 8; do mkdir $x; echo a > $x/f; done
909 933 $ hg ci -Aqm "a"
910 934 $ mkdir 0
911 935 $ touch 0/f
912 936 $ hg mv 1/f 1/g
913 937 $ hg cp 5/f 5/g
914 938 $ hg mv 6/f 6/g
915 939 $ hg rm 8/f
916 940 $ for x in */*; do echo m1 > $x; done
917 941 $ hg ci -Aqm "m1"
918 942 $ hg up -qr0
919 943 $ mkdir 0 7
920 944 $ touch 0/f 7/f
921 945 $ hg mv 1/f 1/g
922 946 $ hg cp 3/f 3/g
923 947 $ hg mv 4/f 4/g
924 948 $ for x in */*; do echo m2 > $x; done
925 949 $ hg ci -Aqm "m2"
926 950 $ hg up -qr1
927 951 $ mkdir 7 8
928 952 $ echo m > 7/f
929 953 $ echo m > 8/f
930 954 $ hg merge -f --tool internal:dump -v --debug -r2 | sed '/^resolving manifests/,$d' 2> /dev/null
931 955 unmatched files in local:
932 956 5/g
933 957 6/g
934 958 unmatched files in other:
935 959 3/g
936 960 4/g
937 961 7/f
938 962 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
939 src: '1/f' -> dst: '1/g' *
940 src: '3/f' -> dst: '3/g' *
941 src: '4/f' -> dst: '4/g' *
942 src: '5/f' -> dst: '5/g' *
943 src: '6/f' -> dst: '6/g' *
963 on local side:
964 src: '1/f' -> dst: '1/g' *
965 src: '5/f' -> dst: '5/g' *
966 src: '6/f' -> dst: '6/g' *
967 on remote side:
968 src: '1/f' -> dst: '1/g' *
969 src: '3/f' -> dst: '3/g' *
970 src: '4/f' -> dst: '4/g' *
944 971 checking for directory renames
945 972 $ hg mani
946 973 0/f
947 974 1/g
948 975 2/f
949 976 3/f
950 977 4/f
951 978 5/f
952 979 5/g
953 980 6/g
954 981 $ for f in */*; do echo $f:; cat $f; done
955 982 0/f:
956 983 m1
957 984 0/f.base:
958 985 0/f.local:
959 986 m1
960 987 0/f.orig:
961 988 m1
962 989 0/f.other:
963 990 m2
964 991 1/g:
965 992 m1
966 993 1/g.base:
967 994 a
968 995 1/g.local:
969 996 m1
970 997 1/g.orig:
971 998 m1
972 999 1/g.other:
973 1000 m2
974 1001 2/f:
975 1002 m1
976 1003 2/f.base:
977 1004 a
978 1005 2/f.local:
979 1006 m1
980 1007 2/f.orig:
981 1008 m1
982 1009 2/f.other:
983 1010 m2
984 1011 3/f:
985 1012 m1
986 1013 3/f.base:
987 1014 a
988 1015 3/f.local:
989 1016 m1
990 1017 3/f.orig:
991 1018 m1
992 1019 3/f.other:
993 1020 m2
994 1021 3/g:
995 1022 m1
996 1023 3/g.base:
997 1024 a
998 1025 3/g.local:
999 1026 m1
1000 1027 3/g.orig:
1001 1028 m1
1002 1029 3/g.other:
1003 1030 m2
1004 1031 4/g:
1005 1032 m1
1006 1033 4/g.base:
1007 1034 a
1008 1035 4/g.local:
1009 1036 m1
1010 1037 4/g.orig:
1011 1038 m1
1012 1039 4/g.other:
1013 1040 m2
1014 1041 5/f:
1015 1042 m1
1016 1043 5/f.base:
1017 1044 a
1018 1045 5/f.local:
1019 1046 m1
1020 1047 5/f.orig:
1021 1048 m1
1022 1049 5/f.other:
1023 1050 m2
1024 1051 5/g:
1025 1052 m1
1026 1053 5/g.base:
1027 1054 a
1028 1055 5/g.local:
1029 1056 m1
1030 1057 5/g.orig:
1031 1058 m1
1032 1059 5/g.other:
1033 1060 m2
1034 1061 6/g:
1035 1062 m1
1036 1063 6/g.base:
1037 1064 a
1038 1065 6/g.local:
1039 1066 m1
1040 1067 6/g.orig:
1041 1068 m1
1042 1069 6/g.other:
1043 1070 m2
1044 1071 7/f:
1045 1072 m
1046 1073 7/f.base:
1047 1074 7/f.local:
1048 1075 m
1049 1076 7/f.orig:
1050 1077 m
1051 1078 7/f.other:
1052 1079 m2
1053 1080 8/f:
1054 1081 m2
1055 1082 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now