##// END OF EJS Templates
merge: fast-forward merge with descendant...
Mads Kiilerich -
r13158:9e7e2405 default
parent child Browse files
Show More
@@ -1,544 +1,544 b''
1 1 # merge.py - directory-level update/merge handling for Mercurial
2 2 #
3 3 # Copyright 2006, 2007 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 node import nullid, nullrev, hex, bin
9 9 from i18n import _
10 10 import util, filemerge, copies, subrepo
11 11 import errno, os, shutil
12 12
13 13 class mergestate(object):
14 14 '''track 3-way merge state of individual files'''
15 15 def __init__(self, repo):
16 16 self._repo = repo
17 17 self._dirty = False
18 18 self._read()
19 19 def reset(self, node=None):
20 20 self._state = {}
21 21 if node:
22 22 self._local = node
23 23 shutil.rmtree(self._repo.join("merge"), True)
24 24 self._dirty = False
25 25 def _read(self):
26 26 self._state = {}
27 27 try:
28 28 f = self._repo.opener("merge/state")
29 29 for i, l in enumerate(f):
30 30 if i == 0:
31 31 self._local = bin(l[:-1])
32 32 else:
33 33 bits = l[:-1].split("\0")
34 34 self._state[bits[0]] = bits[1:]
35 35 except IOError, err:
36 36 if err.errno != errno.ENOENT:
37 37 raise
38 38 self._dirty = False
39 39 def commit(self):
40 40 if self._dirty:
41 41 f = self._repo.opener("merge/state", "w")
42 42 f.write(hex(self._local) + "\n")
43 43 for d, v in self._state.iteritems():
44 44 f.write("\0".join([d] + v) + "\n")
45 45 self._dirty = False
46 46 def add(self, fcl, fco, fca, fd, flags):
47 47 hash = util.sha1(fcl.path()).hexdigest()
48 48 self._repo.opener("merge/" + hash, "w").write(fcl.data())
49 49 self._state[fd] = ['u', hash, fcl.path(), fca.path(),
50 50 hex(fca.filenode()), fco.path(), flags]
51 51 self._dirty = True
52 52 def __contains__(self, dfile):
53 53 return dfile in self._state
54 54 def __getitem__(self, dfile):
55 55 return self._state[dfile][0]
56 56 def __iter__(self):
57 57 l = self._state.keys()
58 58 l.sort()
59 59 for f in l:
60 60 yield f
61 61 def mark(self, dfile, state):
62 62 self._state[dfile][0] = state
63 63 self._dirty = True
64 64 def resolve(self, dfile, wctx, octx):
65 65 if self[dfile] == 'r':
66 66 return 0
67 67 state, hash, lfile, afile, anode, ofile, flags = self._state[dfile]
68 68 f = self._repo.opener("merge/" + hash)
69 69 self._repo.wwrite(dfile, f.read(), flags)
70 70 fcd = wctx[dfile]
71 71 fco = octx[ofile]
72 72 fca = self._repo.filectx(afile, fileid=anode)
73 73 r = filemerge.filemerge(self._repo, self._local, lfile, fcd, fco, fca)
74 74 if not r:
75 75 self.mark(dfile, 'r')
76 76 return r
77 77
78 78 def _checkunknown(wctx, mctx):
79 79 "check for collisions between unknown files and files in mctx"
80 80 for f in wctx.unknown():
81 81 if f in mctx and mctx[f].cmp(wctx[f]):
82 82 raise util.Abort(_("untracked file in working directory differs"
83 83 " from file in requested revision: '%s'") % f)
84 84
85 85 def _checkcollision(mctx):
86 86 "check for case folding collisions in the destination context"
87 87 folded = {}
88 88 for fn in mctx:
89 89 fold = fn.lower()
90 90 if fold in folded:
91 91 raise util.Abort(_("case-folding collision between %s and %s")
92 92 % (fn, folded[fold]))
93 93 folded[fold] = fn
94 94
95 95 def _forgetremoved(wctx, mctx, branchmerge):
96 96 """
97 97 Forget removed files
98 98
99 99 If we're jumping between revisions (as opposed to merging), and if
100 100 neither the working directory nor the target rev has the file,
101 101 then we need to remove it from the dirstate, to prevent the
102 102 dirstate from listing the file when it is no longer in the
103 103 manifest.
104 104
105 105 If we're merging, and the other revision has removed a file
106 106 that is not present in the working directory, we need to mark it
107 107 as removed.
108 108 """
109 109
110 110 action = []
111 111 state = branchmerge and 'r' or 'f'
112 112 for f in wctx.deleted():
113 113 if f not in mctx:
114 114 action.append((f, state))
115 115
116 116 if not branchmerge:
117 117 for f in wctx.removed():
118 118 if f not in mctx:
119 119 action.append((f, "f"))
120 120
121 121 return action
122 122
123 123 def manifestmerge(repo, p1, p2, pa, overwrite, partial):
124 124 """
125 125 Merge p1 and p2 with ancestor pa and generate merge action list
126 126
127 127 overwrite = whether we clobber working files
128 128 partial = function to filter file lists
129 129 """
130 130
131 131 def fmerge(f, f2, fa):
132 132 """merge flags"""
133 133 a, m, n = ma.flags(fa), m1.flags(f), m2.flags(f2)
134 134 if m == n: # flags agree
135 135 return m # unchanged
136 136 if m and n and not a: # flags set, don't agree, differ from parent
137 137 r = repo.ui.promptchoice(
138 138 _(" conflicting flags for %s\n"
139 139 "(n)one, e(x)ec or sym(l)ink?") % f,
140 140 (_("&None"), _("E&xec"), _("Sym&link")), 0)
141 141 if r == 1:
142 142 return "x" # Exec
143 143 if r == 2:
144 144 return "l" # Symlink
145 145 return ""
146 146 if m and m != a: # changed from a to m
147 147 return m
148 148 if n and n != a: # changed from a to n
149 149 return n
150 150 return '' # flag was cleared
151 151
152 152 def act(msg, m, f, *args):
153 153 repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
154 154 action.append((f, m) + args)
155 155
156 156 action, copy = [], {}
157 157
158 158 if overwrite:
159 159 pa = p1
160 160 elif pa == p2: # backwards
161 161 pa = p1.p1()
162 162 elif pa and repo.ui.configbool("merge", "followcopies", True):
163 163 dirs = repo.ui.configbool("merge", "followdirs", True)
164 164 copy, diverge = copies.copies(repo, p1, p2, pa, dirs)
165 165 for of, fl in diverge.iteritems():
166 166 act("divergent renames", "dr", of, fl)
167 167
168 168 repo.ui.note(_("resolving manifests\n"))
169 169 repo.ui.debug(" overwrite %s partial %s\n" % (overwrite, bool(partial)))
170 170 repo.ui.debug(" ancestor %s local %s remote %s\n" % (pa, p1, p2))
171 171
172 172 m1, m2, ma = p1.manifest(), p2.manifest(), pa.manifest()
173 173 copied = set(copy.values())
174 174
175 175 if '.hgsubstate' in m1:
176 176 # check whether sub state is modified
177 177 for s in p1.substate:
178 178 if p1.sub(s).dirty():
179 179 m1['.hgsubstate'] += "+"
180 180 break
181 181
182 182 # Compare manifests
183 183 for f, n in m1.iteritems():
184 184 if partial and not partial(f):
185 185 continue
186 186 if f in m2:
187 187 rflags = fmerge(f, f, f)
188 188 a = ma.get(f, nullid)
189 189 if n == m2[f] or m2[f] == a: # same or local newer
190 190 # is file locally modified or flags need changing?
191 191 # dirstate flags may need to be made current
192 192 if m1.flags(f) != rflags or n[20:]:
193 193 act("update permissions", "e", f, rflags)
194 194 elif n == a: # remote newer
195 195 act("remote is newer", "g", f, rflags)
196 196 else: # both changed
197 197 act("versions differ", "m", f, f, f, rflags, False)
198 198 elif f in copied: # files we'll deal with on m2 side
199 199 pass
200 200 elif f in copy:
201 201 f2 = copy[f]
202 202 if f2 not in m2: # directory rename
203 203 act("remote renamed directory to " + f2, "d",
204 204 f, None, f2, m1.flags(f))
205 205 else: # case 2 A,B/B/B or case 4,21 A/B/B
206 206 act("local copied/moved to " + f2, "m",
207 207 f, f2, f, fmerge(f, f2, f2), False)
208 208 elif f in ma: # clean, a different, no remote
209 209 if n != ma[f]:
210 210 if repo.ui.promptchoice(
211 211 _(" local changed %s which remote deleted\n"
212 212 "use (c)hanged version or (d)elete?") % f,
213 213 (_("&Changed"), _("&Delete")), 0):
214 214 act("prompt delete", "r", f)
215 215 else:
216 216 act("prompt keep", "a", f)
217 217 elif n[20:] == "a": # added, no remote
218 218 act("remote deleted", "f", f)
219 219 elif n[20:] != "u":
220 220 act("other deleted", "r", f)
221 221
222 222 for f, n in m2.iteritems():
223 223 if partial and not partial(f):
224 224 continue
225 225 if f in m1 or f in copied: # files already visited
226 226 continue
227 227 if f in copy:
228 228 f2 = copy[f]
229 229 if f2 not in m1: # directory rename
230 230 act("local renamed directory to " + f2, "d",
231 231 None, f, f2, m2.flags(f))
232 232 elif f2 in m2: # rename case 1, A/A,B/A
233 233 act("remote copied to " + f, "m",
234 234 f2, f, f, fmerge(f2, f, f2), False)
235 235 else: # case 3,20 A/B/A
236 236 act("remote moved to " + f, "m",
237 237 f2, f, f, fmerge(f2, f, f2), True)
238 238 elif f not in ma:
239 239 act("remote created", "g", f, m2.flags(f))
240 240 elif n != ma[f]:
241 241 if repo.ui.promptchoice(
242 242 _("remote changed %s which local deleted\n"
243 243 "use (c)hanged version or leave (d)eleted?") % f,
244 244 (_("&Changed"), _("&Deleted")), 0) == 0:
245 245 act("prompt recreating", "g", f, m2.flags(f))
246 246
247 247 return action
248 248
249 249 def actionkey(a):
250 250 return a[1] == 'r' and -1 or 0, a
251 251
252 252 def applyupdates(repo, action, wctx, mctx, actx):
253 253 """apply the merge action list to the working directory
254 254
255 255 wctx is the working copy context
256 256 mctx is the context to be merged into the working copy
257 257 actx is the context of the common ancestor
258 258 """
259 259
260 260 updated, merged, removed, unresolved = 0, 0, 0, 0
261 261 ms = mergestate(repo)
262 262 ms.reset(wctx.parents()[0].node())
263 263 moves = []
264 264 action.sort(key=actionkey)
265 265 substate = wctx.substate # prime
266 266
267 267 # prescan for merges
268 268 u = repo.ui
269 269 for a in action:
270 270 f, m = a[:2]
271 271 if m == 'm': # merge
272 272 f2, fd, flags, move = a[2:]
273 273 if f == '.hgsubstate': # merged internally
274 274 continue
275 275 repo.ui.debug("preserving %s for resolve of %s\n" % (f, fd))
276 276 fcl = wctx[f]
277 277 fco = mctx[f2]
278 278 if mctx == actx: # backwards, use working dir parent as ancestor
279 279 if fcl.parents():
280 280 fca = fcl.parents()[0]
281 281 else:
282 282 fca = repo.filectx(f, fileid=nullrev)
283 283 else:
284 284 fca = fcl.ancestor(fco, actx)
285 285 if not fca:
286 286 fca = repo.filectx(f, fileid=nullrev)
287 287 ms.add(fcl, fco, fca, fd, flags)
288 288 if f != fd and move:
289 289 moves.append(f)
290 290
291 291 # remove renamed files after safely stored
292 292 for f in moves:
293 293 if os.path.lexists(repo.wjoin(f)):
294 294 repo.ui.debug("removing %s\n" % f)
295 295 os.unlink(repo.wjoin(f))
296 296
297 297 audit_path = util.path_auditor(repo.root)
298 298
299 299 numupdates = len(action)
300 300 for i, a in enumerate(action):
301 301 f, m = a[:2]
302 302 u.progress(_('updating'), i + 1, item=f, total=numupdates,
303 303 unit=_('files'))
304 304 if f and f[0] == "/":
305 305 continue
306 306 if m == "r": # remove
307 307 repo.ui.note(_("removing %s\n") % f)
308 308 audit_path(f)
309 309 if f == '.hgsubstate': # subrepo states need updating
310 310 subrepo.submerge(repo, wctx, mctx, wctx)
311 311 try:
312 312 util.unlink(repo.wjoin(f))
313 313 except OSError, inst:
314 314 if inst.errno != errno.ENOENT:
315 315 repo.ui.warn(_("update failed to remove %s: %s!\n") %
316 316 (f, inst.strerror))
317 317 removed += 1
318 318 elif m == "m": # merge
319 319 if f == '.hgsubstate': # subrepo states need updating
320 320 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx))
321 321 continue
322 322 f2, fd, flags, move = a[2:]
323 323 r = ms.resolve(fd, wctx, mctx)
324 324 if r is not None and r > 0:
325 325 unresolved += 1
326 326 else:
327 327 if r is None:
328 328 updated += 1
329 329 else:
330 330 merged += 1
331 331 util.set_flags(repo.wjoin(fd), 'l' in flags, 'x' in flags)
332 332 if f != fd and move and os.path.lexists(repo.wjoin(f)):
333 333 repo.ui.debug("removing %s\n" % f)
334 334 os.unlink(repo.wjoin(f))
335 335 elif m == "g": # get
336 336 flags = a[2]
337 337 repo.ui.note(_("getting %s\n") % f)
338 338 t = mctx.filectx(f).data()
339 339 repo.wwrite(f, t, flags)
340 340 t = None
341 341 updated += 1
342 342 if f == '.hgsubstate': # subrepo states need updating
343 343 subrepo.submerge(repo, wctx, mctx, wctx)
344 344 elif m == "d": # directory rename
345 345 f2, fd, flags = a[2:]
346 346 if f:
347 347 repo.ui.note(_("moving %s to %s\n") % (f, fd))
348 348 t = wctx.filectx(f).data()
349 349 repo.wwrite(fd, t, flags)
350 350 util.unlink(repo.wjoin(f))
351 351 if f2:
352 352 repo.ui.note(_("getting %s to %s\n") % (f2, fd))
353 353 t = mctx.filectx(f2).data()
354 354 repo.wwrite(fd, t, flags)
355 355 updated += 1
356 356 elif m == "dr": # divergent renames
357 357 fl = a[2]
358 358 repo.ui.warn(_("note: possible conflict - %s was renamed "
359 359 "multiple times to:\n") % f)
360 360 for nf in fl:
361 361 repo.ui.warn(" %s\n" % nf)
362 362 elif m == "e": # exec
363 363 flags = a[2]
364 364 util.set_flags(repo.wjoin(f), 'l' in flags, 'x' in flags)
365 365 ms.commit()
366 366 u.progress(_('updating'), None, total=numupdates, unit=_('files'))
367 367
368 368 return updated, merged, removed, unresolved
369 369
370 370 def recordupdates(repo, action, branchmerge):
371 371 "record merge actions to the dirstate"
372 372
373 373 for a in action:
374 374 f, m = a[:2]
375 375 if m == "r": # remove
376 376 if branchmerge:
377 377 repo.dirstate.remove(f)
378 378 else:
379 379 repo.dirstate.forget(f)
380 380 elif m == "a": # re-add
381 381 if not branchmerge:
382 382 repo.dirstate.add(f)
383 383 elif m == "f": # forget
384 384 repo.dirstate.forget(f)
385 385 elif m == "e": # exec change
386 386 repo.dirstate.normallookup(f)
387 387 elif m == "g": # get
388 388 if branchmerge:
389 389 repo.dirstate.otherparent(f)
390 390 else:
391 391 repo.dirstate.normal(f)
392 392 elif m == "m": # merge
393 393 f2, fd, flag, move = a[2:]
394 394 if branchmerge:
395 395 # We've done a branch merge, mark this file as merged
396 396 # so that we properly record the merger later
397 397 repo.dirstate.merge(fd)
398 398 if f != f2: # copy/rename
399 399 if move:
400 400 repo.dirstate.remove(f)
401 401 if f != fd:
402 402 repo.dirstate.copy(f, fd)
403 403 else:
404 404 repo.dirstate.copy(f2, fd)
405 405 else:
406 406 # We've update-merged a locally modified file, so
407 407 # we set the dirstate to emulate a normal checkout
408 408 # of that file some time in the past. Thus our
409 409 # merge will appear as a normal local file
410 410 # modification.
411 411 if f2 == fd: # file not locally copied/moved
412 412 repo.dirstate.normallookup(fd)
413 413 if move:
414 414 repo.dirstate.forget(f)
415 415 elif m == "d": # directory rename
416 416 f2, fd, flag = a[2:]
417 417 if not f2 and f not in repo.dirstate:
418 418 # untracked file moved
419 419 continue
420 420 if branchmerge:
421 421 repo.dirstate.add(fd)
422 422 if f:
423 423 repo.dirstate.remove(f)
424 424 repo.dirstate.copy(f, fd)
425 425 if f2:
426 426 repo.dirstate.copy(f2, fd)
427 427 else:
428 428 repo.dirstate.normal(fd)
429 429 if f:
430 430 repo.dirstate.forget(f)
431 431
432 432 def update(repo, node, branchmerge, force, partial):
433 433 """
434 434 Perform a merge between the working directory and the given node
435 435
436 436 node = the node to update to, or None if unspecified
437 437 branchmerge = whether to merge between branches
438 438 force = whether to force branch merging or file overwriting
439 439 partial = a function to filter file lists (dirstate not updated)
440 440
441 441 The table below shows all the behaviors of the update command
442 442 given the -c and -C or no options, whether the working directory
443 443 is dirty, whether a revision is specified, and the relationship of
444 444 the parent rev to the target rev (linear, on the same named
445 445 branch, or on another named branch).
446 446
447 447 This logic is tested by test-update-branches.t.
448 448
449 449 -c -C dirty rev | linear same cross
450 450 n n n n | ok (1) x
451 451 n n n y | ok ok ok
452 452 n n y * | merge (2) (2)
453 453 n y * * | --- discard ---
454 454 y n y * | --- (3) ---
455 455 y n n * | --- ok ---
456 456 y y * * | --- (4) ---
457 457
458 458 x = can't happen
459 459 * = don't-care
460 460 1 = abort: crosses branches (use 'hg merge' or 'hg update -c')
461 461 2 = abort: crosses branches (use 'hg merge' to merge or
462 462 use 'hg update -C' to discard changes)
463 463 3 = abort: uncommitted local changes
464 464 4 = incompatible options (checked in commands.py)
465 465 """
466 466
467 467 onode = node
468 468 wlock = repo.wlock()
469 469 try:
470 470 wc = repo[None]
471 471 if node is None:
472 472 # tip of current branch
473 473 try:
474 474 node = repo.branchtags()[wc.branch()]
475 475 except KeyError:
476 476 if wc.branch() == "default": # no default branch!
477 477 node = repo.lookup("tip") # update to tip
478 478 else:
479 479 raise util.Abort(_("branch %s not found") % wc.branch())
480 480 overwrite = force and not branchmerge
481 481 pl = wc.parents()
482 482 p1, p2 = pl[0], repo[node]
483 483 pa = p1.ancestor(p2)
484 484 fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
485 485 fastforward = False
486 486
487 487 ### check phase
488 488 if not overwrite and len(pl) > 1:
489 489 raise util.Abort(_("outstanding uncommitted merges"))
490 490 if branchmerge:
491 491 if pa == p2:
492 492 raise util.Abort(_("merging with a working directory ancestor"
493 493 " has no effect"))
494 494 elif pa == p1:
495 495 if p1.branch() != p2.branch():
496 496 fastforward = True
497 497 else:
498 498 raise util.Abort(_("nothing to merge (use 'hg update'"
499 499 " or check 'hg heads')"))
500 500 if not force and (wc.files() or wc.deleted()):
501 501 raise util.Abort(_("outstanding uncommitted changes "
502 502 "(use 'hg status' to list changes)"))
503 503 elif not overwrite:
504 504 if pa == p1 or pa == p2: # linear
505 505 pass # all good
506 506 elif wc.files() or wc.deleted():
507 507 raise util.Abort(_("crosses branches (merge branches or use"
508 508 " --clean to discard changes)"))
509 509 elif onode is None:
510 510 raise util.Abort(_("crosses branches (merge branches or use"
511 511 " --check to force update)"))
512 512 else:
513 513 # Allow jumping branches if clean and specific rev given
514 514 overwrite = True
515 515
516 516 ### calculate phase
517 517 action = []
518 518 wc.status(unknown=True) # prime cache
519 519 if not force:
520 520 _checkunknown(wc, p2)
521 521 if not util.checkcase(repo.path):
522 522 _checkcollision(p2)
523 523 action += _forgetremoved(wc, p2, branchmerge)
524 524 action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
525 525
526 526 ### apply phase
527 if not branchmerge: # just jump to the new rev
527 if not branchmerge or fastforward: # just jump to the new rev
528 528 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, ''
529 529 if not partial:
530 530 repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
531 531
532 532 stats = applyupdates(repo, action, wc, p2, pa)
533 533
534 534 if not partial:
535 535 repo.dirstate.setparents(fp1, fp2)
536 recordupdates(repo, action, branchmerge)
536 recordupdates(repo, action, branchmerge and not fastforward)
537 537 if not branchmerge and not fastforward:
538 538 repo.dirstate.setbranch(p2.branch())
539 539 finally:
540 540 wlock.release()
541 541
542 542 if not partial:
543 543 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
544 544 return stats
@@ -1,29 +1,34 b''
1 1 http://mercurial.selenic.com/bts/issue619
2 2
3 3 $ hg init
4 4 $ echo a > a
5 5 $ hg ci -Ama
6 6 adding a
7 7
8 8 $ echo b > b
9 9 $ hg branch b
10 10 marked working directory as branch b
11 11 $ hg ci -Amb
12 12 adding b
13 13
14 14 $ hg co -C 0
15 15 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
16 16
17 17 Fast-forward:
18 18
19 19 $ hg merge b
20 20 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
21 21 (branch merge, don't forget to commit)
22 $ hg branch
23 default
24 $ hg parent --template '{rev}:{node|short} {branches}: {desc}\n'
25 1:06c2121185be b: b
22 26 $ hg ci -Ammerge
27 created new head
23 28
24 29 Bogus fast-forward should fail:
25 30
26 31 $ hg merge b
27 32 abort: merging with a working directory ancestor has no effect
28 33 [255]
29 34
@@ -1,320 +1,319 b''
1 1 $ branchcache=.hg/branchheads.cache
2 2
3 3 $ hg init t
4 4 $ cd t
5 5
6 6 $ hg branches
7 7 $ echo foo > a
8 8 $ hg add a
9 9 $ hg ci -m "initial"
10 10 $ hg branch foo
11 11 marked working directory as branch foo
12 12 $ hg branch
13 13 foo
14 14 $ hg ci -m "add branch name"
15 15 $ hg branch bar
16 16 marked working directory as branch bar
17 17 $ hg ci -m "change branch name"
18 18
19 19 Branch shadowing:
20 20
21 21 $ hg branch default
22 22 abort: a branch of the same name already exists (use 'hg update' to switch to it)
23 23 [255]
24 24
25 25 $ hg branch -f default
26 26 marked working directory as branch default
27 27
28 28 $ hg ci -m "clear branch name"
29 29 created new head
30 30
31 31 There should be only one default branch head
32 32
33 33 $ hg heads .
34 34 changeset: 3:9d567d0b51f9
35 35 tag: tip
36 36 user: test
37 37 date: Thu Jan 01 00:00:00 1970 +0000
38 38 summary: clear branch name
39 39
40 40
41 41 $ hg co foo
42 42 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
43 43 $ hg branch
44 44 foo
45 45 $ echo bleah > a
46 46 $ hg ci -m "modify a branch"
47 47
48 48 $ hg merge default
49 49 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
50 50 (branch merge, don't forget to commit)
51 51
52 52 $ hg branch
53 53 foo
54 54 $ hg ci -m "merge"
55 55
56 56 $ hg log
57 57 changeset: 5:dc140083783b
58 58 branch: foo
59 59 tag: tip
60 60 parent: 4:98d14f698afe
61 61 parent: 3:9d567d0b51f9
62 62 user: test
63 63 date: Thu Jan 01 00:00:00 1970 +0000
64 64 summary: merge
65 65
66 66 changeset: 4:98d14f698afe
67 67 branch: foo
68 68 parent: 1:0079f24813e2
69 69 user: test
70 70 date: Thu Jan 01 00:00:00 1970 +0000
71 71 summary: modify a branch
72 72
73 73 changeset: 3:9d567d0b51f9
74 74 user: test
75 75 date: Thu Jan 01 00:00:00 1970 +0000
76 76 summary: clear branch name
77 77
78 78 changeset: 2:ed2bbf4e0102
79 79 branch: bar
80 80 user: test
81 81 date: Thu Jan 01 00:00:00 1970 +0000
82 82 summary: change branch name
83 83
84 84 changeset: 1:0079f24813e2
85 85 branch: foo
86 86 user: test
87 87 date: Thu Jan 01 00:00:00 1970 +0000
88 88 summary: add branch name
89 89
90 90 changeset: 0:db01e8ea3388
91 91 user: test
92 92 date: Thu Jan 01 00:00:00 1970 +0000
93 93 summary: initial
94 94
95 95 $ hg branches
96 96 foo 5:dc140083783b
97 97 default 3:9d567d0b51f9 (inactive)
98 98 bar 2:ed2bbf4e0102 (inactive)
99 99
100 100 $ hg branches -q
101 101 foo
102 102 default
103 103 bar
104 104
105 105 Test for invalid branch cache:
106 106
107 107 $ hg rollback
108 108 rolling back to revision 4 (undo commit)
109 109
110 110 $ cp $branchcache .hg/bc-invalid
111 111
112 112 $ hg log -r foo
113 113 changeset: 4:98d14f698afe
114 114 branch: foo
115 115 tag: tip
116 116 parent: 1:0079f24813e2
117 117 user: test
118 118 date: Thu Jan 01 00:00:00 1970 +0000
119 119 summary: modify a branch
120 120
121 121 $ cp .hg/bc-invalid $branchcache
122 122
123 123 $ hg --debug log -r foo
124 124 invalidating branch cache (tip differs)
125 125 changeset: 4:98d14f698afeaff8cb612dcf215ce95e639effc3
126 126 branch: foo
127 127 tag: tip
128 128 parent: 1:0079f24813e2b73a891577c243684c5066347bc8
129 129 parent: -1:0000000000000000000000000000000000000000
130 130 manifest: 4:d01b250baaa05909152f7ae07d7a649deea0df9a
131 131 user: test
132 132 date: Thu Jan 01 00:00:00 1970 +0000
133 133 files: a
134 134 extra: branch=foo
135 135 description:
136 136 modify a branch
137 137
138 138
139 139 $ rm $branchcache
140 140 $ echo corrupted > $branchcache
141 141
142 142 $ hg log -qr foo
143 143 4:98d14f698afe
144 144
145 145 $ cat $branchcache
146 146 98d14f698afeaff8cb612dcf215ce95e639effc3 4
147 147 9d567d0b51f9e2068b054e1948e1a927f99b5874 default
148 148 98d14f698afeaff8cb612dcf215ce95e639effc3 foo
149 149 ed2bbf4e01029020711be82ca905283e883f0e11 bar
150 150
151 151 Push should update the branch cache:
152 152
153 153 $ hg init ../target
154 154
155 155 Pushing just rev 0:
156 156
157 157 $ hg push -qr 0 ../target
158 158
159 159 $ cat ../target/$branchcache
160 160 db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 0
161 161 db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 default
162 162
163 163 Pushing everything:
164 164
165 165 $ hg push -qf ../target
166 166
167 167 $ cat ../target/$branchcache
168 168 98d14f698afeaff8cb612dcf215ce95e639effc3 4
169 169 9d567d0b51f9e2068b054e1948e1a927f99b5874 default
170 170 98d14f698afeaff8cb612dcf215ce95e639effc3 foo
171 171 ed2bbf4e01029020711be82ca905283e883f0e11 bar
172 172
173 173 Update with no arguments: tipmost revision of the current branch:
174 174
175 175 $ hg up -q -C 0
176 176 $ hg up -q
177 177 $ hg id
178 178 9d567d0b51f9
179 179
180 180 $ hg up -q 1
181 181 $ hg up -q
182 182 $ hg id
183 183 98d14f698afe (foo) tip
184 184
185 185 $ hg branch foobar
186 186 marked working directory as branch foobar
187 187
188 188 $ hg up
189 189 abort: branch foobar not found
190 190 [255]
191 191
192 192 Fastforward merge:
193 193
194 194 $ hg branch ff
195 195 marked working directory as branch ff
196 196
197 197 $ echo ff > ff
198 198 $ hg ci -Am'fast forward'
199 199 adding ff
200 200
201 201 $ hg up foo
202 202 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
203 203
204 204 $ hg merge ff
205 205 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
206 206 (branch merge, don't forget to commit)
207 207
208 208 $ hg branch
209 209 foo
210 210 $ hg commit -m'Merge ff into foo'
211 created new head
211 212 $ hg parents
212 changeset: 6:917eb54e1b4b
213 changeset: 6:6af8030670c9
213 214 branch: foo
214 215 tag: tip
215 parent: 4:98d14f698afe
216 parent: 5:6683a60370cb
217 216 user: test
218 217 date: Thu Jan 01 00:00:00 1970 +0000
219 218 summary: Merge ff into foo
220 219
221 220 $ hg manifest
222 221 a
223 222 ff
224 223
225 224
226 225 Test merging, add 3 default heads and one test head:
227 226
228 227 $ cd ..
229 228 $ hg init merges
230 229 $ cd merges
231 230 $ echo a > a
232 231 $ hg ci -Ama
233 232 adding a
234 233
235 234 $ echo b > b
236 235 $ hg ci -Amb
237 236 adding b
238 237
239 238 $ hg up 0
240 239 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
241 240 $ echo c > c
242 241 $ hg ci -Amc
243 242 adding c
244 243 created new head
245 244
246 245 $ hg up 0
247 246 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
248 247 $ echo d > d
249 248 $ hg ci -Amd
250 249 adding d
251 250 created new head
252 251
253 252 $ hg up 0
254 253 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
255 254 $ hg branch test
256 255 marked working directory as branch test
257 256 $ echo e >> e
258 257 $ hg ci -Ame
259 258 adding e
260 259
261 260 $ hg log
262 261 changeset: 4:3a1e01ed1df4
263 262 branch: test
264 263 tag: tip
265 264 parent: 0:cb9a9f314b8b
266 265 user: test
267 266 date: Thu Jan 01 00:00:00 1970 +0000
268 267 summary: e
269 268
270 269 changeset: 3:980f7dc84c29
271 270 parent: 0:cb9a9f314b8b
272 271 user: test
273 272 date: Thu Jan 01 00:00:00 1970 +0000
274 273 summary: d
275 274
276 275 changeset: 2:d36c0562f908
277 276 parent: 0:cb9a9f314b8b
278 277 user: test
279 278 date: Thu Jan 01 00:00:00 1970 +0000
280 279 summary: c
281 280
282 281 changeset: 1:d2ae7f538514
283 282 user: test
284 283 date: Thu Jan 01 00:00:00 1970 +0000
285 284 summary: b
286 285
287 286 changeset: 0:cb9a9f314b8b
288 287 user: test
289 288 date: Thu Jan 01 00:00:00 1970 +0000
290 289 summary: a
291 290
292 291 Implicit merge with test branch as parent:
293 292
294 293 $ hg merge
295 294 abort: branch 'test' has one head - please merge with an explicit rev
296 295 (run 'hg heads' to see all heads)
297 296 [255]
298 297 $ hg up -C default
299 298 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
300 299
301 300 Implicit merge with default branch as parent:
302 301
303 302 $ hg merge
304 303 abort: branch 'default' has 3 heads - please merge with an explicit rev
305 304 (run 'hg heads .' to see heads)
306 305 [255]
307 306
308 307 3 branch heads, explicit merge required:
309 308
310 309 $ hg merge 2
311 310 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
312 311 (branch merge, don't forget to commit)
313 312 $ hg ci -m merge
314 313
315 314 2 branch heads, implicit merge works:
316 315
317 316 $ hg merge
318 317 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
319 318 (branch merge, don't forget to commit)
320 319
@@ -1,718 +1,719 b''
1 1 $ echo "[extensions]" >> $HGRCPATH
2 2 $ echo "graphlog=" >> $HGRCPATH
3 3
4 4 $ mkdir a
5 5 $ cd a
6 6 $ hg init
7 7 $ echo foo > t1
8 8 $ hg add t1
9 9 $ hg commit -m "1"
10 10
11 11 $ cd ..
12 12 $ hg clone a b
13 13 updating to branch default
14 14 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
15 15
16 16 $ cd a
17 17 $ echo foo > t2
18 18 $ hg add t2
19 19 $ hg commit -m "2"
20 20
21 21 $ cd ../b
22 22 $ echo foo > t3
23 23 $ hg add t3
24 24 $ hg commit -m "3"
25 25
26 26 $ hg push ../a
27 27 pushing to ../a
28 28 searching for changes
29 29 abort: push creates new remote heads on branch 'default'!
30 30 (you should pull and merge or use push -f to force)
31 31 [255]
32 32
33 33 $ hg push --debug ../a
34 34 pushing to ../a
35 35 searching for changes
36 36 examining 1c9246a22a0a:d8d565842d04
37 37 found incomplete branch 1c9246a22a0a:d8d565842d04
38 38 searching: 1 queries
39 39 narrowing 1:1 d8d565842d04
40 40 found new branch changeset 1c9246a22a0a
41 41 found new changesets starting at 1c9246a22a0a
42 42 1 total queries
43 43 common changesets up to d8d565842d04
44 44 new remote heads on branch 'default'
45 45 new remote head 1e108cc5548c
46 46 abort: push creates new remote heads on branch 'default'!
47 47 (you should pull and merge or use push -f to force)
48 48 [255]
49 49
50 50 $ hg pull ../a
51 51 pulling from ../a
52 52 searching for changes
53 53 adding changesets
54 54 adding manifests
55 55 adding file changes
56 56 added 1 changesets with 1 changes to 1 files (+1 heads)
57 57 (run 'hg heads' to see heads, 'hg merge' to merge)
58 58
59 59 $ hg push ../a
60 60 pushing to ../a
61 61 searching for changes
62 62 abort: push creates new remote heads on branch 'default'!
63 63 (did you forget to merge? use push -f to force)
64 64 [255]
65 65
66 66 $ hg merge
67 67 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
68 68 (branch merge, don't forget to commit)
69 69
70 70 $ hg commit -m "4"
71 71 $ hg push ../a
72 72 pushing to ../a
73 73 searching for changes
74 74 adding changesets
75 75 adding manifests
76 76 adding file changes
77 77 added 2 changesets with 1 changes to 1 files
78 78
79 79 $ cd ..
80 80
81 81 $ hg init c
82 82 $ cd c
83 83 $ for i in 0 1 2; do
84 84 > echo $i >> foo
85 85 > hg ci -Am $i
86 86 > done
87 87 adding foo
88 88 $ cd ..
89 89
90 90 $ hg clone c d
91 91 updating to branch default
92 92 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
93 93
94 94 $ cd d
95 95 $ for i in 0 1; do
96 96 > hg co -C $i
97 97 > echo d-$i >> foo
98 98 > hg ci -m d-$i
99 99 > done
100 100 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
101 101 created new head
102 102 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
103 103 created new head
104 104
105 105 $ HGMERGE=true hg merge 3
106 106 merging foo
107 107 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
108 108 (branch merge, don't forget to commit)
109 109
110 110 $ hg ci -m c-d
111 111
112 112 $ hg push ../c
113 113 pushing to ../c
114 114 searching for changes
115 115 abort: push creates new remote heads on branch 'default'!
116 116 (did you forget to merge? use push -f to force)
117 117 [255]
118 118
119 119 $ hg push -r 2 ../c
120 120 pushing to ../c
121 121 searching for changes
122 122 no changes found
123 123
124 124 $ hg push -r 3 ../c
125 125 pushing to ../c
126 126 searching for changes
127 127 abort: push creates new remote heads on branch 'default'!
128 128 (did you forget to merge? use push -f to force)
129 129 [255]
130 130
131 131 $ hg push -r 3 -r 4 ../c
132 132 pushing to ../c
133 133 searching for changes
134 134 abort: push creates new remote heads on branch 'default'!
135 135 (did you forget to merge? use push -f to force)
136 136 [255]
137 137
138 138 $ hg push -f -r 3 -r 4 ../c
139 139 pushing to ../c
140 140 searching for changes
141 141 adding changesets
142 142 adding manifests
143 143 adding file changes
144 144 added 2 changesets with 2 changes to 1 files (+2 heads)
145 145
146 146 $ hg push -r 5 ../c
147 147 pushing to ../c
148 148 searching for changes
149 149 adding changesets
150 150 adding manifests
151 151 adding file changes
152 152 added 1 changesets with 1 changes to 1 files (-1 heads)
153 153
154 154 $ hg in ../c
155 155 comparing with ../c
156 156 searching for changes
157 157 no changes found
158 158 [1]
159 159
160 160
161 161 Issue450: push -r warns about remote head creation even if no heads
162 162 will be created
163 163
164 164 $ hg init ../e
165 165 $ hg push -r 0 ../e
166 166 pushing to ../e
167 167 searching for changes
168 168 adding changesets
169 169 adding manifests
170 170 adding file changes
171 171 added 1 changesets with 1 changes to 1 files
172 172
173 173 $ hg push -r 1 ../e
174 174 pushing to ../e
175 175 searching for changes
176 176 adding changesets
177 177 adding manifests
178 178 adding file changes
179 179 added 1 changesets with 1 changes to 1 files
180 180
181 181 $ cd ..
182 182
183 183
184 184 Issue736: named branches are not considered for detection of
185 185 unmerged heads in "hg push"
186 186
187 187 $ hg init f
188 188 $ cd f
189 189 $ hg -q branch a
190 190 $ echo 0 > foo
191 191 $ hg -q ci -Am 0
192 192 $ echo 1 > foo
193 193 $ hg -q ci -m 1
194 194 $ hg -q up 0
195 195 $ echo 2 > foo
196 196 $ hg -q ci -m 2
197 197 $ hg -q up 0
198 198 $ hg -q branch b
199 199 $ echo 3 > foo
200 200 $ hg -q ci -m 3
201 201 $ cd ..
202 202
203 203 $ hg -q clone f g
204 204 $ cd g
205 205
206 206 Push on existing branch and new branch:
207 207
208 208 $ hg -q up 1
209 209 $ echo 4 > foo
210 210 $ hg -q ci -m 4
211 211 $ hg -q up 0
212 212 $ echo 5 > foo
213 213 $ hg -q branch c
214 214 $ hg -q ci -m 5
215 215
216 216 $ hg push ../f
217 217 pushing to ../f
218 218 searching for changes
219 219 abort: push creates new remote branches: c!
220 220 (use 'hg push --new-branch' to create new remote branches)
221 221 [255]
222 222
223 223 $ hg push -r 4 -r 5 ../f
224 224 pushing to ../f
225 225 searching for changes
226 226 abort: push creates new remote branches: c!
227 227 (use 'hg push --new-branch' to create new remote branches)
228 228 [255]
229 229
230 230
231 231 Multiple new branches:
232 232
233 233 $ hg -q branch d
234 234 $ echo 6 > foo
235 235 $ hg -q ci -m 6
236 236
237 237 $ hg push ../f
238 238 pushing to ../f
239 239 searching for changes
240 240 abort: push creates new remote branches: c, d!
241 241 (use 'hg push --new-branch' to create new remote branches)
242 242 [255]
243 243
244 244 $ hg push -r 4 -r 6 ../f
245 245 pushing to ../f
246 246 searching for changes
247 247 abort: push creates new remote branches: c, d!
248 248 (use 'hg push --new-branch' to create new remote branches)
249 249 [255]
250 250
251 251 $ cd ../g
252 252
253 253
254 254 Fail on multiple head push:
255 255
256 256 $ hg -q up 1
257 257 $ echo 7 > foo
258 258 $ hg -q ci -m 7
259 259
260 260 $ hg push -r 4 -r 7 ../f
261 261 pushing to ../f
262 262 searching for changes
263 263 abort: push creates new remote heads on branch 'a'!
264 264 (did you forget to merge? use push -f to force)
265 265 [255]
266 266
267 267 Push replacement head on existing branches:
268 268
269 269 $ hg -q up 3
270 270 $ echo 8 > foo
271 271 $ hg -q ci -m 8
272 272
273 273 $ hg push -r 7 -r 8 ../f
274 274 pushing to ../f
275 275 searching for changes
276 276 adding changesets
277 277 adding manifests
278 278 adding file changes
279 279 added 2 changesets with 2 changes to 1 files
280 280
281 281
282 282 Merge of branch a to other branch b followed by unrelated push
283 283 on branch a:
284 284
285 285 $ hg -q up 7
286 286 $ HGMERGE=true hg -q merge 8
287 287 $ hg -q ci -m 9
288 288 $ hg -q up 8
289 289 $ echo 10 > foo
290 290 $ hg -q ci -m 10
291 291
292 292 $ hg push -r 9 ../f
293 293 pushing to ../f
294 294 searching for changes
295 295 adding changesets
296 296 adding manifests
297 297 adding file changes
298 298 added 1 changesets with 1 changes to 1 files (-1 heads)
299 299
300 300 $ hg push -r 10 ../f
301 301 pushing to ../f
302 302 searching for changes
303 303 adding changesets
304 304 adding manifests
305 305 adding file changes
306 306 added 1 changesets with 1 changes to 1 files (+1 heads)
307 307
308 308
309 309 Cheating the counting algorithm:
310 310
311 311 $ hg -q up 9
312 312 $ HGMERGE=true hg -q merge 2
313 313 $ hg -q ci -m 11
314 314 $ hg -q up 1
315 315 $ echo 12 > foo
316 316 $ hg -q ci -m 12
317 317
318 318 $ hg push -r 11 -r 12 ../f
319 319 pushing to ../f
320 320 searching for changes
321 321 adding changesets
322 322 adding manifests
323 323 adding file changes
324 324 added 2 changesets with 2 changes to 1 files
325 325
326 326
327 327 Failed push of new named branch:
328 328
329 329 $ echo 12 > foo
330 330 $ hg -q ci -m 12a
331 331 [1]
332 332 $ hg -q up 11
333 333 $ echo 13 > foo
334 334 $ hg -q branch e
335 335 $ hg -q ci -m 13d
336 336
337 337 $ hg push -r 12 -r 13 ../f
338 338 pushing to ../f
339 339 searching for changes
340 340 abort: push creates new remote branches: e!
341 341 (use 'hg push --new-branch' to create new remote branches)
342 342 [255]
343 343
344 344
345 345 Using --new-branch to push new named branch:
346 346
347 347 $ hg push --new-branch -r 12 -r 13 ../f
348 348 pushing to ../f
349 349 searching for changes
350 350 adding changesets
351 351 adding manifests
352 352 adding file changes
353 353 added 1 changesets with 1 changes to 1 files
354 354
355 355
356 356 Checking prepush logic does not allow silently pushing
357 357 multiple new heads:
358 358
359 359 $ cd ..
360 360 $ hg init h
361 361 $ echo init > h/init
362 362 $ hg -R h ci -Am init
363 363 adding init
364 364 $ echo a > h/a
365 365 $ hg -R h ci -Am a
366 366 adding a
367 367 $ hg clone h i
368 368 updating to branch default
369 369 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
370 370 $ hg -R h up 0
371 371 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
372 372 $ echo b > h/b
373 373 $ hg -R h ci -Am b
374 374 adding b
375 375 created new head
376 376 $ hg -R i up 0
377 377 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
378 378 $ echo c > i/c
379 379 $ hg -R i ci -Am c
380 380 adding c
381 381 created new head
382 382
383 383 $ hg -R i push h
384 384 pushing to h
385 385 searching for changes
386 386 abort: push creates new remote heads on branch 'default'!
387 387 (you should pull and merge or use push -f to force)
388 388 [255]
389 389
390 390
391 391 Check prepush logic with merged branches:
392 392
393 393 $ hg init j
394 394 $ hg -R j branch a
395 395 marked working directory as branch a
396 396 $ echo init > j/foo
397 397 $ hg -R j ci -Am init
398 398 adding foo
399 399 $ hg clone j k
400 400 updating to branch a
401 401 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
402 402 $ echo a1 > j/foo
403 403 $ hg -R j ci -m a1
404 404 $ hg -R k branch b
405 405 marked working directory as branch b
406 406 $ echo b > k/foo
407 407 $ hg -R k ci -m b
408 408 $ hg -R k up 0
409 409 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
410 410
411 411 $ hg -R k merge b
412 412 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
413 413 (branch merge, don't forget to commit)
414 414
415 415 $ hg -R k ci -m merge
416 created new head
416 417
417 418 $ hg -R k push -r a j
418 419 pushing to j
419 420 searching for changes
420 421 abort: push creates new remote branches: b!
421 422 (use 'hg push --new-branch' to create new remote branches)
422 423 [255]
423 424
424 425
425 426 Prepush -r should not allow you to sneak in new heads:
426 427
427 428 $ hg init l
428 429 $ cd l
429 430 $ echo a >> foo
430 431 $ hg -q add foo
431 432 $ hg -q branch a
432 433 $ hg -q ci -ma
433 434 $ hg -q up null
434 435 $ echo a >> foo
435 436 $ hg -q add foo
436 437 $ hg -q branch b
437 438 $ hg -q ci -mb
438 439 $ cd ..
439 440 $ hg -q clone l m -u a
440 441 $ cd m
441 442 $ hg -q merge b
442 443 $ hg -q ci -mmb
443 444 $ hg -q up 0
444 445 $ echo a >> foo
445 446 $ hg -q ci -ma2
446 447 $ hg -q up 2
447 448 $ echo a >> foo
448 449 $ hg -q branch -f b
449 450 $ hg -q ci -mb2
450 451 $ hg -q merge 3
451 452 $ hg -q ci -mma
452 453
453 454 $ hg push ../l -b b
454 455 pushing to ../l
455 456 searching for changes
456 457 abort: push creates new remote heads on branch 'a'!
457 458 (did you forget to merge? use push -f to force)
458 459 [255]
459 460
460 461 $ cd ..
461 462
462 463
463 464 Check prepush with new branch head on former topo non-head:
464 465
465 466 $ hg init n
466 467 $ cd n
467 468 $ hg branch A
468 469 marked working directory as branch A
469 470 $ echo a >a
470 471 $ hg ci -Ama
471 472 adding a
472 473 $ hg branch B
473 474 marked working directory as branch B
474 475 $ echo b >b
475 476 $ hg ci -Amb
476 477 adding b
477 478
478 479 b is now branch head of B, and a topological head
479 480 a is now branch head of A, but not a topological head
480 481
481 482 $ hg clone . inner
482 483 updating to branch B
483 484 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
484 485 $ cd inner
485 486 $ hg up B
486 487 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
487 488 $ echo b1 >b1
488 489 $ hg ci -Amb1
489 490 adding b1
490 491
491 492 in the clone b1 is now the head of B
492 493
493 494 $ cd ..
494 495 $ hg up 0
495 496 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
496 497 $ echo a2 >a2
497 498 $ hg ci -Ama2
498 499 adding a2
499 500
500 501 a2 is now the new branch head of A, and a new topological head
501 502 it replaces a former inner branch head, so it should at most warn about
502 503 A, not B
503 504
504 505 glog of local:
505 506
506 507 $ hg glog --template "{rev}: {branches} {desc}\n"
507 508 @ 2: A a2
508 509 |
509 510 | o 1: B b
510 511 |/
511 512 o 0: A a
512 513
513 514 glog of remote:
514 515
515 516 $ hg glog -R inner --template "{rev}: {branches} {desc}\n"
516 517 @ 2: B b1
517 518 |
518 519 o 1: B b
519 520 |
520 521 o 0: A a
521 522
522 523 outgoing:
523 524
524 525 $ hg out inner --template "{rev}: {branches} {desc}\n"
525 526 comparing with inner
526 527 searching for changes
527 528 2: A a2
528 529
529 530 $ hg push inner
530 531 pushing to inner
531 532 searching for changes
532 533 adding changesets
533 534 adding manifests
534 535 adding file changes
535 536 added 1 changesets with 1 changes to 1 files (+1 heads)
536 537
537 538 $ cd ..
538 539
539 540
540 541 Check prepush with new branch head on former topo head:
541 542
542 543 $ hg init o
543 544 $ cd o
544 545 $ hg branch A
545 546 marked working directory as branch A
546 547 $ echo a >a
547 548 $ hg ci -Ama
548 549 adding a
549 550 $ hg branch B
550 551 marked working directory as branch B
551 552 $ echo b >b
552 553 $ hg ci -Amb
553 554 adding b
554 555
555 556 b is now branch head of B, and a topological head
556 557
557 558 $ hg up 0
558 559 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
559 560 $ echo a1 >a1
560 561 $ hg ci -Ama1
561 562 adding a1
562 563
563 564 a1 is now branch head of A, and a topological head
564 565
565 566 $ hg clone . inner
566 567 updating to branch A
567 568 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
568 569 $ cd inner
569 570 $ hg up B
570 571 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
571 572 $ echo b1 >b1
572 573 $ hg ci -Amb1
573 574 adding b1
574 575
575 576 in the clone b1 is now the head of B
576 577
577 578 $ cd ..
578 579 $ echo a2 >a2
579 580 $ hg ci -Ama2
580 581 adding a2
581 582
582 583 a2 is now the new branch head of A, and a topological head
583 584 it replaces a former topological and branch head, so this should not warn
584 585
585 586 glog of local:
586 587
587 588 $ hg glog --template "{rev}: {branches} {desc}\n"
588 589 @ 3: A a2
589 590 |
590 591 o 2: A a1
591 592 |
592 593 | o 1: B b
593 594 |/
594 595 o 0: A a
595 596
596 597 glog of remote:
597 598
598 599 $ hg glog -R inner --template "{rev}: {branches} {desc}\n"
599 600 @ 3: B b1
600 601 |
601 602 | o 2: A a1
602 603 | |
603 604 o | 1: B b
604 605 |/
605 606 o 0: A a
606 607
607 608 outgoing:
608 609
609 610 $ hg out inner --template "{rev}: {branches} {desc}\n"
610 611 comparing with inner
611 612 searching for changes
612 613 3: A a2
613 614
614 615 $ hg push inner
615 616 pushing to inner
616 617 searching for changes
617 618 adding changesets
618 619 adding manifests
619 620 adding file changes
620 621 added 1 changesets with 1 changes to 1 files
621 622
622 623 $ cd ..
623 624
624 625
625 626 Check prepush with new branch head and new child of former branch head
626 627 but child is on different branch:
627 628
628 629 $ hg init p
629 630 $ cd p
630 631 $ hg branch A
631 632 marked working directory as branch A
632 633 $ echo a0 >a
633 634 $ hg ci -Ama0
634 635 adding a
635 636 $ echo a1 >a
636 637 $ hg ci -ma1
637 638 $ hg up null
638 639 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
639 640 $ hg branch B
640 641 marked working directory as branch B
641 642 $ echo b0 >b
642 643 $ hg ci -Amb0
643 644 adding b
644 645 $ echo b1 >b
645 646 $ hg ci -mb1
646 647
647 648 $ hg clone . inner
648 649 updating to branch B
649 650 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
650 651
651 652 $ hg up A
652 653 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
653 654 $ hg branch -f B
654 655 marked working directory as branch B
655 656 $ echo a3 >a
656 657 $ hg ci -ma3
657 658 created new head
658 659 $ hg up 3
659 660 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
660 661 $ hg branch -f A
661 662 marked working directory as branch A
662 663 $ echo b3 >b
663 664 $ hg ci -mb3
664 665 created new head
665 666
666 667 glog of local:
667 668
668 669 $ hg glog --template "{rev}: {branches} {desc}\n"
669 670 @ 5: A b3
670 671 |
671 672 | o 4: B a3
672 673 | |
673 674 o | 3: B b1
674 675 | |
675 676 o | 2: B b0
676 677 /
677 678 o 1: A a1
678 679 |
679 680 o 0: A a0
680 681
681 682 glog of remote:
682 683
683 684 $ hg glog -R inner --template "{rev}: {branches} {desc}\n"
684 685 @ 3: B b1
685 686 |
686 687 o 2: B b0
687 688
688 689 o 1: A a1
689 690 |
690 691 o 0: A a0
691 692
692 693 outgoing:
693 694
694 695 $ hg out inner --template "{rev}: {branches} {desc}\n"
695 696 comparing with inner
696 697 searching for changes
697 698 4: B a3
698 699 5: A b3
699 700
700 701 $ hg push inner
701 702 pushing to inner
702 703 searching for changes
703 704 abort: push creates new remote heads on branch 'A'!
704 705 (did you forget to merge? use push -f to force)
705 706 [255]
706 707
707 708 $ hg push inner -r4 -r5
708 709 pushing to inner
709 710 searching for changes
710 711 abort: push creates new remote heads on branch 'A'!
711 712 (did you forget to merge? use push -f to force)
712 713 [255]
713 714
714 715 $ hg in inner
715 716 comparing with inner
716 717 searching for changes
717 718 no changes found
718 719 [1]
General Comments 0
You need to be logged in to leave comments. Login now