##// END OF EJS Templates
push: added clear warning message when pushing closed branches(issue6080)...
Taapas Agrawal -
r42389:5997eabc default
parent child Browse files
Show More
@@ -1,529 +1,538
1 1 # discovery.py - protocol changeset discovery functions
2 2 #
3 3 # Copyright 2010 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 functools
11 11
12 12 from .i18n import _
13 13 from .node import (
14 14 hex,
15 15 nullid,
16 16 short,
17 17 )
18 18
19 19 from . import (
20 20 bookmarks,
21 21 branchmap,
22 22 error,
23 23 phases,
24 24 scmutil,
25 25 setdiscovery,
26 26 treediscovery,
27 27 util,
28 28 )
29 29
30 30 def findcommonincoming(repo, remote, heads=None, force=False, ancestorsof=None):
31 31 """Return a tuple (common, anyincoming, heads) used to identify the common
32 32 subset of nodes between repo and remote.
33 33
34 34 "common" is a list of (at least) the heads of the common subset.
35 35 "anyincoming" is testable as a boolean indicating if any nodes are missing
36 36 locally. If remote does not support getbundle, this actually is a list of
37 37 roots of the nodes that would be incoming, to be supplied to
38 38 changegroupsubset. No code except for pull should be relying on this fact
39 39 any longer.
40 40 "heads" is either the supplied heads, or else the remote's heads.
41 41 "ancestorsof" if not None, restrict the discovery to a subset defined by
42 42 these nodes. Changeset outside of this set won't be considered (and
43 43 won't appears in "common")
44 44
45 45 If you pass heads and they are all known locally, the response lists just
46 46 these heads in "common" and in "heads".
47 47
48 48 Please use findcommonoutgoing to compute the set of outgoing nodes to give
49 49 extensions a good hook into outgoing.
50 50 """
51 51
52 52 if not remote.capable('getbundle'):
53 53 return treediscovery.findcommonincoming(repo, remote, heads, force)
54 54
55 55 if heads:
56 56 knownnode = repo.changelog.hasnode # no nodemap until it is filtered
57 57 if all(knownnode(h) for h in heads):
58 58 return (heads, False, heads)
59 59
60 60 res = setdiscovery.findcommonheads(repo.ui, repo, remote,
61 61 abortwhenunrelated=not force,
62 62 ancestorsof=ancestorsof)
63 63 common, anyinc, srvheads = res
64 64 return (list(common), anyinc, heads or list(srvheads))
65 65
66 66 class outgoing(object):
67 67 '''Represents the set of nodes present in a local repo but not in a
68 68 (possibly) remote one.
69 69
70 70 Members:
71 71
72 72 missing is a list of all nodes present in local but not in remote.
73 73 common is a list of all nodes shared between the two repos.
74 74 excluded is the list of missing changeset that shouldn't be sent remotely.
75 75 missingheads is the list of heads of missing.
76 76 commonheads is the list of heads of common.
77 77
78 78 The sets are computed on demand from the heads, unless provided upfront
79 79 by discovery.'''
80 80
81 81 def __init__(self, repo, commonheads=None, missingheads=None,
82 82 missingroots=None):
83 83 # at least one of them must not be set
84 84 assert None in (commonheads, missingroots)
85 85 cl = repo.changelog
86 86 if missingheads is None:
87 87 missingheads = cl.heads()
88 88 if missingroots:
89 89 discbases = []
90 90 for n in missingroots:
91 91 discbases.extend([p for p in cl.parents(n) if p != nullid])
92 92 # TODO remove call to nodesbetween.
93 93 # TODO populate attributes on outgoing instance instead of setting
94 94 # discbases.
95 95 csets, roots, heads = cl.nodesbetween(missingroots, missingheads)
96 96 included = set(csets)
97 97 missingheads = heads
98 98 commonheads = [n for n in discbases if n not in included]
99 99 elif not commonheads:
100 100 commonheads = [nullid]
101 101 self.commonheads = commonheads
102 102 self.missingheads = missingheads
103 103 self._revlog = cl
104 104 self._common = None
105 105 self._missing = None
106 106 self.excluded = []
107 107
108 108 def _computecommonmissing(self):
109 109 sets = self._revlog.findcommonmissing(self.commonheads,
110 110 self.missingheads)
111 111 self._common, self._missing = sets
112 112
113 113 @util.propertycache
114 114 def common(self):
115 115 if self._common is None:
116 116 self._computecommonmissing()
117 117 return self._common
118 118
119 119 @util.propertycache
120 120 def missing(self):
121 121 if self._missing is None:
122 122 self._computecommonmissing()
123 123 return self._missing
124 124
125 125 def findcommonoutgoing(repo, other, onlyheads=None, force=False,
126 126 commoninc=None, portable=False):
127 127 '''Return an outgoing instance to identify the nodes present in repo but
128 128 not in other.
129 129
130 130 If onlyheads is given, only nodes ancestral to nodes in onlyheads
131 131 (inclusive) are included. If you already know the local repo's heads,
132 132 passing them in onlyheads is faster than letting them be recomputed here.
133 133
134 134 If commoninc is given, it must be the result of a prior call to
135 135 findcommonincoming(repo, other, force) to avoid recomputing it here.
136 136
137 137 If portable is given, compute more conservative common and missingheads,
138 138 to make bundles created from the instance more portable.'''
139 139 # declare an empty outgoing object to be filled later
140 140 og = outgoing(repo, None, None)
141 141
142 142 # get common set if not provided
143 143 if commoninc is None:
144 144 commoninc = findcommonincoming(repo, other, force=force,
145 145 ancestorsof=onlyheads)
146 146 og.commonheads, _any, _hds = commoninc
147 147
148 148 # compute outgoing
149 149 mayexclude = (repo._phasecache.phaseroots[phases.secret] or repo.obsstore)
150 150 if not mayexclude:
151 151 og.missingheads = onlyheads or repo.heads()
152 152 elif onlyheads is None:
153 153 # use visible heads as it should be cached
154 154 og.missingheads = repo.filtered("served").heads()
155 155 og.excluded = [ctx.node() for ctx in repo.set('secret() or extinct()')]
156 156 else:
157 157 # compute common, missing and exclude secret stuff
158 158 sets = repo.changelog.findcommonmissing(og.commonheads, onlyheads)
159 159 og._common, allmissing = sets
160 160 og._missing = missing = []
161 161 og.excluded = excluded = []
162 162 for node in allmissing:
163 163 ctx = repo[node]
164 164 if ctx.phase() >= phases.secret or ctx.extinct():
165 165 excluded.append(node)
166 166 else:
167 167 missing.append(node)
168 168 if len(missing) == len(allmissing):
169 169 missingheads = onlyheads
170 170 else: # update missing heads
171 171 missingheads = phases.newheads(repo, onlyheads, excluded)
172 172 og.missingheads = missingheads
173 173 if portable:
174 174 # recompute common and missingheads as if -r<rev> had been given for
175 175 # each head of missing, and --base <rev> for each head of the proper
176 176 # ancestors of missing
177 177 og._computecommonmissing()
178 178 cl = repo.changelog
179 179 missingrevs = set(cl.rev(n) for n in og._missing)
180 180 og._common = set(cl.ancestors(missingrevs)) - missingrevs
181 181 commonheads = set(og.commonheads)
182 182 og.missingheads = [h for h in og.missingheads if h not in commonheads]
183 183
184 184 return og
185 185
186 186 def _headssummary(pushop):
187 187 """compute a summary of branch and heads status before and after push
188 188
189 189 return {'branch': ([remoteheads], [newheads],
190 190 [unsyncedheads], [discardedheads])} mapping
191 191
192 192 - branch: the branch name,
193 193 - remoteheads: the list of remote heads known locally
194 194 None if the branch is new,
195 195 - newheads: the new remote heads (known locally) with outgoing pushed,
196 196 - unsyncedheads: the list of remote heads unknown locally,
197 197 - discardedheads: the list of heads made obsolete by the push.
198 198 """
199 199 repo = pushop.repo.unfiltered()
200 200 remote = pushop.remote
201 201 outgoing = pushop.outgoing
202 202 cl = repo.changelog
203 203 headssum = {}
204 204 missingctx = set()
205 205 # A. Create set of branches involved in the push.
206 206 branches = set()
207 207 for n in outgoing.missing:
208 208 ctx = repo[n]
209 209 missingctx.add(ctx)
210 210 branches.add(ctx.branch())
211 211
212 212 with remote.commandexecutor() as e:
213 213 remotemap = e.callcommand('branchmap', {}).result()
214 214
215 215 knownnode = cl.hasnode # do not use nodemap until it is filtered
216 216 # A. register remote heads of branches which are in outgoing set
217 217 for branch, heads in remotemap.iteritems():
218 218 # don't add head info about branches which we don't have locally
219 219 if branch not in branches:
220 220 continue
221 221 known = []
222 222 unsynced = []
223 223 for h in heads:
224 224 if knownnode(h):
225 225 known.append(h)
226 226 else:
227 227 unsynced.append(h)
228 228 headssum[branch] = (known, list(known), unsynced)
229 229
230 230 # B. add new branch data
231 231 for branch in branches:
232 232 if branch not in headssum:
233 233 headssum[branch] = (None, [], [])
234 234
235 235 # C. Update newmap with outgoing changes.
236 236 # This will possibly add new heads and remove existing ones.
237 237 newmap = branchmap.remotebranchcache((branch, heads[1])
238 238 for branch, heads in headssum.iteritems()
239 239 if heads[0] is not None)
240 240 newmap.update(repo, (ctx.rev() for ctx in missingctx))
241 241 for branch, newheads in newmap.iteritems():
242 242 headssum[branch][1][:] = newheads
243 243 for branch, items in headssum.iteritems():
244 244 for l in items:
245 245 if l is not None:
246 246 l.sort()
247 247 headssum[branch] = items + ([],)
248 248
249 249 # If there are no obsstore, no post processing are needed.
250 250 if repo.obsstore:
251 251 torev = repo.changelog.rev
252 252 futureheads = set(torev(h) for h in outgoing.missingheads)
253 253 futureheads |= set(torev(h) for h in outgoing.commonheads)
254 254 allfuturecommon = repo.changelog.ancestors(futureheads, inclusive=True)
255 255 for branch, heads in sorted(headssum.iteritems()):
256 256 remoteheads, newheads, unsyncedheads, placeholder = heads
257 257 result = _postprocessobsolete(pushop, allfuturecommon, newheads)
258 258 headssum[branch] = (remoteheads, sorted(result[0]), unsyncedheads,
259 259 sorted(result[1]))
260 260 return headssum
261 261
262 262 def _oldheadssummary(repo, remoteheads, outgoing, inc=False):
263 263 """Compute branchmapsummary for repo without branchmap support"""
264 264
265 265 # 1-4b. old servers: Check for new topological heads.
266 266 # Construct {old,new}map with branch = None (topological branch).
267 267 # (code based on update)
268 268 knownnode = repo.changelog.hasnode # no nodemap until it is filtered
269 269 oldheads = sorted(h for h in remoteheads if knownnode(h))
270 270 # all nodes in outgoing.missing are children of either:
271 271 # - an element of oldheads
272 272 # - another element of outgoing.missing
273 273 # - nullrev
274 274 # This explains why the new head are very simple to compute.
275 275 r = repo.set('heads(%ln + %ln)', oldheads, outgoing.missing)
276 276 newheads = sorted(c.node() for c in r)
277 277 # set some unsynced head to issue the "unsynced changes" warning
278 278 if inc:
279 279 unsynced = [None]
280 280 else:
281 281 unsynced = []
282 282 return {None: (oldheads, newheads, unsynced, [])}
283 283
284 284 def _nowarnheads(pushop):
285 285 # Compute newly pushed bookmarks. We don't warn about bookmarked heads.
286 286 repo = pushop.repo.unfiltered()
287 287 remote = pushop.remote
288 288 localbookmarks = repo._bookmarks
289 289
290 290 with remote.commandexecutor() as e:
291 291 remotebookmarks = e.callcommand('listkeys', {
292 292 'namespace': 'bookmarks',
293 293 }).result()
294 294
295 295 bookmarkedheads = set()
296 296
297 297 # internal config: bookmarks.pushing
298 298 newbookmarks = [localbookmarks.expandname(b)
299 299 for b in pushop.ui.configlist('bookmarks', 'pushing')]
300 300
301 301 for bm in localbookmarks:
302 302 rnode = remotebookmarks.get(bm)
303 303 if rnode and rnode in repo:
304 304 lctx, rctx = localbookmarks.changectx(bm), repo[rnode]
305 305 if bookmarks.validdest(repo, rctx, lctx):
306 306 bookmarkedheads.add(lctx.node())
307 307 else:
308 308 if bm in newbookmarks and bm not in remotebookmarks:
309 309 bookmarkedheads.add(localbookmarks[bm])
310 310
311 311 return bookmarkedheads
312 312
313 313 def checkheads(pushop):
314 314 """Check that a push won't add any outgoing head
315 315
316 316 raise Abort error and display ui message as needed.
317 317 """
318 318
319 319 repo = pushop.repo.unfiltered()
320 320 remote = pushop.remote
321 321 outgoing = pushop.outgoing
322 322 remoteheads = pushop.remoteheads
323 323 newbranch = pushop.newbranch
324 324 inc = bool(pushop.incoming)
325 325
326 326 # Check for each named branch if we're creating new remote heads.
327 327 # To be a remote head after push, node must be either:
328 328 # - unknown locally
329 329 # - a local outgoing head descended from update
330 330 # - a remote head that's known locally and not
331 331 # ancestral to an outgoing head
332 332 if remoteheads == [nullid]:
333 333 # remote is empty, nothing to check.
334 334 return
335 335
336 336 if remote.capable('branchmap'):
337 337 headssum = _headssummary(pushop)
338 338 else:
339 339 headssum = _oldheadssummary(repo, remoteheads, outgoing, inc)
340 340 pushop.pushbranchmap = headssum
341 341 newbranches = [branch for branch, heads in headssum.iteritems()
342 342 if heads[0] is None]
343 # Makes a set of closed branches
344 closedbranches = set()
345 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
346 if isclosed:
347 closedbranches.add(tag)
348 closedbranches = (closedbranches & set(newbranches))
343 349 # 1. Check for new branches on the remote.
344 350 if newbranches and not newbranch: # new branch requires --new-branch
345 351 branchnames = ', '.join(sorted(newbranches))
346 raise error.Abort(_("push creates new remote branches: %s!")
347 % branchnames,
348 hint=_("use 'hg push --new-branch' to create"
349 " new remote branches"))
352 if closedbranches:
353 errmsg = (_("push creates new remote branches: %s (%d closed)!")
354 % (branchnames, len(closedbranches)))
355 else:
356 errmsg = (_("push creates new remote branches: %s!")% branchnames)
357 hint=_("use 'hg push --new-branch' to create new remote branches")
358 raise error.Abort(errmsg, hint=hint)
350 359
351 360 # 2. Find heads that we need not warn about
352 361 nowarnheads = _nowarnheads(pushop)
353 362
354 363 # 3. Check for new heads.
355 364 # If there are more heads after the push than before, a suitable
356 365 # error message, depending on unsynced status, is displayed.
357 366 errormsg = None
358 367 for branch, heads in sorted(headssum.iteritems()):
359 368 remoteheads, newheads, unsyncedheads, discardedheads = heads
360 369 # add unsynced data
361 370 if remoteheads is None:
362 371 oldhs = set()
363 372 else:
364 373 oldhs = set(remoteheads)
365 374 oldhs.update(unsyncedheads)
366 375 dhs = None # delta heads, the new heads on branch
367 376 newhs = set(newheads)
368 377 newhs.update(unsyncedheads)
369 378 if unsyncedheads:
370 379 if None in unsyncedheads:
371 380 # old remote, no heads data
372 381 heads = None
373 382 else:
374 383 heads = scmutil.nodesummaries(repo, unsyncedheads)
375 384 if heads is None:
376 385 repo.ui.status(_("remote has heads that are "
377 386 "not known locally\n"))
378 387 elif branch is None:
379 388 repo.ui.status(_("remote has heads that are "
380 389 "not known locally: %s\n") % heads)
381 390 else:
382 391 repo.ui.status(_("remote has heads on branch '%s' that are "
383 392 "not known locally: %s\n") % (branch, heads))
384 393 if remoteheads is None:
385 394 if len(newhs) > 1:
386 395 dhs = list(newhs)
387 396 if errormsg is None:
388 397 errormsg = (_("push creates new branch '%s' "
389 398 "with multiple heads") % (branch))
390 399 hint = _("merge or"
391 400 " see 'hg help push' for details about"
392 401 " pushing new heads")
393 402 elif len(newhs) > len(oldhs):
394 403 # remove bookmarked or existing remote heads from the new heads list
395 404 dhs = sorted(newhs - nowarnheads - oldhs)
396 405 if dhs:
397 406 if errormsg is None:
398 407 if branch not in ('default', None):
399 408 errormsg = _("push creates new remote head %s "
400 409 "on branch '%s'!") % (short(dhs[0]), branch)
401 410 elif repo[dhs[0]].bookmarks():
402 411 errormsg = _("push creates new remote head %s "
403 412 "with bookmark '%s'!") % (
404 413 short(dhs[0]), repo[dhs[0]].bookmarks()[0])
405 414 else:
406 415 errormsg = _("push creates new remote head %s!"
407 416 ) % short(dhs[0])
408 417 if unsyncedheads:
409 418 hint = _("pull and merge or"
410 419 " see 'hg help push' for details about"
411 420 " pushing new heads")
412 421 else:
413 422 hint = _("merge or"
414 423 " see 'hg help push' for details about"
415 424 " pushing new heads")
416 425 if branch is None:
417 426 repo.ui.note(_("new remote heads:\n"))
418 427 else:
419 428 repo.ui.note(_("new remote heads on branch '%s':\n") % branch)
420 429 for h in dhs:
421 430 repo.ui.note((" %s\n") % short(h))
422 431 if errormsg:
423 432 raise error.Abort(errormsg, hint=hint)
424 433
425 434 def _postprocessobsolete(pushop, futurecommon, candidate_newhs):
426 435 """post process the list of new heads with obsolescence information
427 436
428 437 Exists as a sub-function to contain the complexity and allow extensions to
429 438 experiment with smarter logic.
430 439
431 440 Returns (newheads, discarded_heads) tuple
432 441 """
433 442 # known issue
434 443 #
435 444 # * We "silently" skip processing on all changeset unknown locally
436 445 #
437 446 # * if <nh> is public on the remote, it won't be affected by obsolete
438 447 # marker and a new is created
439 448
440 449 # define various utilities and containers
441 450 repo = pushop.repo
442 451 unfi = repo.unfiltered()
443 452 tonode = unfi.changelog.node
444 453 torev = unfi.changelog.nodemap.get
445 454 public = phases.public
446 455 getphase = unfi._phasecache.phase
447 456 ispublic = (lambda r: getphase(unfi, r) == public)
448 457 ispushed = (lambda n: torev(n) in futurecommon)
449 458 hasoutmarker = functools.partial(pushingmarkerfor, unfi.obsstore, ispushed)
450 459 successorsmarkers = unfi.obsstore.successors
451 460 newhs = set() # final set of new heads
452 461 discarded = set() # new head of fully replaced branch
453 462
454 463 localcandidate = set() # candidate heads known locally
455 464 unknownheads = set() # candidate heads unknown locally
456 465 for h in candidate_newhs:
457 466 if h in unfi:
458 467 localcandidate.add(h)
459 468 else:
460 469 if successorsmarkers.get(h) is not None:
461 470 msg = ('checkheads: remote head unknown locally has'
462 471 ' local marker: %s\n')
463 472 repo.ui.debug(msg % hex(h))
464 473 unknownheads.add(h)
465 474
466 475 # fast path the simple case
467 476 if len(localcandidate) == 1:
468 477 return unknownheads | set(candidate_newhs), set()
469 478
470 479 # actually process branch replacement
471 480 while localcandidate:
472 481 nh = localcandidate.pop()
473 482 # run this check early to skip the evaluation of the whole branch
474 483 if (torev(nh) in futurecommon or ispublic(torev(nh))):
475 484 newhs.add(nh)
476 485 continue
477 486
478 487 # Get all revs/nodes on the branch exclusive to this head
479 488 # (already filtered heads are "ignored"))
480 489 branchrevs = unfi.revs('only(%n, (%ln+%ln))',
481 490 nh, localcandidate, newhs)
482 491 branchnodes = [tonode(r) for r in branchrevs]
483 492
484 493 # The branch won't be hidden on the remote if
485 494 # * any part of it is public,
486 495 # * any part of it is considered part of the result by previous logic,
487 496 # * if we have no markers to push to obsolete it.
488 497 if (any(ispublic(r) for r in branchrevs)
489 498 or any(torev(n) in futurecommon for n in branchnodes)
490 499 or any(not hasoutmarker(n) for n in branchnodes)):
491 500 newhs.add(nh)
492 501 else:
493 502 # note: there is a corner case if there is a merge in the branch.
494 503 # we might end up with -more- heads. However, these heads are not
495 504 # "added" by the push, but more by the "removal" on the remote so I
496 505 # think is a okay to ignore them,
497 506 discarded.add(nh)
498 507 newhs |= unknownheads
499 508 return newhs, discarded
500 509
501 510 def pushingmarkerfor(obsstore, ispushed, node):
502 511 """true if some markers are to be pushed for node
503 512
504 513 We cannot just look in to the pushed obsmarkers from the pushop because
505 514 discovery might have filtered relevant markers. In addition listing all
506 515 markers relevant to all changesets in the pushed set would be too expensive
507 516 (O(len(repo)))
508 517
509 518 (note: There are cache opportunity in this function. but it would requires
510 519 a two dimensional stack.)
511 520 """
512 521 successorsmarkers = obsstore.successors
513 522 stack = [node]
514 523 seen = set(stack)
515 524 while stack:
516 525 current = stack.pop()
517 526 if ispushed(current):
518 527 return True
519 528 markers = successorsmarkers.get(current, ())
520 529 # markers fields = ('prec', 'succs', 'flag', 'meta', 'date', 'parents')
521 530 for m in markers:
522 531 nexts = m[1] # successors
523 532 if not nexts: # this is a prune marker
524 533 nexts = m[5] or () # parents
525 534 for n in nexts:
526 535 if n not in seen:
527 536 seen.add(n)
528 537 stack.append(n)
529 538 return False
@@ -1,793 +1,847
1 1 $ hg init a
2 2 $ cd a
3 3 $ echo foo > t1
4 4 $ hg add t1
5 5 $ hg commit -m "1"
6 6
7 7 $ cd ..
8 8 $ hg clone a b
9 9 updating to branch default
10 10 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
11 11
12 12 $ cd a
13 13 $ echo foo > t2
14 14 $ hg add t2
15 15 $ hg commit -m "2"
16 16
17 17 $ cd ../b
18 18 $ echo foo > t3
19 19 $ hg add t3
20 20 $ hg commit -m "3"
21 21
22 22 Specifying a revset that evaluates to null will abort
23 23
24 24 $ hg push -r '0 & 1' ../a
25 25 pushing to ../a
26 26 abort: specified revisions evaluate to an empty set
27 27 (use different revision arguments)
28 28 [255]
29 29
30 30 $ hg push ../a
31 31 pushing to ../a
32 32 searching for changes
33 33 remote has heads on branch 'default' that are not known locally: 1c9246a22a0a
34 34 abort: push creates new remote head 1e108cc5548c!
35 35 (pull and merge or see 'hg help push' for details about pushing new heads)
36 36 [255]
37 37
38 38 $ hg push --debug ../a
39 39 pushing to ../a
40 40 query 1; heads
41 41 searching for changes
42 42 taking quick initial sample
43 43 query 2; still undecided: 1, sample size is: 1
44 44 2 total queries in *.????s (glob)
45 45 listing keys for "phases"
46 46 checking for updated bookmarks
47 47 listing keys for "bookmarks"
48 48 listing keys for "bookmarks"
49 49 remote has heads on branch 'default' that are not known locally: 1c9246a22a0a
50 50 new remote heads on branch 'default':
51 51 1e108cc5548c
52 52 abort: push creates new remote head 1e108cc5548c!
53 53 (pull and merge or see 'hg help push' for details about pushing new heads)
54 54 [255]
55 55
56 56 $ hg pull ../a
57 57 pulling from ../a
58 58 searching for changes
59 59 adding changesets
60 60 adding manifests
61 61 adding file changes
62 62 added 1 changesets with 1 changes to 1 files (+1 heads)
63 63 new changesets 1c9246a22a0a
64 64 (run 'hg heads' to see heads, 'hg merge' to merge)
65 65
66 66 $ hg push ../a
67 67 pushing to ../a
68 68 searching for changes
69 69 abort: push creates new remote head 1e108cc5548c!
70 70 (merge or see 'hg help push' for details about pushing new heads)
71 71 [255]
72 72
73 73 $ hg merge
74 74 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
75 75 (branch merge, don't forget to commit)
76 76
77 77 $ hg commit -m "4"
78 78 $ hg push ../a
79 79 pushing to ../a
80 80 searching for changes
81 81 adding changesets
82 82 adding manifests
83 83 adding file changes
84 84 added 2 changesets with 1 changes to 1 files
85 85
86 86 $ cd ..
87 87
88 88 $ hg init c
89 89 $ cd c
90 90 $ for i in 0 1 2; do
91 91 > echo $i >> foo
92 92 > hg ci -Am $i
93 93 > done
94 94 adding foo
95 95 $ cd ..
96 96
97 97 $ hg clone c d
98 98 updating to branch default
99 99 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
100 100
101 101 $ cd d
102 102 $ for i in 0 1; do
103 103 > hg co -C $i
104 104 > echo d-$i >> foo
105 105 > hg ci -m d-$i
106 106 > done
107 107 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
108 108 created new head
109 109 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
110 110 created new head
111 111
112 112 $ HGMERGE=true hg merge 3
113 113 merging foo
114 114 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
115 115 (branch merge, don't forget to commit)
116 116
117 117 $ hg ci -m c-d
118 118
119 119 $ hg push ../c
120 120 pushing to ../c
121 121 searching for changes
122 122 abort: push creates new remote head 6346d66eb9f5!
123 123 (merge or see 'hg help push' for details about pushing new heads)
124 124 [255]
125 125
126 126 $ hg push -r 2 ../c
127 127 pushing to ../c
128 128 searching for changes
129 129 no changes found
130 130 [1]
131 131
132 132 $ hg push -r 3 ../c
133 133 pushing to ../c
134 134 searching for changes
135 135 abort: push creates new remote head a5dda829a167!
136 136 (merge or see 'hg help push' for details about pushing new heads)
137 137 [255]
138 138
139 139 $ hg push -v -r 3 -r 4 ../c
140 140 pushing to ../c
141 141 searching for changes
142 142 new remote heads on branch 'default':
143 143 a5dda829a167
144 144 ee8fbc7a0295
145 145 abort: push creates new remote head a5dda829a167!
146 146 (merge or see 'hg help push' for details about pushing new heads)
147 147 [255]
148 148
149 149 $ hg push -v -f -r 3 -r 4 ../c
150 150 pushing to ../c
151 151 searching for changes
152 152 2 changesets found
153 153 uncompressed size of bundle content:
154 154 352 (changelog)
155 155 326 (manifests)
156 156 25\d foo (re)
157 157 adding changesets
158 158 adding manifests
159 159 adding file changes
160 160 added 2 changesets with 2 changes to 1 files (+2 heads)
161 161
162 162 $ hg push -r 5 ../c
163 163 pushing to ../c
164 164 searching for changes
165 165 adding changesets
166 166 adding manifests
167 167 adding file changes
168 168 added 1 changesets with 1 changes to 1 files (-1 heads)
169 169
170 170 $ hg in ../c
171 171 comparing with ../c
172 172 searching for changes
173 173 no changes found
174 174 [1]
175 175
176 176
177 177 Issue450: push -r warns about remote head creation even if no heads
178 178 will be created
179 179
180 180 $ hg init ../e
181 181 $ hg push -r 0 ../e
182 182 pushing to ../e
183 183 searching for changes
184 184 adding changesets
185 185 adding manifests
186 186 adding file changes
187 187 added 1 changesets with 1 changes to 1 files
188 188
189 189 $ hg push -r 1 ../e
190 190 pushing to ../e
191 191 searching for changes
192 192 adding changesets
193 193 adding manifests
194 194 adding file changes
195 195 added 1 changesets with 1 changes to 1 files
196 196
197 197 $ cd ..
198 198
199 199
200 200 Issue736: named branches are not considered for detection of
201 201 unmerged heads in "hg push"
202 202
203 203 $ hg init f
204 204 $ cd f
205 205 $ hg -q branch a
206 206 $ echo 0 > foo
207 207 $ hg -q ci -Am 0
208 208 $ echo 1 > foo
209 209 $ hg -q ci -m 1
210 210 $ hg -q up 0
211 211 $ echo 2 > foo
212 212 $ hg -q ci -m 2
213 213 $ hg -q up 0
214 214 $ hg -q branch b
215 215 $ echo 3 > foo
216 216 $ hg -q ci -m 3
217 217 $ cd ..
218 218
219 219 $ hg -q clone f g
220 220 $ cd g
221 221
222 222 Push on existing branch and new branch:
223 223
224 224 $ hg -q up 1
225 225 $ echo 4 > foo
226 226 $ hg -q ci -m 4
227 227 $ hg -q up 0
228 228 $ echo 5 > foo
229 229 $ hg -q branch c
230 230 $ hg -q ci -m 5
231 231
232 232 $ hg push ../f
233 233 pushing to ../f
234 234 searching for changes
235 235 abort: push creates new remote branches: c!
236 236 (use 'hg push --new-branch' to create new remote branches)
237 237 [255]
238 238
239 239 $ hg push -r 4 -r 5 ../f
240 240 pushing to ../f
241 241 searching for changes
242 242 abort: push creates new remote branches: c!
243 243 (use 'hg push --new-branch' to create new remote branches)
244 244 [255]
245 245
246 246
247 247 Multiple new branches:
248 248
249 249 $ hg -q branch d
250 250 $ echo 6 > foo
251 251 $ hg -q ci -m 6
252 252
253 253 $ hg push ../f
254 254 pushing to ../f
255 255 searching for changes
256 256 abort: push creates new remote branches: c, d!
257 257 (use 'hg push --new-branch' to create new remote branches)
258 258 [255]
259 259
260 260 $ hg push -r 4 -r 6 ../f
261 261 pushing to ../f
262 262 searching for changes
263 263 abort: push creates new remote branches: c, d!
264 264 (use 'hg push --new-branch' to create new remote branches)
265 265 [255]
266 266
267 267 $ cd ../g
268 268
269 269
270 270 Fail on multiple head push:
271 271
272 272 $ hg -q up 1
273 273 $ echo 7 > foo
274 274 $ hg -q ci -m 7
275 275
276 276 $ hg push -r 4 -r 7 ../f
277 277 pushing to ../f
278 278 searching for changes
279 279 abort: push creates new remote head 0b715ef6ff8f on branch 'a'!
280 280 (merge or see 'hg help push' for details about pushing new heads)
281 281 [255]
282 282
283 283 Push replacement head on existing branches:
284 284
285 285 $ hg -q up 3
286 286 $ echo 8 > foo
287 287 $ hg -q ci -m 8
288 288
289 289 $ hg push -r 7 -r 8 ../f
290 290 pushing to ../f
291 291 searching for changes
292 292 adding changesets
293 293 adding manifests
294 294 adding file changes
295 295 added 2 changesets with 2 changes to 1 files
296 296
297 297
298 298 Merge of branch a to other branch b followed by unrelated push
299 299 on branch a:
300 300
301 301 $ hg -q up 7
302 302 $ HGMERGE=true hg -q merge 8
303 303 $ hg -q ci -m 9
304 304 $ hg -q up 8
305 305 $ echo 10 > foo
306 306 $ hg -q ci -m 10
307 307
308 308 $ hg push -r 9 ../f
309 309 pushing to ../f
310 310 searching for changes
311 311 adding changesets
312 312 adding manifests
313 313 adding file changes
314 314 added 1 changesets with 1 changes to 1 files (-1 heads)
315 315
316 316 $ hg push -r 10 ../f
317 317 pushing to ../f
318 318 searching for changes
319 319 adding changesets
320 320 adding manifests
321 321 adding file changes
322 322 added 1 changesets with 1 changes to 1 files (+1 heads)
323 323
324 324
325 325 Cheating the counting algorithm:
326 326
327 327 $ hg -q up 9
328 328 $ HGMERGE=true hg -q merge 2
329 329 $ hg -q ci -m 11
330 330 $ hg -q up 1
331 331 $ echo 12 > foo
332 332 $ hg -q ci -m 12
333 333
334 334 $ hg push -r 11 -r 12 ../f
335 335 pushing to ../f
336 336 searching for changes
337 337 adding changesets
338 338 adding manifests
339 339 adding file changes
340 340 added 2 changesets with 2 changes to 1 files
341 341
342 342
343 343 Failed push of new named branch:
344 344
345 345 $ echo 12 > foo
346 346 $ hg -q ci -m 12a
347 347 [1]
348 348 $ hg -q up 11
349 349 $ echo 13 > foo
350 350 $ hg -q branch e
351 351 $ hg -q ci -m 13d
352 352
353 353 $ hg push -r 12 -r 13 ../f
354 354 pushing to ../f
355 355 searching for changes
356 356 abort: push creates new remote branches: e!
357 357 (use 'hg push --new-branch' to create new remote branches)
358 358 [255]
359 359
360 360
361 361 Using --new-branch to push new named branch:
362 362
363 363 $ hg push --new-branch -r 12 -r 13 ../f
364 364 pushing to ../f
365 365 searching for changes
366 366 adding changesets
367 367 adding manifests
368 368 adding file changes
369 369 added 1 changesets with 1 changes to 1 files
370 370
371 371 Pushing multi headed new branch:
372 372
373 373 $ echo 14 > foo
374 374 $ hg -q branch f
375 375 $ hg -q ci -m 14
376 376 $ echo 15 > foo
377 377 $ hg -q ci -m 15
378 378 $ hg -q up 14
379 379 $ echo 16 > foo
380 380 $ hg -q ci -m 16
381 381 $ hg push --branch f --new-branch ../f
382 382 pushing to ../f
383 383 searching for changes
384 384 abort: push creates new branch 'f' with multiple heads
385 385 (merge or see 'hg help push' for details about pushing new heads)
386 386 [255]
387 387 $ hg push --branch f --new-branch --force ../f
388 388 pushing to ../f
389 389 searching for changes
390 390 adding changesets
391 391 adding manifests
392 392 adding file changes
393 393 added 3 changesets with 3 changes to 1 files (+1 heads)
394 394
395 395 Checking prepush logic does not allow silently pushing
396 396 multiple new heads but also doesn't report too many heads:
397 397
398 398 $ cd ..
399 399 $ hg init h
400 400 $ echo init > h/init
401 401 $ hg -R h ci -Am init
402 402 adding init
403 403 $ echo a > h/a
404 404 $ hg -R h ci -Am a
405 405 adding a
406 406 $ hg clone h i
407 407 updating to branch default
408 408 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
409 409 $ hg -R h up 0
410 410 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
411 411 $ echo b > h/b
412 412 $ hg -R h ci -Am b
413 413 adding b
414 414 created new head
415 415 $ hg -R i up 0
416 416 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
417 417 $ echo c > i/c
418 418 $ hg -R i ci -Am c
419 419 adding c
420 420 created new head
421 421
422 422 $ for i in `"$PYTHON" $TESTDIR/seq.py 3`; do hg -R h up -q 0; echo $i > h/b; hg -R h ci -qAm$i; done
423 423
424 424 $ hg -R i push h
425 425 pushing to h
426 426 searching for changes
427 427 remote has heads on branch 'default' that are not known locally: 534543e22c29 764f8ec07b96 afe7cc7679f5 ce4212fc8847
428 428 abort: push creates new remote head 97bd0c84d346!
429 429 (pull and merge or see 'hg help push' for details about pushing new heads)
430 430 [255]
431 431 $ hg -R h up -q 0; echo x > h/b; hg -R h ci -qAmx
432 432 $ hg -R i push h
433 433 pushing to h
434 434 searching for changes
435 435 remote has heads on branch 'default' that are not known locally: 18ddb72c4590 534543e22c29 764f8ec07b96 afe7cc7679f5 and 1 others
436 436 abort: push creates new remote head 97bd0c84d346!
437 437 (pull and merge or see 'hg help push' for details about pushing new heads)
438 438 [255]
439 439 $ hg -R i push h -v
440 440 pushing to h
441 441 searching for changes
442 442 remote has heads on branch 'default' that are not known locally: 18ddb72c4590 534543e22c29 764f8ec07b96 afe7cc7679f5 ce4212fc8847
443 443 new remote heads on branch 'default':
444 444 97bd0c84d346
445 445 abort: push creates new remote head 97bd0c84d346!
446 446 (pull and merge or see 'hg help push' for details about pushing new heads)
447 447 [255]
448 448
449 449
450 450 Check prepush logic with merged branches:
451 451
452 452 $ hg init j
453 453 $ hg -R j branch a
454 454 marked working directory as branch a
455 455 (branches are permanent and global, did you want a bookmark?)
456 456 $ echo init > j/foo
457 457 $ hg -R j ci -Am init
458 458 adding foo
459 459 $ hg clone j k
460 460 updating to branch a
461 461 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
462 462 $ echo a1 > j/foo
463 463 $ hg -R j ci -m a1
464 464 $ hg -R k branch b
465 465 marked working directory as branch b
466 466 $ echo b > k/foo
467 467 $ hg -R k ci -m b
468 468 $ hg -R k up 0
469 469 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
470 470
471 471 $ hg -R k merge b
472 472 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
473 473 (branch merge, don't forget to commit)
474 474
475 475 $ hg -R k ci -m merge
476 476
477 477 $ hg -R k push -r a j
478 478 pushing to j
479 479 searching for changes
480 480 abort: push creates new remote branches: b!
481 481 (use 'hg push --new-branch' to create new remote branches)
482 482 [255]
483 483
484 484
485 485 Prepush -r should not allow you to sneak in new heads:
486 486
487 487 $ hg init l
488 488 $ cd l
489 489 $ echo a >> foo
490 490 $ hg -q add foo
491 491 $ hg -q branch a
492 492 $ hg -q ci -ma
493 493 $ hg -q up null
494 494 $ echo a >> foo
495 495 $ hg -q add foo
496 496 $ hg -q branch b
497 497 $ hg -q ci -mb
498 498 $ cd ..
499 499 $ hg -q clone l m -u a
500 500 $ cd m
501 501 $ hg -q merge b
502 502 $ hg -q ci -mmb
503 503 $ hg -q up 0
504 504 $ echo a >> foo
505 505 $ hg -q ci -ma2
506 506 $ hg -q up 2
507 507 $ echo a >> foo
508 508 $ hg -q branch -f b
509 509 $ hg -q ci -mb2
510 510 $ hg -q merge 3
511 511 $ hg -q ci -mma
512 512
513 513 $ hg push ../l -b b
514 514 pushing to ../l
515 515 searching for changes
516 516 abort: push creates new remote head 451211cc22b0 on branch 'a'!
517 517 (merge or see 'hg help push' for details about pushing new heads)
518 518 [255]
519 519
520 520 $ cd ..
521 521
522 522
523 523 Check prepush with new branch head on former topo non-head:
524 524
525 525 $ hg init n
526 526 $ cd n
527 527 $ hg branch A
528 528 marked working directory as branch A
529 529 (branches are permanent and global, did you want a bookmark?)
530 530 $ echo a >a
531 531 $ hg ci -Ama
532 532 adding a
533 533 $ hg branch B
534 534 marked working directory as branch B
535 535 $ echo b >b
536 536 $ hg ci -Amb
537 537 adding b
538 538
539 539 b is now branch head of B, and a topological head
540 540 a is now branch head of A, but not a topological head
541 541
542 542 $ hg clone . inner
543 543 updating to branch B
544 544 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
545 545 $ cd inner
546 546 $ hg up B
547 547 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
548 548 $ echo b1 >b1
549 549 $ hg ci -Amb1
550 550 adding b1
551 551
552 552 in the clone b1 is now the head of B
553 553
554 554 $ cd ..
555 555 $ hg up 0
556 556 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
557 557 $ echo a2 >a2
558 558 $ hg ci -Ama2
559 559 adding a2
560 560
561 561 a2 is now the new branch head of A, and a new topological head
562 562 it replaces a former inner branch head, so it should at most warn about
563 563 A, not B
564 564
565 565 glog of local:
566 566
567 567 $ hg log -G --template "{rev}: {branches} {desc}\n"
568 568 @ 2: A a2
569 569 |
570 570 | o 1: B b
571 571 |/
572 572 o 0: A a
573 573
574 574 glog of remote:
575 575
576 576 $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
577 577 @ 2: B b1
578 578 |
579 579 o 1: B b
580 580 |
581 581 o 0: A a
582 582
583 583 outgoing:
584 584
585 585 $ hg out inner --template "{rev}: {branches} {desc}\n"
586 586 comparing with inner
587 587 searching for changes
588 588 2: A a2
589 589
590 590 $ hg push inner
591 591 pushing to inner
592 592 searching for changes
593 593 adding changesets
594 594 adding manifests
595 595 adding file changes
596 596 added 1 changesets with 1 changes to 1 files (+1 heads)
597 597
598 598 $ cd ..
599 599
600 600
601 601 Check prepush with new branch head on former topo head:
602 602
603 603 $ hg init o
604 604 $ cd o
605 605 $ hg branch A
606 606 marked working directory as branch A
607 607 (branches are permanent and global, did you want a bookmark?)
608 608 $ echo a >a
609 609 $ hg ci -Ama
610 610 adding a
611 611 $ hg branch B
612 612 marked working directory as branch B
613 613 $ echo b >b
614 614 $ hg ci -Amb
615 615 adding b
616 616
617 617 b is now branch head of B, and a topological head
618 618
619 619 $ hg up 0
620 620 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
621 621 $ echo a1 >a1
622 622 $ hg ci -Ama1
623 623 adding a1
624 624
625 625 a1 is now branch head of A, and a topological head
626 626
627 627 $ hg clone . inner
628 628 updating to branch A
629 629 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
630 630 $ cd inner
631 631 $ hg up B
632 632 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
633 633 $ echo b1 >b1
634 634 $ hg ci -Amb1
635 635 adding b1
636 636
637 637 in the clone b1 is now the head of B
638 638
639 639 $ cd ..
640 640 $ echo a2 >a2
641 641 $ hg ci -Ama2
642 642 adding a2
643 643
644 644 a2 is now the new branch head of A, and a topological head
645 645 it replaces a former topological and branch head, so this should not warn
646 646
647 647 glog of local:
648 648
649 649 $ hg log -G --template "{rev}: {branches} {desc}\n"
650 650 @ 3: A a2
651 651 |
652 652 o 2: A a1
653 653 |
654 654 | o 1: B b
655 655 |/
656 656 o 0: A a
657 657
658 658 glog of remote:
659 659
660 660 $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
661 661 @ 3: B b1
662 662 |
663 663 | o 2: A a1
664 664 | |
665 665 o | 1: B b
666 666 |/
667 667 o 0: A a
668 668
669 669 outgoing:
670 670
671 671 $ hg out inner --template "{rev}: {branches} {desc}\n"
672 672 comparing with inner
673 673 searching for changes
674 674 3: A a2
675 675
676 676 $ hg push inner
677 677 pushing to inner
678 678 searching for changes
679 679 adding changesets
680 680 adding manifests
681 681 adding file changes
682 682 added 1 changesets with 1 changes to 1 files
683 683
684 684 $ cd ..
685 685
686 686
687 687 Check prepush with new branch head and new child of former branch head
688 688 but child is on different branch:
689 689
690 690 $ hg init p
691 691 $ cd p
692 692 $ hg branch A
693 693 marked working directory as branch A
694 694 (branches are permanent and global, did you want a bookmark?)
695 695 $ echo a0 >a
696 696 $ hg ci -Ama0
697 697 adding a
698 698 $ echo a1 >a
699 699 $ hg ci -ma1
700 700 $ hg up null
701 701 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
702 702 $ hg branch B
703 703 marked working directory as branch B
704 704 $ echo b0 >b
705 705 $ hg ci -Amb0
706 706 adding b
707 707 $ echo b1 >b
708 708 $ hg ci -mb1
709 709
710 710 $ hg clone . inner
711 711 updating to branch B
712 712 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
713 713
714 714 $ hg up A
715 715 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
716 716 $ hg branch -f B
717 717 marked working directory as branch B
718 718 $ echo a3 >a
719 719 $ hg ci -ma3
720 720 created new head
721 721 $ hg up 3
722 722 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
723 723 $ hg branch -f A
724 724 marked working directory as branch A
725 725 $ echo b3 >b
726 726 $ hg ci -mb3
727 727 created new head
728 728
729 729 glog of local:
730 730
731 731 $ hg log -G --template "{rev}: {branches} {desc}\n"
732 732 @ 5: A b3
733 733 |
734 734 | o 4: B a3
735 735 | |
736 736 o | 3: B b1
737 737 | |
738 738 o | 2: B b0
739 739 /
740 740 o 1: A a1
741 741 |
742 742 o 0: A a0
743 743
744 744 glog of remote:
745 745
746 746 $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
747 747 @ 3: B b1
748 748 |
749 749 o 2: B b0
750 750
751 751 o 1: A a1
752 752 |
753 753 o 0: A a0
754 754
755 755 outgoing:
756 756
757 757 $ hg out inner --template "{rev}: {branches} {desc}\n"
758 758 comparing with inner
759 759 searching for changes
760 760 4: B a3
761 761 5: A b3
762 762
763 763 $ hg push inner
764 764 pushing to inner
765 765 searching for changes
766 766 abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
767 767 (merge or see 'hg help push' for details about pushing new heads)
768 768 [255]
769 769
770 770 $ hg push inner -r4 -r5
771 771 pushing to inner
772 772 searching for changes
773 773 abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
774 774 (merge or see 'hg help push' for details about pushing new heads)
775 775 [255]
776 776
777 777 $ hg in inner
778 778 comparing with inner
779 779 searching for changes
780 780 no changes found
781 781 [1]
782 782
783 783 Test fail hook
784 784
785 785 $ hg push inner --config hooks.fail-push="echo running fail-push hook"
786 786 pushing to inner
787 787 searching for changes
788 788 running fail-push hook
789 789 abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
790 790 (merge or see 'hg help push' for details about pushing new heads)
791 791 [255]
792 792
793 793 $ cd ..
794
795 Test regarding pushing of closed branch/branches(Issue6080)
796
797 $ hg init x
798 $ cd x
799 $ hg -q branch a
800 $ echo 0 > foo
801 $ hg -q ci -Am 0
802 $ hg -q up 0
803 $ cd ..
804
805 $ hg -q clone x z
806 $ cd z
807
808 When there is a single closed branch
809
810 $ hg -q branch foo
811 $ echo 0 > foo
812 $ hg -q ci -Am 0
813 $ hg ci --close-branch -m 'closing branch foo'
814 $ hg -q up 0
815 $ hg push ../x
816 pushing to ../x
817 searching for changes
818 abort: push creates new remote branches: foo (1 closed)!
819 (use 'hg push --new-branch' to create new remote branches)
820 [255]
821
822 When there is more than one closed branches
823 $ hg -q branch bar
824 $ echo 0 > bar
825 $ hg -q ci -Am 0
826 $ hg ci --close-branch -m 'closing branch bar'
827 $ hg -q up 0
828 $ hg push ../x
829 pushing to ../x
830 searching for changes
831 abort: push creates new remote branches: bar, foo (2 closed)!
832 (use 'hg push --new-branch' to create new remote branches)
833 [255]
834
835 When there are more than one new branches and not all are closed
836 $ hg -q branch bar1
837 $ echo 0 > bar1
838 $ hg -q ci -Am 0
839 $ hg -q up 0
840 $ hg push ../x
841 pushing to ../x
842 searching for changes
843 abort: push creates new remote branches: bar, bar1, foo (2 closed)!
844 (use 'hg push --new-branch' to create new remote branches)
845 [255]
846
847 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now