##// END OF EJS Templates
rebase: use cmdutil.check_incompatible_arguments() for action+confirm/dryrun...
Martin von Zweigbergk -
r44379:905b2178 default
parent child Browse files
Show More
@@ -1,2308 +1,2308 b''
1 # rebase.py - rebasing feature for mercurial
1 # rebase.py - rebasing feature for mercurial
2 #
2 #
3 # Copyright 2008 Stefano Tortarolo <stefano.tortarolo at gmail dot com>
3 # Copyright 2008 Stefano Tortarolo <stefano.tortarolo at gmail dot com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 '''command to move sets of revisions to a different ancestor
8 '''command to move sets of revisions to a different ancestor
9
9
10 This extension lets you rebase changesets in an existing Mercurial
10 This extension lets you rebase changesets in an existing Mercurial
11 repository.
11 repository.
12
12
13 For more information:
13 For more information:
14 https://mercurial-scm.org/wiki/RebaseExtension
14 https://mercurial-scm.org/wiki/RebaseExtension
15 '''
15 '''
16
16
17 from __future__ import absolute_import
17 from __future__ import absolute_import
18
18
19 import errno
19 import errno
20 import os
20 import os
21
21
22 from mercurial.i18n import _
22 from mercurial.i18n import _
23 from mercurial.node import (
23 from mercurial.node import (
24 nullrev,
24 nullrev,
25 short,
25 short,
26 )
26 )
27 from mercurial.pycompat import open
27 from mercurial.pycompat import open
28 from mercurial import (
28 from mercurial import (
29 bookmarks,
29 bookmarks,
30 cmdutil,
30 cmdutil,
31 commands,
31 commands,
32 copies,
32 copies,
33 destutil,
33 destutil,
34 dirstateguard,
34 dirstateguard,
35 error,
35 error,
36 extensions,
36 extensions,
37 hg,
37 hg,
38 merge as mergemod,
38 merge as mergemod,
39 mergeutil,
39 mergeutil,
40 obsolete,
40 obsolete,
41 obsutil,
41 obsutil,
42 patch,
42 patch,
43 phases,
43 phases,
44 pycompat,
44 pycompat,
45 registrar,
45 registrar,
46 repair,
46 repair,
47 revset,
47 revset,
48 revsetlang,
48 revsetlang,
49 scmutil,
49 scmutil,
50 smartset,
50 smartset,
51 state as statemod,
51 state as statemod,
52 util,
52 util,
53 )
53 )
54
54
55 # The following constants are used throughout the rebase module. The ordering of
55 # The following constants are used throughout the rebase module. The ordering of
56 # their values must be maintained.
56 # their values must be maintained.
57
57
58 # Indicates that a revision needs to be rebased
58 # Indicates that a revision needs to be rebased
59 revtodo = -1
59 revtodo = -1
60 revtodostr = b'-1'
60 revtodostr = b'-1'
61
61
62 # legacy revstates no longer needed in current code
62 # legacy revstates no longer needed in current code
63 # -2: nullmerge, -3: revignored, -4: revprecursor, -5: revpruned
63 # -2: nullmerge, -3: revignored, -4: revprecursor, -5: revpruned
64 legacystates = {b'-2', b'-3', b'-4', b'-5'}
64 legacystates = {b'-2', b'-3', b'-4', b'-5'}
65
65
66 cmdtable = {}
66 cmdtable = {}
67 command = registrar.command(cmdtable)
67 command = registrar.command(cmdtable)
68 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
68 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
69 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
69 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
70 # be specifying the version(s) of Mercurial they are tested with, or
70 # be specifying the version(s) of Mercurial they are tested with, or
71 # leave the attribute unspecified.
71 # leave the attribute unspecified.
72 testedwith = b'ships-with-hg-core'
72 testedwith = b'ships-with-hg-core'
73
73
74
74
75 def _nothingtorebase():
75 def _nothingtorebase():
76 return 1
76 return 1
77
77
78
78
79 def _savegraft(ctx, extra):
79 def _savegraft(ctx, extra):
80 s = ctx.extra().get(b'source', None)
80 s = ctx.extra().get(b'source', None)
81 if s is not None:
81 if s is not None:
82 extra[b'source'] = s
82 extra[b'source'] = s
83 s = ctx.extra().get(b'intermediate-source', None)
83 s = ctx.extra().get(b'intermediate-source', None)
84 if s is not None:
84 if s is not None:
85 extra[b'intermediate-source'] = s
85 extra[b'intermediate-source'] = s
86
86
87
87
88 def _savebranch(ctx, extra):
88 def _savebranch(ctx, extra):
89 extra[b'branch'] = ctx.branch()
89 extra[b'branch'] = ctx.branch()
90
90
91
91
92 def _destrebase(repo, sourceset, destspace=None):
92 def _destrebase(repo, sourceset, destspace=None):
93 """small wrapper around destmerge to pass the right extra args
93 """small wrapper around destmerge to pass the right extra args
94
94
95 Please wrap destutil.destmerge instead."""
95 Please wrap destutil.destmerge instead."""
96 return destutil.destmerge(
96 return destutil.destmerge(
97 repo,
97 repo,
98 action=b'rebase',
98 action=b'rebase',
99 sourceset=sourceset,
99 sourceset=sourceset,
100 onheadcheck=False,
100 onheadcheck=False,
101 destspace=destspace,
101 destspace=destspace,
102 )
102 )
103
103
104
104
105 revsetpredicate = registrar.revsetpredicate()
105 revsetpredicate = registrar.revsetpredicate()
106
106
107
107
108 @revsetpredicate(b'_destrebase')
108 @revsetpredicate(b'_destrebase')
109 def _revsetdestrebase(repo, subset, x):
109 def _revsetdestrebase(repo, subset, x):
110 # ``_rebasedefaultdest()``
110 # ``_rebasedefaultdest()``
111
111
112 # default destination for rebase.
112 # default destination for rebase.
113 # # XXX: Currently private because I expect the signature to change.
113 # # XXX: Currently private because I expect the signature to change.
114 # # XXX: - bailing out in case of ambiguity vs returning all data.
114 # # XXX: - bailing out in case of ambiguity vs returning all data.
115 # i18n: "_rebasedefaultdest" is a keyword
115 # i18n: "_rebasedefaultdest" is a keyword
116 sourceset = None
116 sourceset = None
117 if x is not None:
117 if x is not None:
118 sourceset = revset.getset(repo, smartset.fullreposet(repo), x)
118 sourceset = revset.getset(repo, smartset.fullreposet(repo), x)
119 return subset & smartset.baseset([_destrebase(repo, sourceset)])
119 return subset & smartset.baseset([_destrebase(repo, sourceset)])
120
120
121
121
122 @revsetpredicate(b'_destautoorphanrebase')
122 @revsetpredicate(b'_destautoorphanrebase')
123 def _revsetdestautoorphanrebase(repo, subset, x):
123 def _revsetdestautoorphanrebase(repo, subset, x):
124 # ``_destautoorphanrebase()``
124 # ``_destautoorphanrebase()``
125
125
126 # automatic rebase destination for a single orphan revision.
126 # automatic rebase destination for a single orphan revision.
127 unfi = repo.unfiltered()
127 unfi = repo.unfiltered()
128 obsoleted = unfi.revs(b'obsolete()')
128 obsoleted = unfi.revs(b'obsolete()')
129
129
130 src = revset.getset(repo, subset, x).first()
130 src = revset.getset(repo, subset, x).first()
131
131
132 # Empty src or already obsoleted - Do not return a destination
132 # Empty src or already obsoleted - Do not return a destination
133 if not src or src in obsoleted:
133 if not src or src in obsoleted:
134 return smartset.baseset()
134 return smartset.baseset()
135 dests = destutil.orphanpossibledestination(repo, src)
135 dests = destutil.orphanpossibledestination(repo, src)
136 if len(dests) > 1:
136 if len(dests) > 1:
137 raise error.Abort(
137 raise error.Abort(
138 _(b"ambiguous automatic rebase: %r could end up on any of %r")
138 _(b"ambiguous automatic rebase: %r could end up on any of %r")
139 % (src, dests)
139 % (src, dests)
140 )
140 )
141 # We have zero or one destination, so we can just return here.
141 # We have zero or one destination, so we can just return here.
142 return smartset.baseset(dests)
142 return smartset.baseset(dests)
143
143
144
144
145 def _ctxdesc(ctx):
145 def _ctxdesc(ctx):
146 """short description for a context"""
146 """short description for a context"""
147 desc = b'%d:%s "%s"' % (
147 desc = b'%d:%s "%s"' % (
148 ctx.rev(),
148 ctx.rev(),
149 ctx,
149 ctx,
150 ctx.description().split(b'\n', 1)[0],
150 ctx.description().split(b'\n', 1)[0],
151 )
151 )
152 repo = ctx.repo()
152 repo = ctx.repo()
153 names = []
153 names = []
154 for nsname, ns in pycompat.iteritems(repo.names):
154 for nsname, ns in pycompat.iteritems(repo.names):
155 if nsname == b'branches':
155 if nsname == b'branches':
156 continue
156 continue
157 names.extend(ns.names(repo, ctx.node()))
157 names.extend(ns.names(repo, ctx.node()))
158 if names:
158 if names:
159 desc += b' (%s)' % b' '.join(names)
159 desc += b' (%s)' % b' '.join(names)
160 return desc
160 return desc
161
161
162
162
163 class rebaseruntime(object):
163 class rebaseruntime(object):
164 """This class is a container for rebase runtime state"""
164 """This class is a container for rebase runtime state"""
165
165
166 def __init__(self, repo, ui, inmemory=False, opts=None):
166 def __init__(self, repo, ui, inmemory=False, opts=None):
167 if opts is None:
167 if opts is None:
168 opts = {}
168 opts = {}
169
169
170 # prepared: whether we have rebasestate prepared or not. Currently it
170 # prepared: whether we have rebasestate prepared or not. Currently it
171 # decides whether "self.repo" is unfiltered or not.
171 # decides whether "self.repo" is unfiltered or not.
172 # The rebasestate has explicit hash to hash instructions not depending
172 # The rebasestate has explicit hash to hash instructions not depending
173 # on visibility. If rebasestate exists (in-memory or on-disk), use
173 # on visibility. If rebasestate exists (in-memory or on-disk), use
174 # unfiltered repo to avoid visibility issues.
174 # unfiltered repo to avoid visibility issues.
175 # Before knowing rebasestate (i.e. when starting a new rebase (not
175 # Before knowing rebasestate (i.e. when starting a new rebase (not
176 # --continue or --abort)), the original repo should be used so
176 # --continue or --abort)), the original repo should be used so
177 # visibility-dependent revsets are correct.
177 # visibility-dependent revsets are correct.
178 self.prepared = False
178 self.prepared = False
179 self._repo = repo
179 self._repo = repo
180
180
181 self.ui = ui
181 self.ui = ui
182 self.opts = opts
182 self.opts = opts
183 self.originalwd = None
183 self.originalwd = None
184 self.external = nullrev
184 self.external = nullrev
185 # Mapping between the old revision id and either what is the new rebased
185 # Mapping between the old revision id and either what is the new rebased
186 # revision or what needs to be done with the old revision. The state
186 # revision or what needs to be done with the old revision. The state
187 # dict will be what contains most of the rebase progress state.
187 # dict will be what contains most of the rebase progress state.
188 self.state = {}
188 self.state = {}
189 self.activebookmark = None
189 self.activebookmark = None
190 self.destmap = {}
190 self.destmap = {}
191 self.skipped = set()
191 self.skipped = set()
192
192
193 self.collapsef = opts.get(b'collapse', False)
193 self.collapsef = opts.get(b'collapse', False)
194 self.collapsemsg = cmdutil.logmessage(ui, opts)
194 self.collapsemsg = cmdutil.logmessage(ui, opts)
195 self.date = opts.get(b'date', None)
195 self.date = opts.get(b'date', None)
196
196
197 e = opts.get(b'extrafn') # internal, used by e.g. hgsubversion
197 e = opts.get(b'extrafn') # internal, used by e.g. hgsubversion
198 self.extrafns = [_savegraft]
198 self.extrafns = [_savegraft]
199 if e:
199 if e:
200 self.extrafns = [e]
200 self.extrafns = [e]
201
201
202 self.backupf = ui.configbool(b'rewrite', b'backup-bundle')
202 self.backupf = ui.configbool(b'rewrite', b'backup-bundle')
203 self.keepf = opts.get(b'keep', False)
203 self.keepf = opts.get(b'keep', False)
204 self.keepbranchesf = opts.get(b'keepbranches', False)
204 self.keepbranchesf = opts.get(b'keepbranches', False)
205 self.obsoletenotrebased = {}
205 self.obsoletenotrebased = {}
206 self.obsoletewithoutsuccessorindestination = set()
206 self.obsoletewithoutsuccessorindestination = set()
207 self.inmemory = inmemory
207 self.inmemory = inmemory
208 self.stateobj = statemod.cmdstate(repo, b'rebasestate')
208 self.stateobj = statemod.cmdstate(repo, b'rebasestate')
209
209
210 @property
210 @property
211 def repo(self):
211 def repo(self):
212 if self.prepared:
212 if self.prepared:
213 return self._repo.unfiltered()
213 return self._repo.unfiltered()
214 else:
214 else:
215 return self._repo
215 return self._repo
216
216
217 def storestatus(self, tr=None):
217 def storestatus(self, tr=None):
218 """Store the current status to allow recovery"""
218 """Store the current status to allow recovery"""
219 if tr:
219 if tr:
220 tr.addfilegenerator(
220 tr.addfilegenerator(
221 b'rebasestate',
221 b'rebasestate',
222 (b'rebasestate',),
222 (b'rebasestate',),
223 self._writestatus,
223 self._writestatus,
224 location=b'plain',
224 location=b'plain',
225 )
225 )
226 else:
226 else:
227 with self.repo.vfs(b"rebasestate", b"w") as f:
227 with self.repo.vfs(b"rebasestate", b"w") as f:
228 self._writestatus(f)
228 self._writestatus(f)
229
229
230 def _writestatus(self, f):
230 def _writestatus(self, f):
231 repo = self.repo
231 repo = self.repo
232 assert repo.filtername is None
232 assert repo.filtername is None
233 f.write(repo[self.originalwd].hex() + b'\n')
233 f.write(repo[self.originalwd].hex() + b'\n')
234 # was "dest". we now write dest per src root below.
234 # was "dest". we now write dest per src root below.
235 f.write(b'\n')
235 f.write(b'\n')
236 f.write(repo[self.external].hex() + b'\n')
236 f.write(repo[self.external].hex() + b'\n')
237 f.write(b'%d\n' % int(self.collapsef))
237 f.write(b'%d\n' % int(self.collapsef))
238 f.write(b'%d\n' % int(self.keepf))
238 f.write(b'%d\n' % int(self.keepf))
239 f.write(b'%d\n' % int(self.keepbranchesf))
239 f.write(b'%d\n' % int(self.keepbranchesf))
240 f.write(b'%s\n' % (self.activebookmark or b''))
240 f.write(b'%s\n' % (self.activebookmark or b''))
241 destmap = self.destmap
241 destmap = self.destmap
242 for d, v in pycompat.iteritems(self.state):
242 for d, v in pycompat.iteritems(self.state):
243 oldrev = repo[d].hex()
243 oldrev = repo[d].hex()
244 if v >= 0:
244 if v >= 0:
245 newrev = repo[v].hex()
245 newrev = repo[v].hex()
246 else:
246 else:
247 newrev = b"%d" % v
247 newrev = b"%d" % v
248 destnode = repo[destmap[d]].hex()
248 destnode = repo[destmap[d]].hex()
249 f.write(b"%s:%s:%s\n" % (oldrev, newrev, destnode))
249 f.write(b"%s:%s:%s\n" % (oldrev, newrev, destnode))
250 repo.ui.debug(b'rebase status stored\n')
250 repo.ui.debug(b'rebase status stored\n')
251
251
252 def restorestatus(self):
252 def restorestatus(self):
253 """Restore a previously stored status"""
253 """Restore a previously stored status"""
254 if not self.stateobj.exists():
254 if not self.stateobj.exists():
255 cmdutil.wrongtooltocontinue(self.repo, _(b'rebase'))
255 cmdutil.wrongtooltocontinue(self.repo, _(b'rebase'))
256
256
257 data = self._read()
257 data = self._read()
258 self.repo.ui.debug(b'rebase status resumed\n')
258 self.repo.ui.debug(b'rebase status resumed\n')
259
259
260 self.originalwd = data[b'originalwd']
260 self.originalwd = data[b'originalwd']
261 self.destmap = data[b'destmap']
261 self.destmap = data[b'destmap']
262 self.state = data[b'state']
262 self.state = data[b'state']
263 self.skipped = data[b'skipped']
263 self.skipped = data[b'skipped']
264 self.collapsef = data[b'collapse']
264 self.collapsef = data[b'collapse']
265 self.keepf = data[b'keep']
265 self.keepf = data[b'keep']
266 self.keepbranchesf = data[b'keepbranches']
266 self.keepbranchesf = data[b'keepbranches']
267 self.external = data[b'external']
267 self.external = data[b'external']
268 self.activebookmark = data[b'activebookmark']
268 self.activebookmark = data[b'activebookmark']
269
269
270 def _read(self):
270 def _read(self):
271 self.prepared = True
271 self.prepared = True
272 repo = self.repo
272 repo = self.repo
273 assert repo.filtername is None
273 assert repo.filtername is None
274 data = {
274 data = {
275 b'keepbranches': None,
275 b'keepbranches': None,
276 b'collapse': None,
276 b'collapse': None,
277 b'activebookmark': None,
277 b'activebookmark': None,
278 b'external': nullrev,
278 b'external': nullrev,
279 b'keep': None,
279 b'keep': None,
280 b'originalwd': None,
280 b'originalwd': None,
281 }
281 }
282 legacydest = None
282 legacydest = None
283 state = {}
283 state = {}
284 destmap = {}
284 destmap = {}
285
285
286 if True:
286 if True:
287 f = repo.vfs(b"rebasestate")
287 f = repo.vfs(b"rebasestate")
288 for i, l in enumerate(f.read().splitlines()):
288 for i, l in enumerate(f.read().splitlines()):
289 if i == 0:
289 if i == 0:
290 data[b'originalwd'] = repo[l].rev()
290 data[b'originalwd'] = repo[l].rev()
291 elif i == 1:
291 elif i == 1:
292 # this line should be empty in newer version. but legacy
292 # this line should be empty in newer version. but legacy
293 # clients may still use it
293 # clients may still use it
294 if l:
294 if l:
295 legacydest = repo[l].rev()
295 legacydest = repo[l].rev()
296 elif i == 2:
296 elif i == 2:
297 data[b'external'] = repo[l].rev()
297 data[b'external'] = repo[l].rev()
298 elif i == 3:
298 elif i == 3:
299 data[b'collapse'] = bool(int(l))
299 data[b'collapse'] = bool(int(l))
300 elif i == 4:
300 elif i == 4:
301 data[b'keep'] = bool(int(l))
301 data[b'keep'] = bool(int(l))
302 elif i == 5:
302 elif i == 5:
303 data[b'keepbranches'] = bool(int(l))
303 data[b'keepbranches'] = bool(int(l))
304 elif i == 6 and not (len(l) == 81 and b':' in l):
304 elif i == 6 and not (len(l) == 81 and b':' in l):
305 # line 6 is a recent addition, so for backwards
305 # line 6 is a recent addition, so for backwards
306 # compatibility check that the line doesn't look like the
306 # compatibility check that the line doesn't look like the
307 # oldrev:newrev lines
307 # oldrev:newrev lines
308 data[b'activebookmark'] = l
308 data[b'activebookmark'] = l
309 else:
309 else:
310 args = l.split(b':')
310 args = l.split(b':')
311 oldrev = repo[args[0]].rev()
311 oldrev = repo[args[0]].rev()
312 newrev = args[1]
312 newrev = args[1]
313 if newrev in legacystates:
313 if newrev in legacystates:
314 continue
314 continue
315 if len(args) > 2:
315 if len(args) > 2:
316 destrev = repo[args[2]].rev()
316 destrev = repo[args[2]].rev()
317 else:
317 else:
318 destrev = legacydest
318 destrev = legacydest
319 destmap[oldrev] = destrev
319 destmap[oldrev] = destrev
320 if newrev == revtodostr:
320 if newrev == revtodostr:
321 state[oldrev] = revtodo
321 state[oldrev] = revtodo
322 # Legacy compat special case
322 # Legacy compat special case
323 else:
323 else:
324 state[oldrev] = repo[newrev].rev()
324 state[oldrev] = repo[newrev].rev()
325
325
326 if data[b'keepbranches'] is None:
326 if data[b'keepbranches'] is None:
327 raise error.Abort(_(b'.hg/rebasestate is incomplete'))
327 raise error.Abort(_(b'.hg/rebasestate is incomplete'))
328
328
329 data[b'destmap'] = destmap
329 data[b'destmap'] = destmap
330 data[b'state'] = state
330 data[b'state'] = state
331 skipped = set()
331 skipped = set()
332 # recompute the set of skipped revs
332 # recompute the set of skipped revs
333 if not data[b'collapse']:
333 if not data[b'collapse']:
334 seen = set(destmap.values())
334 seen = set(destmap.values())
335 for old, new in sorted(state.items()):
335 for old, new in sorted(state.items()):
336 if new != revtodo and new in seen:
336 if new != revtodo and new in seen:
337 skipped.add(old)
337 skipped.add(old)
338 seen.add(new)
338 seen.add(new)
339 data[b'skipped'] = skipped
339 data[b'skipped'] = skipped
340 repo.ui.debug(
340 repo.ui.debug(
341 b'computed skipped revs: %s\n'
341 b'computed skipped revs: %s\n'
342 % (b' '.join(b'%d' % r for r in sorted(skipped)) or b'')
342 % (b' '.join(b'%d' % r for r in sorted(skipped)) or b'')
343 )
343 )
344
344
345 return data
345 return data
346
346
347 def _handleskippingobsolete(self, obsoleterevs, destmap):
347 def _handleskippingobsolete(self, obsoleterevs, destmap):
348 """Compute structures necessary for skipping obsolete revisions
348 """Compute structures necessary for skipping obsolete revisions
349
349
350 obsoleterevs: iterable of all obsolete revisions in rebaseset
350 obsoleterevs: iterable of all obsolete revisions in rebaseset
351 destmap: {srcrev: destrev} destination revisions
351 destmap: {srcrev: destrev} destination revisions
352 """
352 """
353 self.obsoletenotrebased = {}
353 self.obsoletenotrebased = {}
354 if not self.ui.configbool(b'experimental', b'rebaseskipobsolete'):
354 if not self.ui.configbool(b'experimental', b'rebaseskipobsolete'):
355 return
355 return
356 obsoleteset = set(obsoleterevs)
356 obsoleteset = set(obsoleterevs)
357 (
357 (
358 self.obsoletenotrebased,
358 self.obsoletenotrebased,
359 self.obsoletewithoutsuccessorindestination,
359 self.obsoletewithoutsuccessorindestination,
360 obsoleteextinctsuccessors,
360 obsoleteextinctsuccessors,
361 ) = _computeobsoletenotrebased(self.repo, obsoleteset, destmap)
361 ) = _computeobsoletenotrebased(self.repo, obsoleteset, destmap)
362 skippedset = set(self.obsoletenotrebased)
362 skippedset = set(self.obsoletenotrebased)
363 skippedset.update(self.obsoletewithoutsuccessorindestination)
363 skippedset.update(self.obsoletewithoutsuccessorindestination)
364 skippedset.update(obsoleteextinctsuccessors)
364 skippedset.update(obsoleteextinctsuccessors)
365 _checkobsrebase(self.repo, self.ui, obsoleteset, skippedset)
365 _checkobsrebase(self.repo, self.ui, obsoleteset, skippedset)
366
366
367 def _prepareabortorcontinue(self, isabort, backup=True, suppwarns=False):
367 def _prepareabortorcontinue(self, isabort, backup=True, suppwarns=False):
368 try:
368 try:
369 self.restorestatus()
369 self.restorestatus()
370 self.collapsemsg = restorecollapsemsg(self.repo, isabort)
370 self.collapsemsg = restorecollapsemsg(self.repo, isabort)
371 except error.RepoLookupError:
371 except error.RepoLookupError:
372 if isabort:
372 if isabort:
373 clearstatus(self.repo)
373 clearstatus(self.repo)
374 clearcollapsemsg(self.repo)
374 clearcollapsemsg(self.repo)
375 self.repo.ui.warn(
375 self.repo.ui.warn(
376 _(
376 _(
377 b'rebase aborted (no revision is removed,'
377 b'rebase aborted (no revision is removed,'
378 b' only broken state is cleared)\n'
378 b' only broken state is cleared)\n'
379 )
379 )
380 )
380 )
381 return 0
381 return 0
382 else:
382 else:
383 msg = _(b'cannot continue inconsistent rebase')
383 msg = _(b'cannot continue inconsistent rebase')
384 hint = _(b'use "hg rebase --abort" to clear broken state')
384 hint = _(b'use "hg rebase --abort" to clear broken state')
385 raise error.Abort(msg, hint=hint)
385 raise error.Abort(msg, hint=hint)
386
386
387 if isabort:
387 if isabort:
388 backup = backup and self.backupf
388 backup = backup and self.backupf
389 return self._abort(backup=backup, suppwarns=suppwarns)
389 return self._abort(backup=backup, suppwarns=suppwarns)
390
390
391 def _preparenewrebase(self, destmap):
391 def _preparenewrebase(self, destmap):
392 if not destmap:
392 if not destmap:
393 return _nothingtorebase()
393 return _nothingtorebase()
394
394
395 rebaseset = destmap.keys()
395 rebaseset = destmap.keys()
396 allowunstable = obsolete.isenabled(self.repo, obsolete.allowunstableopt)
396 allowunstable = obsolete.isenabled(self.repo, obsolete.allowunstableopt)
397 if not (self.keepf or allowunstable) and self.repo.revs(
397 if not (self.keepf or allowunstable) and self.repo.revs(
398 b'first(children(%ld) - %ld)', rebaseset, rebaseset
398 b'first(children(%ld) - %ld)', rebaseset, rebaseset
399 ):
399 ):
400 raise error.Abort(
400 raise error.Abort(
401 _(
401 _(
402 b"can't remove original changesets with"
402 b"can't remove original changesets with"
403 b" unrebased descendants"
403 b" unrebased descendants"
404 ),
404 ),
405 hint=_(b'use --keep to keep original changesets'),
405 hint=_(b'use --keep to keep original changesets'),
406 )
406 )
407
407
408 result = buildstate(self.repo, destmap, self.collapsef)
408 result = buildstate(self.repo, destmap, self.collapsef)
409
409
410 if not result:
410 if not result:
411 # Empty state built, nothing to rebase
411 # Empty state built, nothing to rebase
412 self.ui.status(_(b'nothing to rebase\n'))
412 self.ui.status(_(b'nothing to rebase\n'))
413 return _nothingtorebase()
413 return _nothingtorebase()
414
414
415 for root in self.repo.set(b'roots(%ld)', rebaseset):
415 for root in self.repo.set(b'roots(%ld)', rebaseset):
416 if not self.keepf and not root.mutable():
416 if not self.keepf and not root.mutable():
417 raise error.Abort(
417 raise error.Abort(
418 _(b"can't rebase public changeset %s") % root,
418 _(b"can't rebase public changeset %s") % root,
419 hint=_(b"see 'hg help phases' for details"),
419 hint=_(b"see 'hg help phases' for details"),
420 )
420 )
421
421
422 (self.originalwd, self.destmap, self.state) = result
422 (self.originalwd, self.destmap, self.state) = result
423 if self.collapsef:
423 if self.collapsef:
424 dests = set(self.destmap.values())
424 dests = set(self.destmap.values())
425 if len(dests) != 1:
425 if len(dests) != 1:
426 raise error.Abort(
426 raise error.Abort(
427 _(b'--collapse does not work with multiple destinations')
427 _(b'--collapse does not work with multiple destinations')
428 )
428 )
429 destrev = next(iter(dests))
429 destrev = next(iter(dests))
430 destancestors = self.repo.changelog.ancestors(
430 destancestors = self.repo.changelog.ancestors(
431 [destrev], inclusive=True
431 [destrev], inclusive=True
432 )
432 )
433 self.external = externalparent(self.repo, self.state, destancestors)
433 self.external = externalparent(self.repo, self.state, destancestors)
434
434
435 for destrev in sorted(set(destmap.values())):
435 for destrev in sorted(set(destmap.values())):
436 dest = self.repo[destrev]
436 dest = self.repo[destrev]
437 if dest.closesbranch() and not self.keepbranchesf:
437 if dest.closesbranch() and not self.keepbranchesf:
438 self.ui.status(_(b'reopening closed branch head %s\n') % dest)
438 self.ui.status(_(b'reopening closed branch head %s\n') % dest)
439
439
440 self.prepared = True
440 self.prepared = True
441
441
442 def _assignworkingcopy(self):
442 def _assignworkingcopy(self):
443 if self.inmemory:
443 if self.inmemory:
444 from mercurial.context import overlayworkingctx
444 from mercurial.context import overlayworkingctx
445
445
446 self.wctx = overlayworkingctx(self.repo)
446 self.wctx = overlayworkingctx(self.repo)
447 self.repo.ui.debug(b"rebasing in-memory\n")
447 self.repo.ui.debug(b"rebasing in-memory\n")
448 else:
448 else:
449 self.wctx = self.repo[None]
449 self.wctx = self.repo[None]
450 self.repo.ui.debug(b"rebasing on disk\n")
450 self.repo.ui.debug(b"rebasing on disk\n")
451 self.repo.ui.log(
451 self.repo.ui.log(
452 b"rebase",
452 b"rebase",
453 b"using in-memory rebase: %r\n",
453 b"using in-memory rebase: %r\n",
454 self.inmemory,
454 self.inmemory,
455 rebase_imm_used=self.inmemory,
455 rebase_imm_used=self.inmemory,
456 )
456 )
457
457
458 def _performrebase(self, tr):
458 def _performrebase(self, tr):
459 self._assignworkingcopy()
459 self._assignworkingcopy()
460 repo, ui = self.repo, self.ui
460 repo, ui = self.repo, self.ui
461 if self.keepbranchesf:
461 if self.keepbranchesf:
462 # insert _savebranch at the start of extrafns so if
462 # insert _savebranch at the start of extrafns so if
463 # there's a user-provided extrafn it can clobber branch if
463 # there's a user-provided extrafn it can clobber branch if
464 # desired
464 # desired
465 self.extrafns.insert(0, _savebranch)
465 self.extrafns.insert(0, _savebranch)
466 if self.collapsef:
466 if self.collapsef:
467 branches = set()
467 branches = set()
468 for rev in self.state:
468 for rev in self.state:
469 branches.add(repo[rev].branch())
469 branches.add(repo[rev].branch())
470 if len(branches) > 1:
470 if len(branches) > 1:
471 raise error.Abort(
471 raise error.Abort(
472 _(b'cannot collapse multiple named branches')
472 _(b'cannot collapse multiple named branches')
473 )
473 )
474
474
475 # Calculate self.obsoletenotrebased
475 # Calculate self.obsoletenotrebased
476 obsrevs = _filterobsoleterevs(self.repo, self.state)
476 obsrevs = _filterobsoleterevs(self.repo, self.state)
477 self._handleskippingobsolete(obsrevs, self.destmap)
477 self._handleskippingobsolete(obsrevs, self.destmap)
478
478
479 # Keep track of the active bookmarks in order to reset them later
479 # Keep track of the active bookmarks in order to reset them later
480 self.activebookmark = self.activebookmark or repo._activebookmark
480 self.activebookmark = self.activebookmark or repo._activebookmark
481 if self.activebookmark:
481 if self.activebookmark:
482 bookmarks.deactivate(repo)
482 bookmarks.deactivate(repo)
483
483
484 # Store the state before we begin so users can run 'hg rebase --abort'
484 # Store the state before we begin so users can run 'hg rebase --abort'
485 # if we fail before the transaction closes.
485 # if we fail before the transaction closes.
486 self.storestatus()
486 self.storestatus()
487 if tr:
487 if tr:
488 # When using single transaction, store state when transaction
488 # When using single transaction, store state when transaction
489 # commits.
489 # commits.
490 self.storestatus(tr)
490 self.storestatus(tr)
491
491
492 cands = [k for k, v in pycompat.iteritems(self.state) if v == revtodo]
492 cands = [k for k, v in pycompat.iteritems(self.state) if v == revtodo]
493 p = repo.ui.makeprogress(
493 p = repo.ui.makeprogress(
494 _(b"rebasing"), unit=_(b'changesets'), total=len(cands)
494 _(b"rebasing"), unit=_(b'changesets'), total=len(cands)
495 )
495 )
496
496
497 def progress(ctx):
497 def progress(ctx):
498 p.increment(item=(b"%d:%s" % (ctx.rev(), ctx)))
498 p.increment(item=(b"%d:%s" % (ctx.rev(), ctx)))
499
499
500 allowdivergence = self.ui.configbool(
500 allowdivergence = self.ui.configbool(
501 b'experimental', b'evolution.allowdivergence'
501 b'experimental', b'evolution.allowdivergence'
502 )
502 )
503 for subset in sortsource(self.destmap):
503 for subset in sortsource(self.destmap):
504 sortedrevs = self.repo.revs(b'sort(%ld, -topo)', subset)
504 sortedrevs = self.repo.revs(b'sort(%ld, -topo)', subset)
505 if not allowdivergence:
505 if not allowdivergence:
506 sortedrevs -= self.repo.revs(
506 sortedrevs -= self.repo.revs(
507 b'descendants(%ld) and not %ld',
507 b'descendants(%ld) and not %ld',
508 self.obsoletewithoutsuccessorindestination,
508 self.obsoletewithoutsuccessorindestination,
509 self.obsoletewithoutsuccessorindestination,
509 self.obsoletewithoutsuccessorindestination,
510 )
510 )
511 for rev in sortedrevs:
511 for rev in sortedrevs:
512 self._rebasenode(tr, rev, allowdivergence, progress)
512 self._rebasenode(tr, rev, allowdivergence, progress)
513 p.complete()
513 p.complete()
514 ui.note(_(b'rebase merging completed\n'))
514 ui.note(_(b'rebase merging completed\n'))
515
515
516 def _concludenode(self, rev, p1, p2, editor, commitmsg=None):
516 def _concludenode(self, rev, p1, p2, editor, commitmsg=None):
517 '''Commit the wd changes with parents p1 and p2.
517 '''Commit the wd changes with parents p1 and p2.
518
518
519 Reuse commit info from rev but also store useful information in extra.
519 Reuse commit info from rev but also store useful information in extra.
520 Return node of committed revision.'''
520 Return node of committed revision.'''
521 repo = self.repo
521 repo = self.repo
522 ctx = repo[rev]
522 ctx = repo[rev]
523 if commitmsg is None:
523 if commitmsg is None:
524 commitmsg = ctx.description()
524 commitmsg = ctx.description()
525 date = self.date
525 date = self.date
526 if date is None:
526 if date is None:
527 date = ctx.date()
527 date = ctx.date()
528 extra = {b'rebase_source': ctx.hex()}
528 extra = {b'rebase_source': ctx.hex()}
529 for c in self.extrafns:
529 for c in self.extrafns:
530 c(ctx, extra)
530 c(ctx, extra)
531 keepbranch = self.keepbranchesf and repo[p1].branch() != ctx.branch()
531 keepbranch = self.keepbranchesf and repo[p1].branch() != ctx.branch()
532 destphase = max(ctx.phase(), phases.draft)
532 destphase = max(ctx.phase(), phases.draft)
533 overrides = {(b'phases', b'new-commit'): destphase}
533 overrides = {(b'phases', b'new-commit'): destphase}
534 if keepbranch:
534 if keepbranch:
535 overrides[(b'ui', b'allowemptycommit')] = True
535 overrides[(b'ui', b'allowemptycommit')] = True
536 with repo.ui.configoverride(overrides, b'rebase'):
536 with repo.ui.configoverride(overrides, b'rebase'):
537 if self.inmemory:
537 if self.inmemory:
538 newnode = commitmemorynode(
538 newnode = commitmemorynode(
539 repo,
539 repo,
540 p1,
540 p1,
541 p2,
541 p2,
542 wctx=self.wctx,
542 wctx=self.wctx,
543 extra=extra,
543 extra=extra,
544 commitmsg=commitmsg,
544 commitmsg=commitmsg,
545 editor=editor,
545 editor=editor,
546 user=ctx.user(),
546 user=ctx.user(),
547 date=date,
547 date=date,
548 )
548 )
549 mergemod.mergestate.clean(repo)
549 mergemod.mergestate.clean(repo)
550 else:
550 else:
551 newnode = commitnode(
551 newnode = commitnode(
552 repo,
552 repo,
553 p1,
553 p1,
554 p2,
554 p2,
555 extra=extra,
555 extra=extra,
556 commitmsg=commitmsg,
556 commitmsg=commitmsg,
557 editor=editor,
557 editor=editor,
558 user=ctx.user(),
558 user=ctx.user(),
559 date=date,
559 date=date,
560 )
560 )
561
561
562 if newnode is None:
562 if newnode is None:
563 # If it ended up being a no-op commit, then the normal
563 # If it ended up being a no-op commit, then the normal
564 # merge state clean-up path doesn't happen, so do it
564 # merge state clean-up path doesn't happen, so do it
565 # here. Fix issue5494
565 # here. Fix issue5494
566 mergemod.mergestate.clean(repo)
566 mergemod.mergestate.clean(repo)
567 return newnode
567 return newnode
568
568
569 def _rebasenode(self, tr, rev, allowdivergence, progressfn):
569 def _rebasenode(self, tr, rev, allowdivergence, progressfn):
570 repo, ui, opts = self.repo, self.ui, self.opts
570 repo, ui, opts = self.repo, self.ui, self.opts
571 dest = self.destmap[rev]
571 dest = self.destmap[rev]
572 ctx = repo[rev]
572 ctx = repo[rev]
573 desc = _ctxdesc(ctx)
573 desc = _ctxdesc(ctx)
574 if self.state[rev] == rev:
574 if self.state[rev] == rev:
575 ui.status(_(b'already rebased %s\n') % desc)
575 ui.status(_(b'already rebased %s\n') % desc)
576 elif (
576 elif (
577 not allowdivergence
577 not allowdivergence
578 and rev in self.obsoletewithoutsuccessorindestination
578 and rev in self.obsoletewithoutsuccessorindestination
579 ):
579 ):
580 msg = (
580 msg = (
581 _(
581 _(
582 b'note: not rebasing %s and its descendants as '
582 b'note: not rebasing %s and its descendants as '
583 b'this would cause divergence\n'
583 b'this would cause divergence\n'
584 )
584 )
585 % desc
585 % desc
586 )
586 )
587 repo.ui.status(msg)
587 repo.ui.status(msg)
588 self.skipped.add(rev)
588 self.skipped.add(rev)
589 elif rev in self.obsoletenotrebased:
589 elif rev in self.obsoletenotrebased:
590 succ = self.obsoletenotrebased[rev]
590 succ = self.obsoletenotrebased[rev]
591 if succ is None:
591 if succ is None:
592 msg = _(b'note: not rebasing %s, it has no successor\n') % desc
592 msg = _(b'note: not rebasing %s, it has no successor\n') % desc
593 else:
593 else:
594 succdesc = _ctxdesc(repo[succ])
594 succdesc = _ctxdesc(repo[succ])
595 msg = _(
595 msg = _(
596 b'note: not rebasing %s, already in destination as %s\n'
596 b'note: not rebasing %s, already in destination as %s\n'
597 ) % (desc, succdesc)
597 ) % (desc, succdesc)
598 repo.ui.status(msg)
598 repo.ui.status(msg)
599 # Make clearrebased aware state[rev] is not a true successor
599 # Make clearrebased aware state[rev] is not a true successor
600 self.skipped.add(rev)
600 self.skipped.add(rev)
601 # Record rev as moved to its desired destination in self.state.
601 # Record rev as moved to its desired destination in self.state.
602 # This helps bookmark and working parent movement.
602 # This helps bookmark and working parent movement.
603 dest = max(
603 dest = max(
604 adjustdest(repo, rev, self.destmap, self.state, self.skipped)
604 adjustdest(repo, rev, self.destmap, self.state, self.skipped)
605 )
605 )
606 self.state[rev] = dest
606 self.state[rev] = dest
607 elif self.state[rev] == revtodo:
607 elif self.state[rev] == revtodo:
608 ui.status(_(b'rebasing %s\n') % desc)
608 ui.status(_(b'rebasing %s\n') % desc)
609 progressfn(ctx)
609 progressfn(ctx)
610 p1, p2, base = defineparents(
610 p1, p2, base = defineparents(
611 repo,
611 repo,
612 rev,
612 rev,
613 self.destmap,
613 self.destmap,
614 self.state,
614 self.state,
615 self.skipped,
615 self.skipped,
616 self.obsoletenotrebased,
616 self.obsoletenotrebased,
617 )
617 )
618 if not self.inmemory and len(repo[None].parents()) == 2:
618 if not self.inmemory and len(repo[None].parents()) == 2:
619 repo.ui.debug(b'resuming interrupted rebase\n')
619 repo.ui.debug(b'resuming interrupted rebase\n')
620 else:
620 else:
621 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
621 overrides = {(b'ui', b'forcemerge'): opts.get(b'tool', b'')}
622 with ui.configoverride(overrides, b'rebase'):
622 with ui.configoverride(overrides, b'rebase'):
623 stats = rebasenode(
623 stats = rebasenode(
624 repo,
624 repo,
625 rev,
625 rev,
626 p1,
626 p1,
627 base,
627 base,
628 self.collapsef,
628 self.collapsef,
629 dest,
629 dest,
630 wctx=self.wctx,
630 wctx=self.wctx,
631 )
631 )
632 if stats.unresolvedcount > 0:
632 if stats.unresolvedcount > 0:
633 if self.inmemory:
633 if self.inmemory:
634 raise error.InMemoryMergeConflictsError()
634 raise error.InMemoryMergeConflictsError()
635 else:
635 else:
636 raise error.InterventionRequired(
636 raise error.InterventionRequired(
637 _(
637 _(
638 b'unresolved conflicts (see hg '
638 b'unresolved conflicts (see hg '
639 b'resolve, then hg rebase --continue)'
639 b'resolve, then hg rebase --continue)'
640 )
640 )
641 )
641 )
642 if not self.collapsef:
642 if not self.collapsef:
643 merging = p2 != nullrev
643 merging = p2 != nullrev
644 editform = cmdutil.mergeeditform(merging, b'rebase')
644 editform = cmdutil.mergeeditform(merging, b'rebase')
645 editor = cmdutil.getcommiteditor(
645 editor = cmdutil.getcommiteditor(
646 editform=editform, **pycompat.strkwargs(opts)
646 editform=editform, **pycompat.strkwargs(opts)
647 )
647 )
648 newnode = self._concludenode(rev, p1, p2, editor)
648 newnode = self._concludenode(rev, p1, p2, editor)
649 else:
649 else:
650 # Skip commit if we are collapsing
650 # Skip commit if we are collapsing
651 if self.inmemory:
651 if self.inmemory:
652 self.wctx.setbase(repo[p1])
652 self.wctx.setbase(repo[p1])
653 else:
653 else:
654 repo.setparents(repo[p1].node())
654 repo.setparents(repo[p1].node())
655 newnode = None
655 newnode = None
656 # Update the state
656 # Update the state
657 if newnode is not None:
657 if newnode is not None:
658 self.state[rev] = repo[newnode].rev()
658 self.state[rev] = repo[newnode].rev()
659 ui.debug(b'rebased as %s\n' % short(newnode))
659 ui.debug(b'rebased as %s\n' % short(newnode))
660 else:
660 else:
661 if not self.collapsef:
661 if not self.collapsef:
662 ui.warn(
662 ui.warn(
663 _(
663 _(
664 b'note: not rebasing %s, its destination already '
664 b'note: not rebasing %s, its destination already '
665 b'has all its changes\n'
665 b'has all its changes\n'
666 )
666 )
667 % desc
667 % desc
668 )
668 )
669 self.skipped.add(rev)
669 self.skipped.add(rev)
670 self.state[rev] = p1
670 self.state[rev] = p1
671 ui.debug(b'next revision set to %d\n' % p1)
671 ui.debug(b'next revision set to %d\n' % p1)
672 else:
672 else:
673 ui.status(
673 ui.status(
674 _(b'already rebased %s as %s\n') % (desc, repo[self.state[rev]])
674 _(b'already rebased %s as %s\n') % (desc, repo[self.state[rev]])
675 )
675 )
676 if not tr:
676 if not tr:
677 # When not using single transaction, store state after each
677 # When not using single transaction, store state after each
678 # commit is completely done. On InterventionRequired, we thus
678 # commit is completely done. On InterventionRequired, we thus
679 # won't store the status. Instead, we'll hit the "len(parents) == 2"
679 # won't store the status. Instead, we'll hit the "len(parents) == 2"
680 # case and realize that the commit was in progress.
680 # case and realize that the commit was in progress.
681 self.storestatus()
681 self.storestatus()
682
682
683 def _finishrebase(self):
683 def _finishrebase(self):
684 repo, ui, opts = self.repo, self.ui, self.opts
684 repo, ui, opts = self.repo, self.ui, self.opts
685 fm = ui.formatter(b'rebase', opts)
685 fm = ui.formatter(b'rebase', opts)
686 fm.startitem()
686 fm.startitem()
687 if self.collapsef:
687 if self.collapsef:
688 p1, p2, _base = defineparents(
688 p1, p2, _base = defineparents(
689 repo,
689 repo,
690 min(self.state),
690 min(self.state),
691 self.destmap,
691 self.destmap,
692 self.state,
692 self.state,
693 self.skipped,
693 self.skipped,
694 self.obsoletenotrebased,
694 self.obsoletenotrebased,
695 )
695 )
696 editopt = opts.get(b'edit')
696 editopt = opts.get(b'edit')
697 editform = b'rebase.collapse'
697 editform = b'rebase.collapse'
698 if self.collapsemsg:
698 if self.collapsemsg:
699 commitmsg = self.collapsemsg
699 commitmsg = self.collapsemsg
700 else:
700 else:
701 commitmsg = b'Collapsed revision'
701 commitmsg = b'Collapsed revision'
702 for rebased in sorted(self.state):
702 for rebased in sorted(self.state):
703 if rebased not in self.skipped:
703 if rebased not in self.skipped:
704 commitmsg += b'\n* %s' % repo[rebased].description()
704 commitmsg += b'\n* %s' % repo[rebased].description()
705 editopt = True
705 editopt = True
706 editor = cmdutil.getcommiteditor(edit=editopt, editform=editform)
706 editor = cmdutil.getcommiteditor(edit=editopt, editform=editform)
707 revtoreuse = max(self.state)
707 revtoreuse = max(self.state)
708
708
709 newnode = self._concludenode(
709 newnode = self._concludenode(
710 revtoreuse, p1, self.external, editor, commitmsg=commitmsg
710 revtoreuse, p1, self.external, editor, commitmsg=commitmsg
711 )
711 )
712
712
713 if newnode is not None:
713 if newnode is not None:
714 newrev = repo[newnode].rev()
714 newrev = repo[newnode].rev()
715 for oldrev in self.state:
715 for oldrev in self.state:
716 self.state[oldrev] = newrev
716 self.state[oldrev] = newrev
717
717
718 if b'qtip' in repo.tags():
718 if b'qtip' in repo.tags():
719 updatemq(repo, self.state, self.skipped, **pycompat.strkwargs(opts))
719 updatemq(repo, self.state, self.skipped, **pycompat.strkwargs(opts))
720
720
721 # restore original working directory
721 # restore original working directory
722 # (we do this before stripping)
722 # (we do this before stripping)
723 newwd = self.state.get(self.originalwd, self.originalwd)
723 newwd = self.state.get(self.originalwd, self.originalwd)
724 if newwd < 0:
724 if newwd < 0:
725 # original directory is a parent of rebase set root or ignored
725 # original directory is a parent of rebase set root or ignored
726 newwd = self.originalwd
726 newwd = self.originalwd
727 if newwd not in [c.rev() for c in repo[None].parents()]:
727 if newwd not in [c.rev() for c in repo[None].parents()]:
728 ui.note(_(b"update back to initial working directory parent\n"))
728 ui.note(_(b"update back to initial working directory parent\n"))
729 hg.updaterepo(repo, newwd, overwrite=False)
729 hg.updaterepo(repo, newwd, overwrite=False)
730
730
731 collapsedas = None
731 collapsedas = None
732 if self.collapsef and not self.keepf:
732 if self.collapsef and not self.keepf:
733 collapsedas = newnode
733 collapsedas = newnode
734 clearrebased(
734 clearrebased(
735 ui,
735 ui,
736 repo,
736 repo,
737 self.destmap,
737 self.destmap,
738 self.state,
738 self.state,
739 self.skipped,
739 self.skipped,
740 collapsedas,
740 collapsedas,
741 self.keepf,
741 self.keepf,
742 fm=fm,
742 fm=fm,
743 backup=self.backupf,
743 backup=self.backupf,
744 )
744 )
745
745
746 clearstatus(repo)
746 clearstatus(repo)
747 clearcollapsemsg(repo)
747 clearcollapsemsg(repo)
748
748
749 ui.note(_(b"rebase completed\n"))
749 ui.note(_(b"rebase completed\n"))
750 util.unlinkpath(repo.sjoin(b'undo'), ignoremissing=True)
750 util.unlinkpath(repo.sjoin(b'undo'), ignoremissing=True)
751 if self.skipped:
751 if self.skipped:
752 skippedlen = len(self.skipped)
752 skippedlen = len(self.skipped)
753 ui.note(_(b"%d revisions have been skipped\n") % skippedlen)
753 ui.note(_(b"%d revisions have been skipped\n") % skippedlen)
754 fm.end()
754 fm.end()
755
755
756 if (
756 if (
757 self.activebookmark
757 self.activebookmark
758 and self.activebookmark in repo._bookmarks
758 and self.activebookmark in repo._bookmarks
759 and repo[b'.'].node() == repo._bookmarks[self.activebookmark]
759 and repo[b'.'].node() == repo._bookmarks[self.activebookmark]
760 ):
760 ):
761 bookmarks.activate(repo, self.activebookmark)
761 bookmarks.activate(repo, self.activebookmark)
762
762
763 def _abort(self, backup=True, suppwarns=False):
763 def _abort(self, backup=True, suppwarns=False):
764 '''Restore the repository to its original state.'''
764 '''Restore the repository to its original state.'''
765
765
766 repo = self.repo
766 repo = self.repo
767 try:
767 try:
768 # If the first commits in the rebased set get skipped during the
768 # If the first commits in the rebased set get skipped during the
769 # rebase, their values within the state mapping will be the dest
769 # rebase, their values within the state mapping will be the dest
770 # rev id. The rebased list must must not contain the dest rev
770 # rev id. The rebased list must must not contain the dest rev
771 # (issue4896)
771 # (issue4896)
772 rebased = [
772 rebased = [
773 s
773 s
774 for r, s in self.state.items()
774 for r, s in self.state.items()
775 if s >= 0 and s != r and s != self.destmap[r]
775 if s >= 0 and s != r and s != self.destmap[r]
776 ]
776 ]
777 immutable = [d for d in rebased if not repo[d].mutable()]
777 immutable = [d for d in rebased if not repo[d].mutable()]
778 cleanup = True
778 cleanup = True
779 if immutable:
779 if immutable:
780 repo.ui.warn(
780 repo.ui.warn(
781 _(b"warning: can't clean up public changesets %s\n")
781 _(b"warning: can't clean up public changesets %s\n")
782 % b', '.join(bytes(repo[r]) for r in immutable),
782 % b', '.join(bytes(repo[r]) for r in immutable),
783 hint=_(b"see 'hg help phases' for details"),
783 hint=_(b"see 'hg help phases' for details"),
784 )
784 )
785 cleanup = False
785 cleanup = False
786
786
787 descendants = set()
787 descendants = set()
788 if rebased:
788 if rebased:
789 descendants = set(repo.changelog.descendants(rebased))
789 descendants = set(repo.changelog.descendants(rebased))
790 if descendants - set(rebased):
790 if descendants - set(rebased):
791 repo.ui.warn(
791 repo.ui.warn(
792 _(
792 _(
793 b"warning: new changesets detected on "
793 b"warning: new changesets detected on "
794 b"destination branch, can't strip\n"
794 b"destination branch, can't strip\n"
795 )
795 )
796 )
796 )
797 cleanup = False
797 cleanup = False
798
798
799 if cleanup:
799 if cleanup:
800 shouldupdate = False
800 shouldupdate = False
801 if rebased:
801 if rebased:
802 strippoints = [
802 strippoints = [
803 c.node() for c in repo.set(b'roots(%ld)', rebased)
803 c.node() for c in repo.set(b'roots(%ld)', rebased)
804 ]
804 ]
805
805
806 updateifonnodes = set(rebased)
806 updateifonnodes = set(rebased)
807 updateifonnodes.update(self.destmap.values())
807 updateifonnodes.update(self.destmap.values())
808 updateifonnodes.add(self.originalwd)
808 updateifonnodes.add(self.originalwd)
809 shouldupdate = repo[b'.'].rev() in updateifonnodes
809 shouldupdate = repo[b'.'].rev() in updateifonnodes
810
810
811 # Update away from the rebase if necessary
811 # Update away from the rebase if necessary
812 if shouldupdate or needupdate(repo, self.state):
812 if shouldupdate or needupdate(repo, self.state):
813 mergemod.update(
813 mergemod.update(
814 repo, self.originalwd, branchmerge=False, force=True
814 repo, self.originalwd, branchmerge=False, force=True
815 )
815 )
816
816
817 # Strip from the first rebased revision
817 # Strip from the first rebased revision
818 if rebased:
818 if rebased:
819 repair.strip(repo.ui, repo, strippoints, backup=backup)
819 repair.strip(repo.ui, repo, strippoints, backup=backup)
820
820
821 if self.activebookmark and self.activebookmark in repo._bookmarks:
821 if self.activebookmark and self.activebookmark in repo._bookmarks:
822 bookmarks.activate(repo, self.activebookmark)
822 bookmarks.activate(repo, self.activebookmark)
823
823
824 finally:
824 finally:
825 clearstatus(repo)
825 clearstatus(repo)
826 clearcollapsemsg(repo)
826 clearcollapsemsg(repo)
827 if not suppwarns:
827 if not suppwarns:
828 repo.ui.warn(_(b'rebase aborted\n'))
828 repo.ui.warn(_(b'rebase aborted\n'))
829 return 0
829 return 0
830
830
831
831
832 @command(
832 @command(
833 b'rebase',
833 b'rebase',
834 [
834 [
835 (
835 (
836 b's',
836 b's',
837 b'source',
837 b'source',
838 b'',
838 b'',
839 _(b'rebase the specified changeset and descendants'),
839 _(b'rebase the specified changeset and descendants'),
840 _(b'REV'),
840 _(b'REV'),
841 ),
841 ),
842 (
842 (
843 b'b',
843 b'b',
844 b'base',
844 b'base',
845 b'',
845 b'',
846 _(b'rebase everything from branching point of specified changeset'),
846 _(b'rebase everything from branching point of specified changeset'),
847 _(b'REV'),
847 _(b'REV'),
848 ),
848 ),
849 (b'r', b'rev', [], _(b'rebase these revisions'), _(b'REV')),
849 (b'r', b'rev', [], _(b'rebase these revisions'), _(b'REV')),
850 (
850 (
851 b'd',
851 b'd',
852 b'dest',
852 b'dest',
853 b'',
853 b'',
854 _(b'rebase onto the specified changeset'),
854 _(b'rebase onto the specified changeset'),
855 _(b'REV'),
855 _(b'REV'),
856 ),
856 ),
857 (b'', b'collapse', False, _(b'collapse the rebased changesets')),
857 (b'', b'collapse', False, _(b'collapse the rebased changesets')),
858 (
858 (
859 b'm',
859 b'm',
860 b'message',
860 b'message',
861 b'',
861 b'',
862 _(b'use text as collapse commit message'),
862 _(b'use text as collapse commit message'),
863 _(b'TEXT'),
863 _(b'TEXT'),
864 ),
864 ),
865 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
865 (b'e', b'edit', False, _(b'invoke editor on commit messages')),
866 (
866 (
867 b'l',
867 b'l',
868 b'logfile',
868 b'logfile',
869 b'',
869 b'',
870 _(b'read collapse commit message from file'),
870 _(b'read collapse commit message from file'),
871 _(b'FILE'),
871 _(b'FILE'),
872 ),
872 ),
873 (b'k', b'keep', False, _(b'keep original changesets')),
873 (b'k', b'keep', False, _(b'keep original changesets')),
874 (b'', b'keepbranches', False, _(b'keep original branch names')),
874 (b'', b'keepbranches', False, _(b'keep original branch names')),
875 (b'D', b'detach', False, _(b'(DEPRECATED)')),
875 (b'D', b'detach', False, _(b'(DEPRECATED)')),
876 (b'i', b'interactive', False, _(b'(DEPRECATED)')),
876 (b'i', b'interactive', False, _(b'(DEPRECATED)')),
877 (b't', b'tool', b'', _(b'specify merge tool')),
877 (b't', b'tool', b'', _(b'specify merge tool')),
878 (b'', b'stop', False, _(b'stop interrupted rebase')),
878 (b'', b'stop', False, _(b'stop interrupted rebase')),
879 (b'c', b'continue', False, _(b'continue an interrupted rebase')),
879 (b'c', b'continue', False, _(b'continue an interrupted rebase')),
880 (b'a', b'abort', False, _(b'abort an interrupted rebase')),
880 (b'a', b'abort', False, _(b'abort an interrupted rebase')),
881 (
881 (
882 b'',
882 b'',
883 b'auto-orphans',
883 b'auto-orphans',
884 b'',
884 b'',
885 _(
885 _(
886 b'automatically rebase orphan revisions '
886 b'automatically rebase orphan revisions '
887 b'in the specified revset (EXPERIMENTAL)'
887 b'in the specified revset (EXPERIMENTAL)'
888 ),
888 ),
889 ),
889 ),
890 ]
890 ]
891 + cmdutil.dryrunopts
891 + cmdutil.dryrunopts
892 + cmdutil.formatteropts
892 + cmdutil.formatteropts
893 + cmdutil.confirmopts,
893 + cmdutil.confirmopts,
894 _(b'[-s REV | -b REV] [-d REV] [OPTION]'),
894 _(b'[-s REV | -b REV] [-d REV] [OPTION]'),
895 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
895 helpcategory=command.CATEGORY_CHANGE_MANAGEMENT,
896 )
896 )
897 def rebase(ui, repo, **opts):
897 def rebase(ui, repo, **opts):
898 """move changeset (and descendants) to a different branch
898 """move changeset (and descendants) to a different branch
899
899
900 Rebase uses repeated merging to graft changesets from one part of
900 Rebase uses repeated merging to graft changesets from one part of
901 history (the source) onto another (the destination). This can be
901 history (the source) onto another (the destination). This can be
902 useful for linearizing *local* changes relative to a master
902 useful for linearizing *local* changes relative to a master
903 development tree.
903 development tree.
904
904
905 Published commits cannot be rebased (see :hg:`help phases`).
905 Published commits cannot be rebased (see :hg:`help phases`).
906 To copy commits, see :hg:`help graft`.
906 To copy commits, see :hg:`help graft`.
907
907
908 If you don't specify a destination changeset (``-d/--dest``), rebase
908 If you don't specify a destination changeset (``-d/--dest``), rebase
909 will use the same logic as :hg:`merge` to pick a destination. if
909 will use the same logic as :hg:`merge` to pick a destination. if
910 the current branch contains exactly one other head, the other head
910 the current branch contains exactly one other head, the other head
911 is merged with by default. Otherwise, an explicit revision with
911 is merged with by default. Otherwise, an explicit revision with
912 which to merge with must be provided. (destination changeset is not
912 which to merge with must be provided. (destination changeset is not
913 modified by rebasing, but new changesets are added as its
913 modified by rebasing, but new changesets are added as its
914 descendants.)
914 descendants.)
915
915
916 Here are the ways to select changesets:
916 Here are the ways to select changesets:
917
917
918 1. Explicitly select them using ``--rev``.
918 1. Explicitly select them using ``--rev``.
919
919
920 2. Use ``--source`` to select a root changeset and include all of its
920 2. Use ``--source`` to select a root changeset and include all of its
921 descendants.
921 descendants.
922
922
923 3. Use ``--base`` to select a changeset; rebase will find ancestors
923 3. Use ``--base`` to select a changeset; rebase will find ancestors
924 and their descendants which are not also ancestors of the destination.
924 and their descendants which are not also ancestors of the destination.
925
925
926 4. If you do not specify any of ``--rev``, ``--source``, or ``--base``,
926 4. If you do not specify any of ``--rev``, ``--source``, or ``--base``,
927 rebase will use ``--base .`` as above.
927 rebase will use ``--base .`` as above.
928
928
929 If ``--source`` or ``--rev`` is used, special names ``SRC`` and ``ALLSRC``
929 If ``--source`` or ``--rev`` is used, special names ``SRC`` and ``ALLSRC``
930 can be used in ``--dest``. Destination would be calculated per source
930 can be used in ``--dest``. Destination would be calculated per source
931 revision with ``SRC`` substituted by that single source revision and
931 revision with ``SRC`` substituted by that single source revision and
932 ``ALLSRC`` substituted by all source revisions.
932 ``ALLSRC`` substituted by all source revisions.
933
933
934 Rebase will destroy original changesets unless you use ``--keep``.
934 Rebase will destroy original changesets unless you use ``--keep``.
935 It will also move your bookmarks (even if you do).
935 It will also move your bookmarks (even if you do).
936
936
937 Some changesets may be dropped if they do not contribute changes
937 Some changesets may be dropped if they do not contribute changes
938 (e.g. merges from the destination branch).
938 (e.g. merges from the destination branch).
939
939
940 Unlike ``merge``, rebase will do nothing if you are at the branch tip of
940 Unlike ``merge``, rebase will do nothing if you are at the branch tip of
941 a named branch with two heads. You will need to explicitly specify source
941 a named branch with two heads. You will need to explicitly specify source
942 and/or destination.
942 and/or destination.
943
943
944 If you need to use a tool to automate merge/conflict decisions, you
944 If you need to use a tool to automate merge/conflict decisions, you
945 can specify one with ``--tool``, see :hg:`help merge-tools`.
945 can specify one with ``--tool``, see :hg:`help merge-tools`.
946 As a caveat: the tool will not be used to mediate when a file was
946 As a caveat: the tool will not be used to mediate when a file was
947 deleted, there is no hook presently available for this.
947 deleted, there is no hook presently available for this.
948
948
949 If a rebase is interrupted to manually resolve a conflict, it can be
949 If a rebase is interrupted to manually resolve a conflict, it can be
950 continued with --continue/-c, aborted with --abort/-a, or stopped with
950 continued with --continue/-c, aborted with --abort/-a, or stopped with
951 --stop.
951 --stop.
952
952
953 .. container:: verbose
953 .. container:: verbose
954
954
955 Examples:
955 Examples:
956
956
957 - move "local changes" (current commit back to branching point)
957 - move "local changes" (current commit back to branching point)
958 to the current branch tip after a pull::
958 to the current branch tip after a pull::
959
959
960 hg rebase
960 hg rebase
961
961
962 - move a single changeset to the stable branch::
962 - move a single changeset to the stable branch::
963
963
964 hg rebase -r 5f493448 -d stable
964 hg rebase -r 5f493448 -d stable
965
965
966 - splice a commit and all its descendants onto another part of history::
966 - splice a commit and all its descendants onto another part of history::
967
967
968 hg rebase --source c0c3 --dest 4cf9
968 hg rebase --source c0c3 --dest 4cf9
969
969
970 - rebase everything on a branch marked by a bookmark onto the
970 - rebase everything on a branch marked by a bookmark onto the
971 default branch::
971 default branch::
972
972
973 hg rebase --base myfeature --dest default
973 hg rebase --base myfeature --dest default
974
974
975 - collapse a sequence of changes into a single commit::
975 - collapse a sequence of changes into a single commit::
976
976
977 hg rebase --collapse -r 1520:1525 -d .
977 hg rebase --collapse -r 1520:1525 -d .
978
978
979 - move a named branch while preserving its name::
979 - move a named branch while preserving its name::
980
980
981 hg rebase -r "branch(featureX)" -d 1.3 --keepbranches
981 hg rebase -r "branch(featureX)" -d 1.3 --keepbranches
982
982
983 - stabilize orphaned changesets so history looks linear::
983 - stabilize orphaned changesets so history looks linear::
984
984
985 hg rebase -r 'orphan()-obsolete()'\
985 hg rebase -r 'orphan()-obsolete()'\
986 -d 'first(max((successors(max(roots(ALLSRC) & ::SRC)^)-obsolete())::) +\
986 -d 'first(max((successors(max(roots(ALLSRC) & ::SRC)^)-obsolete())::) +\
987 max(::((roots(ALLSRC) & ::SRC)^)-obsolete()))'
987 max(::((roots(ALLSRC) & ::SRC)^)-obsolete()))'
988
988
989 Configuration Options:
989 Configuration Options:
990
990
991 You can make rebase require a destination if you set the following config
991 You can make rebase require a destination if you set the following config
992 option::
992 option::
993
993
994 [commands]
994 [commands]
995 rebase.requiredest = True
995 rebase.requiredest = True
996
996
997 By default, rebase will close the transaction after each commit. For
997 By default, rebase will close the transaction after each commit. For
998 performance purposes, you can configure rebase to use a single transaction
998 performance purposes, you can configure rebase to use a single transaction
999 across the entire rebase. WARNING: This setting introduces a significant
999 across the entire rebase. WARNING: This setting introduces a significant
1000 risk of losing the work you've done in a rebase if the rebase aborts
1000 risk of losing the work you've done in a rebase if the rebase aborts
1001 unexpectedly::
1001 unexpectedly::
1002
1002
1003 [rebase]
1003 [rebase]
1004 singletransaction = True
1004 singletransaction = True
1005
1005
1006 By default, rebase writes to the working copy, but you can configure it to
1006 By default, rebase writes to the working copy, but you can configure it to
1007 run in-memory for better performance. When the rebase is not moving the
1007 run in-memory for better performance. When the rebase is not moving the
1008 parent(s) of the working copy (AKA the "currently checked out changesets"),
1008 parent(s) of the working copy (AKA the "currently checked out changesets"),
1009 this may also allow it to run even if the working copy is dirty::
1009 this may also allow it to run even if the working copy is dirty::
1010
1010
1011 [rebase]
1011 [rebase]
1012 experimental.inmemory = True
1012 experimental.inmemory = True
1013
1013
1014 Return Values:
1014 Return Values:
1015
1015
1016 Returns 0 on success, 1 if nothing to rebase or there are
1016 Returns 0 on success, 1 if nothing to rebase or there are
1017 unresolved conflicts.
1017 unresolved conflicts.
1018
1018
1019 """
1019 """
1020 opts = pycompat.byteskwargs(opts)
1020 opts = pycompat.byteskwargs(opts)
1021 inmemory = ui.configbool(b'rebase', b'experimental.inmemory')
1021 inmemory = ui.configbool(b'rebase', b'experimental.inmemory')
1022 dryrun = opts.get(b'dry_run')
1022 dryrun = opts.get(b'dry_run')
1023 confirm = opts.get(b'confirm')
1023 confirm = opts.get(b'confirm')
1024 action = cmdutil.check_at_most_one_arg(opts, b'abort', b'stop', b'continue')
1024 action = cmdutil.check_at_most_one_arg(opts, b'abort', b'stop', b'continue')
1025 if dryrun and action:
1025 if action:
1026 raise error.Abort(_(b'cannot specify both --dry-run and --%s') % action)
1026 cmdutil.check_incompatible_arguments(
1027 if confirm and action:
1027 opts, action, b'confirm', b'dry_run'
1028 raise error.Abort(_(b'cannot specify both --confirm and --%s') % action)
1028 )
1029 cmdutil.check_at_most_one_arg(opts, b'confirm', b'dry_run')
1029 cmdutil.check_at_most_one_arg(opts, b'confirm', b'dry_run')
1030
1030
1031 if action or repo.currenttransaction() is not None:
1031 if action or repo.currenttransaction() is not None:
1032 # in-memory rebase is not compatible with resuming rebases.
1032 # in-memory rebase is not compatible with resuming rebases.
1033 # (Or if it is run within a transaction, since the restart logic can
1033 # (Or if it is run within a transaction, since the restart logic can
1034 # fail the entire transaction.)
1034 # fail the entire transaction.)
1035 inmemory = False
1035 inmemory = False
1036
1036
1037 if opts.get(b'auto_orphans'):
1037 if opts.get(b'auto_orphans'):
1038 for key in opts:
1038 for key in opts:
1039 if key != b'auto_orphans' and opts.get(key):
1039 if key != b'auto_orphans' and opts.get(key):
1040 raise error.Abort(
1040 raise error.Abort(
1041 _(b'--auto-orphans is incompatible with %s') % (b'--' + key)
1041 _(b'--auto-orphans is incompatible with %s') % (b'--' + key)
1042 )
1042 )
1043 userrevs = list(repo.revs(opts.get(b'auto_orphans')))
1043 userrevs = list(repo.revs(opts.get(b'auto_orphans')))
1044 opts[b'rev'] = [revsetlang.formatspec(b'%ld and orphan()', userrevs)]
1044 opts[b'rev'] = [revsetlang.formatspec(b'%ld and orphan()', userrevs)]
1045 opts[b'dest'] = b'_destautoorphanrebase(SRC)'
1045 opts[b'dest'] = b'_destautoorphanrebase(SRC)'
1046
1046
1047 if dryrun or confirm:
1047 if dryrun or confirm:
1048 return _dryrunrebase(ui, repo, action, opts)
1048 return _dryrunrebase(ui, repo, action, opts)
1049 elif action == b'stop':
1049 elif action == b'stop':
1050 rbsrt = rebaseruntime(repo, ui)
1050 rbsrt = rebaseruntime(repo, ui)
1051 with repo.wlock(), repo.lock():
1051 with repo.wlock(), repo.lock():
1052 rbsrt.restorestatus()
1052 rbsrt.restorestatus()
1053 if rbsrt.collapsef:
1053 if rbsrt.collapsef:
1054 raise error.Abort(_(b"cannot stop in --collapse session"))
1054 raise error.Abort(_(b"cannot stop in --collapse session"))
1055 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1055 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1056 if not (rbsrt.keepf or allowunstable):
1056 if not (rbsrt.keepf or allowunstable):
1057 raise error.Abort(
1057 raise error.Abort(
1058 _(
1058 _(
1059 b"cannot remove original changesets with"
1059 b"cannot remove original changesets with"
1060 b" unrebased descendants"
1060 b" unrebased descendants"
1061 ),
1061 ),
1062 hint=_(
1062 hint=_(
1063 b'either enable obsmarkers to allow unstable '
1063 b'either enable obsmarkers to allow unstable '
1064 b'revisions or use --keep to keep original '
1064 b'revisions or use --keep to keep original '
1065 b'changesets'
1065 b'changesets'
1066 ),
1066 ),
1067 )
1067 )
1068 if needupdate(repo, rbsrt.state):
1068 if needupdate(repo, rbsrt.state):
1069 # update to the current working revision
1069 # update to the current working revision
1070 # to clear interrupted merge
1070 # to clear interrupted merge
1071 hg.updaterepo(repo, rbsrt.originalwd, overwrite=True)
1071 hg.updaterepo(repo, rbsrt.originalwd, overwrite=True)
1072 rbsrt._finishrebase()
1072 rbsrt._finishrebase()
1073 return 0
1073 return 0
1074 elif inmemory:
1074 elif inmemory:
1075 try:
1075 try:
1076 # in-memory merge doesn't support conflicts, so if we hit any, abort
1076 # in-memory merge doesn't support conflicts, so if we hit any, abort
1077 # and re-run as an on-disk merge.
1077 # and re-run as an on-disk merge.
1078 overrides = {(b'rebase', b'singletransaction'): True}
1078 overrides = {(b'rebase', b'singletransaction'): True}
1079 with ui.configoverride(overrides, b'rebase'):
1079 with ui.configoverride(overrides, b'rebase'):
1080 return _dorebase(ui, repo, action, opts, inmemory=inmemory)
1080 return _dorebase(ui, repo, action, opts, inmemory=inmemory)
1081 except error.InMemoryMergeConflictsError:
1081 except error.InMemoryMergeConflictsError:
1082 ui.warn(
1082 ui.warn(
1083 _(
1083 _(
1084 b'hit merge conflicts; re-running rebase without in-memory'
1084 b'hit merge conflicts; re-running rebase without in-memory'
1085 b' merge\n'
1085 b' merge\n'
1086 )
1086 )
1087 )
1087 )
1088 # TODO: Make in-memory merge not use the on-disk merge state, so
1088 # TODO: Make in-memory merge not use the on-disk merge state, so
1089 # we don't have to clean it here
1089 # we don't have to clean it here
1090 mergemod.mergestate.clean(repo)
1090 mergemod.mergestate.clean(repo)
1091 clearstatus(repo)
1091 clearstatus(repo)
1092 clearcollapsemsg(repo)
1092 clearcollapsemsg(repo)
1093 return _dorebase(ui, repo, action, opts, inmemory=False)
1093 return _dorebase(ui, repo, action, opts, inmemory=False)
1094 else:
1094 else:
1095 return _dorebase(ui, repo, action, opts)
1095 return _dorebase(ui, repo, action, opts)
1096
1096
1097
1097
1098 def _dryrunrebase(ui, repo, action, opts):
1098 def _dryrunrebase(ui, repo, action, opts):
1099 rbsrt = rebaseruntime(repo, ui, inmemory=True, opts=opts)
1099 rbsrt = rebaseruntime(repo, ui, inmemory=True, opts=opts)
1100 confirm = opts.get(b'confirm')
1100 confirm = opts.get(b'confirm')
1101 if confirm:
1101 if confirm:
1102 ui.status(_(b'starting in-memory rebase\n'))
1102 ui.status(_(b'starting in-memory rebase\n'))
1103 else:
1103 else:
1104 ui.status(
1104 ui.status(
1105 _(b'starting dry-run rebase; repository will not be changed\n')
1105 _(b'starting dry-run rebase; repository will not be changed\n')
1106 )
1106 )
1107 with repo.wlock(), repo.lock():
1107 with repo.wlock(), repo.lock():
1108 needsabort = True
1108 needsabort = True
1109 try:
1109 try:
1110 overrides = {(b'rebase', b'singletransaction'): True}
1110 overrides = {(b'rebase', b'singletransaction'): True}
1111 with ui.configoverride(overrides, b'rebase'):
1111 with ui.configoverride(overrides, b'rebase'):
1112 _origrebase(
1112 _origrebase(
1113 ui,
1113 ui,
1114 repo,
1114 repo,
1115 action,
1115 action,
1116 opts,
1116 opts,
1117 rbsrt,
1117 rbsrt,
1118 inmemory=True,
1118 inmemory=True,
1119 leaveunfinished=True,
1119 leaveunfinished=True,
1120 )
1120 )
1121 except error.InMemoryMergeConflictsError:
1121 except error.InMemoryMergeConflictsError:
1122 ui.status(_(b'hit a merge conflict\n'))
1122 ui.status(_(b'hit a merge conflict\n'))
1123 return 1
1123 return 1
1124 except error.Abort:
1124 except error.Abort:
1125 needsabort = False
1125 needsabort = False
1126 raise
1126 raise
1127 else:
1127 else:
1128 if confirm:
1128 if confirm:
1129 ui.status(_(b'rebase completed successfully\n'))
1129 ui.status(_(b'rebase completed successfully\n'))
1130 if not ui.promptchoice(_(b'apply changes (yn)?$$ &Yes $$ &No')):
1130 if not ui.promptchoice(_(b'apply changes (yn)?$$ &Yes $$ &No')):
1131 # finish unfinished rebase
1131 # finish unfinished rebase
1132 rbsrt._finishrebase()
1132 rbsrt._finishrebase()
1133 else:
1133 else:
1134 rbsrt._prepareabortorcontinue(
1134 rbsrt._prepareabortorcontinue(
1135 isabort=True, backup=False, suppwarns=True
1135 isabort=True, backup=False, suppwarns=True
1136 )
1136 )
1137 needsabort = False
1137 needsabort = False
1138 else:
1138 else:
1139 ui.status(
1139 ui.status(
1140 _(
1140 _(
1141 b'dry-run rebase completed successfully; run without'
1141 b'dry-run rebase completed successfully; run without'
1142 b' -n/--dry-run to perform this rebase\n'
1142 b' -n/--dry-run to perform this rebase\n'
1143 )
1143 )
1144 )
1144 )
1145 return 0
1145 return 0
1146 finally:
1146 finally:
1147 if needsabort:
1147 if needsabort:
1148 # no need to store backup in case of dryrun
1148 # no need to store backup in case of dryrun
1149 rbsrt._prepareabortorcontinue(
1149 rbsrt._prepareabortorcontinue(
1150 isabort=True, backup=False, suppwarns=True
1150 isabort=True, backup=False, suppwarns=True
1151 )
1151 )
1152
1152
1153
1153
1154 def _dorebase(ui, repo, action, opts, inmemory=False):
1154 def _dorebase(ui, repo, action, opts, inmemory=False):
1155 rbsrt = rebaseruntime(repo, ui, inmemory, opts)
1155 rbsrt = rebaseruntime(repo, ui, inmemory, opts)
1156 return _origrebase(ui, repo, action, opts, rbsrt, inmemory=inmemory)
1156 return _origrebase(ui, repo, action, opts, rbsrt, inmemory=inmemory)
1157
1157
1158
1158
1159 def _origrebase(
1159 def _origrebase(
1160 ui, repo, action, opts, rbsrt, inmemory=False, leaveunfinished=False
1160 ui, repo, action, opts, rbsrt, inmemory=False, leaveunfinished=False
1161 ):
1161 ):
1162 assert action != b'stop'
1162 assert action != b'stop'
1163 with repo.wlock(), repo.lock():
1163 with repo.wlock(), repo.lock():
1164 # Validate input and define rebasing points
1164 # Validate input and define rebasing points
1165 destf = opts.get(b'dest', None)
1165 destf = opts.get(b'dest', None)
1166 srcf = opts.get(b'source', None)
1166 srcf = opts.get(b'source', None)
1167 basef = opts.get(b'base', None)
1167 basef = opts.get(b'base', None)
1168 revf = opts.get(b'rev', [])
1168 revf = opts.get(b'rev', [])
1169 # search default destination in this space
1169 # search default destination in this space
1170 # used in the 'hg pull --rebase' case, see issue 5214.
1170 # used in the 'hg pull --rebase' case, see issue 5214.
1171 destspace = opts.get(b'_destspace')
1171 destspace = opts.get(b'_destspace')
1172 if opts.get(b'interactive'):
1172 if opts.get(b'interactive'):
1173 try:
1173 try:
1174 if extensions.find(b'histedit'):
1174 if extensions.find(b'histedit'):
1175 enablehistedit = b''
1175 enablehistedit = b''
1176 except KeyError:
1176 except KeyError:
1177 enablehistedit = b" --config extensions.histedit="
1177 enablehistedit = b" --config extensions.histedit="
1178 help = b"hg%s help -e histedit" % enablehistedit
1178 help = b"hg%s help -e histedit" % enablehistedit
1179 msg = (
1179 msg = (
1180 _(
1180 _(
1181 b"interactive history editing is supported by the "
1181 b"interactive history editing is supported by the "
1182 b"'histedit' extension (see \"%s\")"
1182 b"'histedit' extension (see \"%s\")"
1183 )
1183 )
1184 % help
1184 % help
1185 )
1185 )
1186 raise error.Abort(msg)
1186 raise error.Abort(msg)
1187
1187
1188 if rbsrt.collapsemsg and not rbsrt.collapsef:
1188 if rbsrt.collapsemsg and not rbsrt.collapsef:
1189 raise error.Abort(_(b'message can only be specified with collapse'))
1189 raise error.Abort(_(b'message can only be specified with collapse'))
1190
1190
1191 if action:
1191 if action:
1192 if rbsrt.collapsef:
1192 if rbsrt.collapsef:
1193 raise error.Abort(
1193 raise error.Abort(
1194 _(b'cannot use collapse with continue or abort')
1194 _(b'cannot use collapse with continue or abort')
1195 )
1195 )
1196 if srcf or basef or destf:
1196 if srcf or basef or destf:
1197 raise error.Abort(
1197 raise error.Abort(
1198 _(b'abort and continue do not allow specifying revisions')
1198 _(b'abort and continue do not allow specifying revisions')
1199 )
1199 )
1200 if action == b'abort' and opts.get(b'tool', False):
1200 if action == b'abort' and opts.get(b'tool', False):
1201 ui.warn(_(b'tool option will be ignored\n'))
1201 ui.warn(_(b'tool option will be ignored\n'))
1202 if action == b'continue':
1202 if action == b'continue':
1203 ms = mergemod.mergestate.read(repo)
1203 ms = mergemod.mergestate.read(repo)
1204 mergeutil.checkunresolved(ms)
1204 mergeutil.checkunresolved(ms)
1205
1205
1206 retcode = rbsrt._prepareabortorcontinue(
1206 retcode = rbsrt._prepareabortorcontinue(
1207 isabort=(action == b'abort')
1207 isabort=(action == b'abort')
1208 )
1208 )
1209 if retcode is not None:
1209 if retcode is not None:
1210 return retcode
1210 return retcode
1211 else:
1211 else:
1212 destmap = _definedestmap(
1212 destmap = _definedestmap(
1213 ui,
1213 ui,
1214 repo,
1214 repo,
1215 inmemory,
1215 inmemory,
1216 destf,
1216 destf,
1217 srcf,
1217 srcf,
1218 basef,
1218 basef,
1219 revf,
1219 revf,
1220 destspace=destspace,
1220 destspace=destspace,
1221 )
1221 )
1222 retcode = rbsrt._preparenewrebase(destmap)
1222 retcode = rbsrt._preparenewrebase(destmap)
1223 if retcode is not None:
1223 if retcode is not None:
1224 return retcode
1224 return retcode
1225 storecollapsemsg(repo, rbsrt.collapsemsg)
1225 storecollapsemsg(repo, rbsrt.collapsemsg)
1226
1226
1227 tr = None
1227 tr = None
1228
1228
1229 singletr = ui.configbool(b'rebase', b'singletransaction')
1229 singletr = ui.configbool(b'rebase', b'singletransaction')
1230 if singletr:
1230 if singletr:
1231 tr = repo.transaction(b'rebase')
1231 tr = repo.transaction(b'rebase')
1232
1232
1233 # If `rebase.singletransaction` is enabled, wrap the entire operation in
1233 # If `rebase.singletransaction` is enabled, wrap the entire operation in
1234 # one transaction here. Otherwise, transactions are obtained when
1234 # one transaction here. Otherwise, transactions are obtained when
1235 # committing each node, which is slower but allows partial success.
1235 # committing each node, which is slower but allows partial success.
1236 with util.acceptintervention(tr):
1236 with util.acceptintervention(tr):
1237 # Same logic for the dirstate guard, except we don't create one when
1237 # Same logic for the dirstate guard, except we don't create one when
1238 # rebasing in-memory (it's not needed).
1238 # rebasing in-memory (it's not needed).
1239 dsguard = None
1239 dsguard = None
1240 if singletr and not inmemory:
1240 if singletr and not inmemory:
1241 dsguard = dirstateguard.dirstateguard(repo, b'rebase')
1241 dsguard = dirstateguard.dirstateguard(repo, b'rebase')
1242 with util.acceptintervention(dsguard):
1242 with util.acceptintervention(dsguard):
1243 rbsrt._performrebase(tr)
1243 rbsrt._performrebase(tr)
1244 if not leaveunfinished:
1244 if not leaveunfinished:
1245 rbsrt._finishrebase()
1245 rbsrt._finishrebase()
1246
1246
1247
1247
1248 def _definedestmap(
1248 def _definedestmap(
1249 ui,
1249 ui,
1250 repo,
1250 repo,
1251 inmemory,
1251 inmemory,
1252 destf=None,
1252 destf=None,
1253 srcf=None,
1253 srcf=None,
1254 basef=None,
1254 basef=None,
1255 revf=None,
1255 revf=None,
1256 destspace=None,
1256 destspace=None,
1257 ):
1257 ):
1258 """use revisions argument to define destmap {srcrev: destrev}"""
1258 """use revisions argument to define destmap {srcrev: destrev}"""
1259 if revf is None:
1259 if revf is None:
1260 revf = []
1260 revf = []
1261
1261
1262 # destspace is here to work around issues with `hg pull --rebase` see
1262 # destspace is here to work around issues with `hg pull --rebase` see
1263 # issue5214 for details
1263 # issue5214 for details
1264 if srcf and basef:
1264 if srcf and basef:
1265 raise error.Abort(_(b'cannot specify both a source and a base'))
1265 raise error.Abort(_(b'cannot specify both a source and a base'))
1266 if revf and basef:
1266 if revf and basef:
1267 raise error.Abort(_(b'cannot specify both a revision and a base'))
1267 raise error.Abort(_(b'cannot specify both a revision and a base'))
1268 if revf and srcf:
1268 if revf and srcf:
1269 raise error.Abort(_(b'cannot specify both a revision and a source'))
1269 raise error.Abort(_(b'cannot specify both a revision and a source'))
1270
1270
1271 cmdutil.checkunfinished(repo)
1271 cmdutil.checkunfinished(repo)
1272 if not inmemory:
1272 if not inmemory:
1273 cmdutil.bailifchanged(repo)
1273 cmdutil.bailifchanged(repo)
1274
1274
1275 if ui.configbool(b'commands', b'rebase.requiredest') and not destf:
1275 if ui.configbool(b'commands', b'rebase.requiredest') and not destf:
1276 raise error.Abort(
1276 raise error.Abort(
1277 _(b'you must specify a destination'),
1277 _(b'you must specify a destination'),
1278 hint=_(b'use: hg rebase -d REV'),
1278 hint=_(b'use: hg rebase -d REV'),
1279 )
1279 )
1280
1280
1281 dest = None
1281 dest = None
1282
1282
1283 if revf:
1283 if revf:
1284 rebaseset = scmutil.revrange(repo, revf)
1284 rebaseset = scmutil.revrange(repo, revf)
1285 if not rebaseset:
1285 if not rebaseset:
1286 ui.status(_(b'empty "rev" revision set - nothing to rebase\n'))
1286 ui.status(_(b'empty "rev" revision set - nothing to rebase\n'))
1287 return None
1287 return None
1288 elif srcf:
1288 elif srcf:
1289 src = scmutil.revrange(repo, [srcf])
1289 src = scmutil.revrange(repo, [srcf])
1290 if not src:
1290 if not src:
1291 ui.status(_(b'empty "source" revision set - nothing to rebase\n'))
1291 ui.status(_(b'empty "source" revision set - nothing to rebase\n'))
1292 return None
1292 return None
1293 rebaseset = repo.revs(b'(%ld)::', src)
1293 rebaseset = repo.revs(b'(%ld)::', src)
1294 assert rebaseset
1294 assert rebaseset
1295 else:
1295 else:
1296 base = scmutil.revrange(repo, [basef or b'.'])
1296 base = scmutil.revrange(repo, [basef or b'.'])
1297 if not base:
1297 if not base:
1298 ui.status(
1298 ui.status(
1299 _(b'empty "base" revision set - ' b"can't compute rebase set\n")
1299 _(b'empty "base" revision set - ' b"can't compute rebase set\n")
1300 )
1300 )
1301 return None
1301 return None
1302 if destf:
1302 if destf:
1303 # --base does not support multiple destinations
1303 # --base does not support multiple destinations
1304 dest = scmutil.revsingle(repo, destf)
1304 dest = scmutil.revsingle(repo, destf)
1305 else:
1305 else:
1306 dest = repo[_destrebase(repo, base, destspace=destspace)]
1306 dest = repo[_destrebase(repo, base, destspace=destspace)]
1307 destf = bytes(dest)
1307 destf = bytes(dest)
1308
1308
1309 roots = [] # selected children of branching points
1309 roots = [] # selected children of branching points
1310 bpbase = {} # {branchingpoint: [origbase]}
1310 bpbase = {} # {branchingpoint: [origbase]}
1311 for b in base: # group bases by branching points
1311 for b in base: # group bases by branching points
1312 bp = repo.revs(b'ancestor(%d, %d)', b, dest.rev()).first()
1312 bp = repo.revs(b'ancestor(%d, %d)', b, dest.rev()).first()
1313 bpbase[bp] = bpbase.get(bp, []) + [b]
1313 bpbase[bp] = bpbase.get(bp, []) + [b]
1314 if None in bpbase:
1314 if None in bpbase:
1315 # emulate the old behavior, showing "nothing to rebase" (a better
1315 # emulate the old behavior, showing "nothing to rebase" (a better
1316 # behavior may be abort with "cannot find branching point" error)
1316 # behavior may be abort with "cannot find branching point" error)
1317 bpbase.clear()
1317 bpbase.clear()
1318 for bp, bs in pycompat.iteritems(bpbase): # calculate roots
1318 for bp, bs in pycompat.iteritems(bpbase): # calculate roots
1319 roots += list(repo.revs(b'children(%d) & ancestors(%ld)', bp, bs))
1319 roots += list(repo.revs(b'children(%d) & ancestors(%ld)', bp, bs))
1320
1320
1321 rebaseset = repo.revs(b'%ld::', roots)
1321 rebaseset = repo.revs(b'%ld::', roots)
1322
1322
1323 if not rebaseset:
1323 if not rebaseset:
1324 # transform to list because smartsets are not comparable to
1324 # transform to list because smartsets are not comparable to
1325 # lists. This should be improved to honor laziness of
1325 # lists. This should be improved to honor laziness of
1326 # smartset.
1326 # smartset.
1327 if list(base) == [dest.rev()]:
1327 if list(base) == [dest.rev()]:
1328 if basef:
1328 if basef:
1329 ui.status(
1329 ui.status(
1330 _(
1330 _(
1331 b'nothing to rebase - %s is both "base"'
1331 b'nothing to rebase - %s is both "base"'
1332 b' and destination\n'
1332 b' and destination\n'
1333 )
1333 )
1334 % dest
1334 % dest
1335 )
1335 )
1336 else:
1336 else:
1337 ui.status(
1337 ui.status(
1338 _(
1338 _(
1339 b'nothing to rebase - working directory '
1339 b'nothing to rebase - working directory '
1340 b'parent is also destination\n'
1340 b'parent is also destination\n'
1341 )
1341 )
1342 )
1342 )
1343 elif not repo.revs(b'%ld - ::%d', base, dest.rev()):
1343 elif not repo.revs(b'%ld - ::%d', base, dest.rev()):
1344 if basef:
1344 if basef:
1345 ui.status(
1345 ui.status(
1346 _(
1346 _(
1347 b'nothing to rebase - "base" %s is '
1347 b'nothing to rebase - "base" %s is '
1348 b'already an ancestor of destination '
1348 b'already an ancestor of destination '
1349 b'%s\n'
1349 b'%s\n'
1350 )
1350 )
1351 % (b'+'.join(bytes(repo[r]) for r in base), dest)
1351 % (b'+'.join(bytes(repo[r]) for r in base), dest)
1352 )
1352 )
1353 else:
1353 else:
1354 ui.status(
1354 ui.status(
1355 _(
1355 _(
1356 b'nothing to rebase - working '
1356 b'nothing to rebase - working '
1357 b'directory parent is already an '
1357 b'directory parent is already an '
1358 b'ancestor of destination %s\n'
1358 b'ancestor of destination %s\n'
1359 )
1359 )
1360 % dest
1360 % dest
1361 )
1361 )
1362 else: # can it happen?
1362 else: # can it happen?
1363 ui.status(
1363 ui.status(
1364 _(b'nothing to rebase from %s to %s\n')
1364 _(b'nothing to rebase from %s to %s\n')
1365 % (b'+'.join(bytes(repo[r]) for r in base), dest)
1365 % (b'+'.join(bytes(repo[r]) for r in base), dest)
1366 )
1366 )
1367 return None
1367 return None
1368
1368
1369 rebasingwcp = repo[b'.'].rev() in rebaseset
1369 rebasingwcp = repo[b'.'].rev() in rebaseset
1370 ui.log(
1370 ui.log(
1371 b"rebase",
1371 b"rebase",
1372 b"rebasing working copy parent: %r\n",
1372 b"rebasing working copy parent: %r\n",
1373 rebasingwcp,
1373 rebasingwcp,
1374 rebase_rebasing_wcp=rebasingwcp,
1374 rebase_rebasing_wcp=rebasingwcp,
1375 )
1375 )
1376 if inmemory and rebasingwcp:
1376 if inmemory and rebasingwcp:
1377 # Check these since we did not before.
1377 # Check these since we did not before.
1378 cmdutil.checkunfinished(repo)
1378 cmdutil.checkunfinished(repo)
1379 cmdutil.bailifchanged(repo)
1379 cmdutil.bailifchanged(repo)
1380
1380
1381 if not destf:
1381 if not destf:
1382 dest = repo[_destrebase(repo, rebaseset, destspace=destspace)]
1382 dest = repo[_destrebase(repo, rebaseset, destspace=destspace)]
1383 destf = bytes(dest)
1383 destf = bytes(dest)
1384
1384
1385 allsrc = revsetlang.formatspec(b'%ld', rebaseset)
1385 allsrc = revsetlang.formatspec(b'%ld', rebaseset)
1386 alias = {b'ALLSRC': allsrc}
1386 alias = {b'ALLSRC': allsrc}
1387
1387
1388 if dest is None:
1388 if dest is None:
1389 try:
1389 try:
1390 # fast path: try to resolve dest without SRC alias
1390 # fast path: try to resolve dest without SRC alias
1391 dest = scmutil.revsingle(repo, destf, localalias=alias)
1391 dest = scmutil.revsingle(repo, destf, localalias=alias)
1392 except error.RepoLookupError:
1392 except error.RepoLookupError:
1393 # multi-dest path: resolve dest for each SRC separately
1393 # multi-dest path: resolve dest for each SRC separately
1394 destmap = {}
1394 destmap = {}
1395 for r in rebaseset:
1395 for r in rebaseset:
1396 alias[b'SRC'] = revsetlang.formatspec(b'%d', r)
1396 alias[b'SRC'] = revsetlang.formatspec(b'%d', r)
1397 # use repo.anyrevs instead of scmutil.revsingle because we
1397 # use repo.anyrevs instead of scmutil.revsingle because we
1398 # don't want to abort if destset is empty.
1398 # don't want to abort if destset is empty.
1399 destset = repo.anyrevs([destf], user=True, localalias=alias)
1399 destset = repo.anyrevs([destf], user=True, localalias=alias)
1400 size = len(destset)
1400 size = len(destset)
1401 if size == 1:
1401 if size == 1:
1402 destmap[r] = destset.first()
1402 destmap[r] = destset.first()
1403 elif size == 0:
1403 elif size == 0:
1404 ui.note(_(b'skipping %s - empty destination\n') % repo[r])
1404 ui.note(_(b'skipping %s - empty destination\n') % repo[r])
1405 else:
1405 else:
1406 raise error.Abort(
1406 raise error.Abort(
1407 _(b'rebase destination for %s is not unique') % repo[r]
1407 _(b'rebase destination for %s is not unique') % repo[r]
1408 )
1408 )
1409
1409
1410 if dest is not None:
1410 if dest is not None:
1411 # single-dest case: assign dest to each rev in rebaseset
1411 # single-dest case: assign dest to each rev in rebaseset
1412 destrev = dest.rev()
1412 destrev = dest.rev()
1413 destmap = {r: destrev for r in rebaseset} # {srcrev: destrev}
1413 destmap = {r: destrev for r in rebaseset} # {srcrev: destrev}
1414
1414
1415 if not destmap:
1415 if not destmap:
1416 ui.status(_(b'nothing to rebase - empty destination\n'))
1416 ui.status(_(b'nothing to rebase - empty destination\n'))
1417 return None
1417 return None
1418
1418
1419 return destmap
1419 return destmap
1420
1420
1421
1421
1422 def externalparent(repo, state, destancestors):
1422 def externalparent(repo, state, destancestors):
1423 """Return the revision that should be used as the second parent
1423 """Return the revision that should be used as the second parent
1424 when the revisions in state is collapsed on top of destancestors.
1424 when the revisions in state is collapsed on top of destancestors.
1425 Abort if there is more than one parent.
1425 Abort if there is more than one parent.
1426 """
1426 """
1427 parents = set()
1427 parents = set()
1428 source = min(state)
1428 source = min(state)
1429 for rev in state:
1429 for rev in state:
1430 if rev == source:
1430 if rev == source:
1431 continue
1431 continue
1432 for p in repo[rev].parents():
1432 for p in repo[rev].parents():
1433 if p.rev() not in state and p.rev() not in destancestors:
1433 if p.rev() not in state and p.rev() not in destancestors:
1434 parents.add(p.rev())
1434 parents.add(p.rev())
1435 if not parents:
1435 if not parents:
1436 return nullrev
1436 return nullrev
1437 if len(parents) == 1:
1437 if len(parents) == 1:
1438 return parents.pop()
1438 return parents.pop()
1439 raise error.Abort(
1439 raise error.Abort(
1440 _(
1440 _(
1441 b'unable to collapse on top of %d, there is more '
1441 b'unable to collapse on top of %d, there is more '
1442 b'than one external parent: %s'
1442 b'than one external parent: %s'
1443 )
1443 )
1444 % (max(destancestors), b', '.join(b"%d" % p for p in sorted(parents)))
1444 % (max(destancestors), b', '.join(b"%d" % p for p in sorted(parents)))
1445 )
1445 )
1446
1446
1447
1447
1448 def commitmemorynode(repo, p1, p2, wctx, editor, extra, user, date, commitmsg):
1448 def commitmemorynode(repo, p1, p2, wctx, editor, extra, user, date, commitmsg):
1449 '''Commit the memory changes with parents p1 and p2.
1449 '''Commit the memory changes with parents p1 and p2.
1450 Return node of committed revision.'''
1450 Return node of committed revision.'''
1451 # Replicates the empty check in ``repo.commit``.
1451 # Replicates the empty check in ``repo.commit``.
1452 if wctx.isempty() and not repo.ui.configbool(b'ui', b'allowemptycommit'):
1452 if wctx.isempty() and not repo.ui.configbool(b'ui', b'allowemptycommit'):
1453 return None
1453 return None
1454
1454
1455 # By convention, ``extra['branch']`` (set by extrafn) clobbers
1455 # By convention, ``extra['branch']`` (set by extrafn) clobbers
1456 # ``branch`` (used when passing ``--keepbranches``).
1456 # ``branch`` (used when passing ``--keepbranches``).
1457 branch = repo[p1].branch()
1457 branch = repo[p1].branch()
1458 if b'branch' in extra:
1458 if b'branch' in extra:
1459 branch = extra[b'branch']
1459 branch = extra[b'branch']
1460
1460
1461 memctx = wctx.tomemctx(
1461 memctx = wctx.tomemctx(
1462 commitmsg,
1462 commitmsg,
1463 parents=(p1, p2),
1463 parents=(p1, p2),
1464 date=date,
1464 date=date,
1465 extra=extra,
1465 extra=extra,
1466 user=user,
1466 user=user,
1467 branch=branch,
1467 branch=branch,
1468 editor=editor,
1468 editor=editor,
1469 )
1469 )
1470 commitres = repo.commitctx(memctx)
1470 commitres = repo.commitctx(memctx)
1471 wctx.clean() # Might be reused
1471 wctx.clean() # Might be reused
1472 return commitres
1472 return commitres
1473
1473
1474
1474
1475 def commitnode(repo, p1, p2, editor, extra, user, date, commitmsg):
1475 def commitnode(repo, p1, p2, editor, extra, user, date, commitmsg):
1476 '''Commit the wd changes with parents p1 and p2.
1476 '''Commit the wd changes with parents p1 and p2.
1477 Return node of committed revision.'''
1477 Return node of committed revision.'''
1478 dsguard = util.nullcontextmanager()
1478 dsguard = util.nullcontextmanager()
1479 if not repo.ui.configbool(b'rebase', b'singletransaction'):
1479 if not repo.ui.configbool(b'rebase', b'singletransaction'):
1480 dsguard = dirstateguard.dirstateguard(repo, b'rebase')
1480 dsguard = dirstateguard.dirstateguard(repo, b'rebase')
1481 with dsguard:
1481 with dsguard:
1482 repo.setparents(repo[p1].node(), repo[p2].node())
1482 repo.setparents(repo[p1].node(), repo[p2].node())
1483
1483
1484 # Commit might fail if unresolved files exist
1484 # Commit might fail if unresolved files exist
1485 newnode = repo.commit(
1485 newnode = repo.commit(
1486 text=commitmsg, user=user, date=date, extra=extra, editor=editor
1486 text=commitmsg, user=user, date=date, extra=extra, editor=editor
1487 )
1487 )
1488
1488
1489 repo.dirstate.setbranch(repo[newnode].branch())
1489 repo.dirstate.setbranch(repo[newnode].branch())
1490 return newnode
1490 return newnode
1491
1491
1492
1492
1493 def rebasenode(repo, rev, p1, base, collapse, dest, wctx):
1493 def rebasenode(repo, rev, p1, base, collapse, dest, wctx):
1494 """Rebase a single revision rev on top of p1 using base as merge ancestor"""
1494 """Rebase a single revision rev on top of p1 using base as merge ancestor"""
1495 # Merge phase
1495 # Merge phase
1496 # Update to destination and merge it with local
1496 # Update to destination and merge it with local
1497 if wctx.isinmemory():
1497 if wctx.isinmemory():
1498 wctx.setbase(repo[p1])
1498 wctx.setbase(repo[p1])
1499 else:
1499 else:
1500 if repo[b'.'].rev() != p1:
1500 if repo[b'.'].rev() != p1:
1501 repo.ui.debug(b" update to %d:%s\n" % (p1, repo[p1]))
1501 repo.ui.debug(b" update to %d:%s\n" % (p1, repo[p1]))
1502 mergemod.update(repo, p1, branchmerge=False, force=True)
1502 mergemod.update(repo, p1, branchmerge=False, force=True)
1503 else:
1503 else:
1504 repo.ui.debug(b" already in destination\n")
1504 repo.ui.debug(b" already in destination\n")
1505 # This is, alas, necessary to invalidate workingctx's manifest cache,
1505 # This is, alas, necessary to invalidate workingctx's manifest cache,
1506 # as well as other data we litter on it in other places.
1506 # as well as other data we litter on it in other places.
1507 wctx = repo[None]
1507 wctx = repo[None]
1508 repo.dirstate.write(repo.currenttransaction())
1508 repo.dirstate.write(repo.currenttransaction())
1509 repo.ui.debug(b" merge against %d:%s\n" % (rev, repo[rev]))
1509 repo.ui.debug(b" merge against %d:%s\n" % (rev, repo[rev]))
1510 if base is not None:
1510 if base is not None:
1511 repo.ui.debug(b" detach base %d:%s\n" % (base, repo[base]))
1511 repo.ui.debug(b" detach base %d:%s\n" % (base, repo[base]))
1512 # When collapsing in-place, the parent is the common ancestor, we
1512 # When collapsing in-place, the parent is the common ancestor, we
1513 # have to allow merging with it.
1513 # have to allow merging with it.
1514 stats = mergemod.update(
1514 stats = mergemod.update(
1515 repo,
1515 repo,
1516 rev,
1516 rev,
1517 branchmerge=True,
1517 branchmerge=True,
1518 force=True,
1518 force=True,
1519 ancestor=base,
1519 ancestor=base,
1520 mergeancestor=collapse,
1520 mergeancestor=collapse,
1521 labels=[b'dest', b'source'],
1521 labels=[b'dest', b'source'],
1522 wc=wctx,
1522 wc=wctx,
1523 )
1523 )
1524 if collapse:
1524 if collapse:
1525 copies.duplicatecopies(repo, wctx, rev, dest)
1525 copies.duplicatecopies(repo, wctx, rev, dest)
1526 else:
1526 else:
1527 # If we're not using --collapse, we need to
1527 # If we're not using --collapse, we need to
1528 # duplicate copies between the revision we're
1528 # duplicate copies between the revision we're
1529 # rebasing and its first parent, but *not*
1529 # rebasing and its first parent, but *not*
1530 # duplicate any copies that have already been
1530 # duplicate any copies that have already been
1531 # performed in the destination.
1531 # performed in the destination.
1532 p1rev = repo[rev].p1().rev()
1532 p1rev = repo[rev].p1().rev()
1533 copies.duplicatecopies(repo, wctx, rev, p1rev, skiprev=dest)
1533 copies.duplicatecopies(repo, wctx, rev, p1rev, skiprev=dest)
1534 return stats
1534 return stats
1535
1535
1536
1536
1537 def adjustdest(repo, rev, destmap, state, skipped):
1537 def adjustdest(repo, rev, destmap, state, skipped):
1538 r"""adjust rebase destination given the current rebase state
1538 r"""adjust rebase destination given the current rebase state
1539
1539
1540 rev is what is being rebased. Return a list of two revs, which are the
1540 rev is what is being rebased. Return a list of two revs, which are the
1541 adjusted destinations for rev's p1 and p2, respectively. If a parent is
1541 adjusted destinations for rev's p1 and p2, respectively. If a parent is
1542 nullrev, return dest without adjustment for it.
1542 nullrev, return dest without adjustment for it.
1543
1543
1544 For example, when doing rebasing B+E to F, C to G, rebase will first move B
1544 For example, when doing rebasing B+E to F, C to G, rebase will first move B
1545 to B1, and E's destination will be adjusted from F to B1.
1545 to B1, and E's destination will be adjusted from F to B1.
1546
1546
1547 B1 <- written during rebasing B
1547 B1 <- written during rebasing B
1548 |
1548 |
1549 F <- original destination of B, E
1549 F <- original destination of B, E
1550 |
1550 |
1551 | E <- rev, which is being rebased
1551 | E <- rev, which is being rebased
1552 | |
1552 | |
1553 | D <- prev, one parent of rev being checked
1553 | D <- prev, one parent of rev being checked
1554 | |
1554 | |
1555 | x <- skipped, ex. no successor or successor in (::dest)
1555 | x <- skipped, ex. no successor or successor in (::dest)
1556 | |
1556 | |
1557 | C <- rebased as C', different destination
1557 | C <- rebased as C', different destination
1558 | |
1558 | |
1559 | B <- rebased as B1 C'
1559 | B <- rebased as B1 C'
1560 |/ |
1560 |/ |
1561 A G <- destination of C, different
1561 A G <- destination of C, different
1562
1562
1563 Another example about merge changeset, rebase -r C+G+H -d K, rebase will
1563 Another example about merge changeset, rebase -r C+G+H -d K, rebase will
1564 first move C to C1, G to G1, and when it's checking H, the adjusted
1564 first move C to C1, G to G1, and when it's checking H, the adjusted
1565 destinations will be [C1, G1].
1565 destinations will be [C1, G1].
1566
1566
1567 H C1 G1
1567 H C1 G1
1568 /| | /
1568 /| | /
1569 F G |/
1569 F G |/
1570 K | | -> K
1570 K | | -> K
1571 | C D |
1571 | C D |
1572 | |/ |
1572 | |/ |
1573 | B | ...
1573 | B | ...
1574 |/ |/
1574 |/ |/
1575 A A
1575 A A
1576
1576
1577 Besides, adjust dest according to existing rebase information. For example,
1577 Besides, adjust dest according to existing rebase information. For example,
1578
1578
1579 B C D B needs to be rebased on top of C, C needs to be rebased on top
1579 B C D B needs to be rebased on top of C, C needs to be rebased on top
1580 \|/ of D. We will rebase C first.
1580 \|/ of D. We will rebase C first.
1581 A
1581 A
1582
1582
1583 C' After rebasing C, when considering B's destination, use C'
1583 C' After rebasing C, when considering B's destination, use C'
1584 | instead of the original C.
1584 | instead of the original C.
1585 B D
1585 B D
1586 \ /
1586 \ /
1587 A
1587 A
1588 """
1588 """
1589 # pick already rebased revs with same dest from state as interesting source
1589 # pick already rebased revs with same dest from state as interesting source
1590 dest = destmap[rev]
1590 dest = destmap[rev]
1591 source = [
1591 source = [
1592 s
1592 s
1593 for s, d in state.items()
1593 for s, d in state.items()
1594 if d > 0 and destmap[s] == dest and s not in skipped
1594 if d > 0 and destmap[s] == dest and s not in skipped
1595 ]
1595 ]
1596
1596
1597 result = []
1597 result = []
1598 for prev in repo.changelog.parentrevs(rev):
1598 for prev in repo.changelog.parentrevs(rev):
1599 adjusted = dest
1599 adjusted = dest
1600 if prev != nullrev:
1600 if prev != nullrev:
1601 candidate = repo.revs(b'max(%ld and (::%d))', source, prev).first()
1601 candidate = repo.revs(b'max(%ld and (::%d))', source, prev).first()
1602 if candidate is not None:
1602 if candidate is not None:
1603 adjusted = state[candidate]
1603 adjusted = state[candidate]
1604 if adjusted == dest and dest in state:
1604 if adjusted == dest and dest in state:
1605 adjusted = state[dest]
1605 adjusted = state[dest]
1606 if adjusted == revtodo:
1606 if adjusted == revtodo:
1607 # sortsource should produce an order that makes this impossible
1607 # sortsource should produce an order that makes this impossible
1608 raise error.ProgrammingError(
1608 raise error.ProgrammingError(
1609 b'rev %d should be rebased already at this time' % dest
1609 b'rev %d should be rebased already at this time' % dest
1610 )
1610 )
1611 result.append(adjusted)
1611 result.append(adjusted)
1612 return result
1612 return result
1613
1613
1614
1614
1615 def _checkobsrebase(repo, ui, rebaseobsrevs, rebaseobsskipped):
1615 def _checkobsrebase(repo, ui, rebaseobsrevs, rebaseobsskipped):
1616 """
1616 """
1617 Abort if rebase will create divergence or rebase is noop because of markers
1617 Abort if rebase will create divergence or rebase is noop because of markers
1618
1618
1619 `rebaseobsrevs`: set of obsolete revision in source
1619 `rebaseobsrevs`: set of obsolete revision in source
1620 `rebaseobsskipped`: set of revisions from source skipped because they have
1620 `rebaseobsskipped`: set of revisions from source skipped because they have
1621 successors in destination or no non-obsolete successor.
1621 successors in destination or no non-obsolete successor.
1622 """
1622 """
1623 # Obsolete node with successors not in dest leads to divergence
1623 # Obsolete node with successors not in dest leads to divergence
1624 divergenceok = ui.configbool(b'experimental', b'evolution.allowdivergence')
1624 divergenceok = ui.configbool(b'experimental', b'evolution.allowdivergence')
1625 divergencebasecandidates = rebaseobsrevs - rebaseobsskipped
1625 divergencebasecandidates = rebaseobsrevs - rebaseobsskipped
1626
1626
1627 if divergencebasecandidates and not divergenceok:
1627 if divergencebasecandidates and not divergenceok:
1628 divhashes = (bytes(repo[r]) for r in divergencebasecandidates)
1628 divhashes = (bytes(repo[r]) for r in divergencebasecandidates)
1629 msg = _(b"this rebase will cause divergences from: %s")
1629 msg = _(b"this rebase will cause divergences from: %s")
1630 h = _(
1630 h = _(
1631 b"to force the rebase please set "
1631 b"to force the rebase please set "
1632 b"experimental.evolution.allowdivergence=True"
1632 b"experimental.evolution.allowdivergence=True"
1633 )
1633 )
1634 raise error.Abort(msg % (b",".join(divhashes),), hint=h)
1634 raise error.Abort(msg % (b",".join(divhashes),), hint=h)
1635
1635
1636
1636
1637 def successorrevs(unfi, rev):
1637 def successorrevs(unfi, rev):
1638 """yield revision numbers for successors of rev"""
1638 """yield revision numbers for successors of rev"""
1639 assert unfi.filtername is None
1639 assert unfi.filtername is None
1640 get_rev = unfi.changelog.index.get_rev
1640 get_rev = unfi.changelog.index.get_rev
1641 for s in obsutil.allsuccessors(unfi.obsstore, [unfi[rev].node()]):
1641 for s in obsutil.allsuccessors(unfi.obsstore, [unfi[rev].node()]):
1642 r = get_rev(s)
1642 r = get_rev(s)
1643 if r is not None:
1643 if r is not None:
1644 yield r
1644 yield r
1645
1645
1646
1646
1647 def defineparents(repo, rev, destmap, state, skipped, obsskipped):
1647 def defineparents(repo, rev, destmap, state, skipped, obsskipped):
1648 """Return new parents and optionally a merge base for rev being rebased
1648 """Return new parents and optionally a merge base for rev being rebased
1649
1649
1650 The destination specified by "dest" cannot always be used directly because
1650 The destination specified by "dest" cannot always be used directly because
1651 previously rebase result could affect destination. For example,
1651 previously rebase result could affect destination. For example,
1652
1652
1653 D E rebase -r C+D+E -d B
1653 D E rebase -r C+D+E -d B
1654 |/ C will be rebased to C'
1654 |/ C will be rebased to C'
1655 B C D's new destination will be C' instead of B
1655 B C D's new destination will be C' instead of B
1656 |/ E's new destination will be C' instead of B
1656 |/ E's new destination will be C' instead of B
1657 A
1657 A
1658
1658
1659 The new parents of a merge is slightly more complicated. See the comment
1659 The new parents of a merge is slightly more complicated. See the comment
1660 block below.
1660 block below.
1661 """
1661 """
1662 # use unfiltered changelog since successorrevs may return filtered nodes
1662 # use unfiltered changelog since successorrevs may return filtered nodes
1663 assert repo.filtername is None
1663 assert repo.filtername is None
1664 cl = repo.changelog
1664 cl = repo.changelog
1665 isancestor = cl.isancestorrev
1665 isancestor = cl.isancestorrev
1666
1666
1667 dest = destmap[rev]
1667 dest = destmap[rev]
1668 oldps = repo.changelog.parentrevs(rev) # old parents
1668 oldps = repo.changelog.parentrevs(rev) # old parents
1669 newps = [nullrev, nullrev] # new parents
1669 newps = [nullrev, nullrev] # new parents
1670 dests = adjustdest(repo, rev, destmap, state, skipped)
1670 dests = adjustdest(repo, rev, destmap, state, skipped)
1671 bases = list(oldps) # merge base candidates, initially just old parents
1671 bases = list(oldps) # merge base candidates, initially just old parents
1672
1672
1673 if all(r == nullrev for r in oldps[1:]):
1673 if all(r == nullrev for r in oldps[1:]):
1674 # For non-merge changeset, just move p to adjusted dest as requested.
1674 # For non-merge changeset, just move p to adjusted dest as requested.
1675 newps[0] = dests[0]
1675 newps[0] = dests[0]
1676 else:
1676 else:
1677 # For merge changeset, if we move p to dests[i] unconditionally, both
1677 # For merge changeset, if we move p to dests[i] unconditionally, both
1678 # parents may change and the end result looks like "the merge loses a
1678 # parents may change and the end result looks like "the merge loses a
1679 # parent", which is a surprise. This is a limit because "--dest" only
1679 # parent", which is a surprise. This is a limit because "--dest" only
1680 # accepts one dest per src.
1680 # accepts one dest per src.
1681 #
1681 #
1682 # Therefore, only move p with reasonable conditions (in this order):
1682 # Therefore, only move p with reasonable conditions (in this order):
1683 # 1. use dest, if dest is a descendent of (p or one of p's successors)
1683 # 1. use dest, if dest is a descendent of (p or one of p's successors)
1684 # 2. use p's rebased result, if p is rebased (state[p] > 0)
1684 # 2. use p's rebased result, if p is rebased (state[p] > 0)
1685 #
1685 #
1686 # Comparing with adjustdest, the logic here does some additional work:
1686 # Comparing with adjustdest, the logic here does some additional work:
1687 # 1. decide which parents will not be moved towards dest
1687 # 1. decide which parents will not be moved towards dest
1688 # 2. if the above decision is "no", should a parent still be moved
1688 # 2. if the above decision is "no", should a parent still be moved
1689 # because it was rebased?
1689 # because it was rebased?
1690 #
1690 #
1691 # For example:
1691 # For example:
1692 #
1692 #
1693 # C # "rebase -r C -d D" is an error since none of the parents
1693 # C # "rebase -r C -d D" is an error since none of the parents
1694 # /| # can be moved. "rebase -r B+C -d D" will move C's parent
1694 # /| # can be moved. "rebase -r B+C -d D" will move C's parent
1695 # A B D # B (using rule "2."), since B will be rebased.
1695 # A B D # B (using rule "2."), since B will be rebased.
1696 #
1696 #
1697 # The loop tries to be not rely on the fact that a Mercurial node has
1697 # The loop tries to be not rely on the fact that a Mercurial node has
1698 # at most 2 parents.
1698 # at most 2 parents.
1699 for i, p in enumerate(oldps):
1699 for i, p in enumerate(oldps):
1700 np = p # new parent
1700 np = p # new parent
1701 if any(isancestor(x, dests[i]) for x in successorrevs(repo, p)):
1701 if any(isancestor(x, dests[i]) for x in successorrevs(repo, p)):
1702 np = dests[i]
1702 np = dests[i]
1703 elif p in state and state[p] > 0:
1703 elif p in state and state[p] > 0:
1704 np = state[p]
1704 np = state[p]
1705
1705
1706 # "bases" only record "special" merge bases that cannot be
1706 # "bases" only record "special" merge bases that cannot be
1707 # calculated from changelog DAG (i.e. isancestor(p, np) is False).
1707 # calculated from changelog DAG (i.e. isancestor(p, np) is False).
1708 # For example:
1708 # For example:
1709 #
1709 #
1710 # B' # rebase -s B -d D, when B was rebased to B'. dest for C
1710 # B' # rebase -s B -d D, when B was rebased to B'. dest for C
1711 # | C # is B', but merge base for C is B, instead of
1711 # | C # is B', but merge base for C is B, instead of
1712 # D | # changelog.ancestor(C, B') == A. If changelog DAG and
1712 # D | # changelog.ancestor(C, B') == A. If changelog DAG and
1713 # | B # "state" edges are merged (so there will be an edge from
1713 # | B # "state" edges are merged (so there will be an edge from
1714 # |/ # B to B'), the merge base is still ancestor(C, B') in
1714 # |/ # B to B'), the merge base is still ancestor(C, B') in
1715 # A # the merged graph.
1715 # A # the merged graph.
1716 #
1716 #
1717 # Also see https://bz.mercurial-scm.org/show_bug.cgi?id=1950#c8
1717 # Also see https://bz.mercurial-scm.org/show_bug.cgi?id=1950#c8
1718 # which uses "virtual null merge" to explain this situation.
1718 # which uses "virtual null merge" to explain this situation.
1719 if isancestor(p, np):
1719 if isancestor(p, np):
1720 bases[i] = nullrev
1720 bases[i] = nullrev
1721
1721
1722 # If one parent becomes an ancestor of the other, drop the ancestor
1722 # If one parent becomes an ancestor of the other, drop the ancestor
1723 for j, x in enumerate(newps[:i]):
1723 for j, x in enumerate(newps[:i]):
1724 if x == nullrev:
1724 if x == nullrev:
1725 continue
1725 continue
1726 if isancestor(np, x): # CASE-1
1726 if isancestor(np, x): # CASE-1
1727 np = nullrev
1727 np = nullrev
1728 elif isancestor(x, np): # CASE-2
1728 elif isancestor(x, np): # CASE-2
1729 newps[j] = np
1729 newps[j] = np
1730 np = nullrev
1730 np = nullrev
1731 # New parents forming an ancestor relationship does not
1731 # New parents forming an ancestor relationship does not
1732 # mean the old parents have a similar relationship. Do not
1732 # mean the old parents have a similar relationship. Do not
1733 # set bases[x] to nullrev.
1733 # set bases[x] to nullrev.
1734 bases[j], bases[i] = bases[i], bases[j]
1734 bases[j], bases[i] = bases[i], bases[j]
1735
1735
1736 newps[i] = np
1736 newps[i] = np
1737
1737
1738 # "rebasenode" updates to new p1, and the old p1 will be used as merge
1738 # "rebasenode" updates to new p1, and the old p1 will be used as merge
1739 # base. If only p2 changes, merging using unchanged p1 as merge base is
1739 # base. If only p2 changes, merging using unchanged p1 as merge base is
1740 # suboptimal. Therefore swap parents to make the merge sane.
1740 # suboptimal. Therefore swap parents to make the merge sane.
1741 if newps[1] != nullrev and oldps[0] == newps[0]:
1741 if newps[1] != nullrev and oldps[0] == newps[0]:
1742 assert len(newps) == 2 and len(oldps) == 2
1742 assert len(newps) == 2 and len(oldps) == 2
1743 newps.reverse()
1743 newps.reverse()
1744 bases.reverse()
1744 bases.reverse()
1745
1745
1746 # No parent change might be an error because we fail to make rev a
1746 # No parent change might be an error because we fail to make rev a
1747 # descendent of requested dest. This can happen, for example:
1747 # descendent of requested dest. This can happen, for example:
1748 #
1748 #
1749 # C # rebase -r C -d D
1749 # C # rebase -r C -d D
1750 # /| # None of A and B will be changed to D and rebase fails.
1750 # /| # None of A and B will be changed to D and rebase fails.
1751 # A B D
1751 # A B D
1752 if set(newps) == set(oldps) and dest not in newps:
1752 if set(newps) == set(oldps) and dest not in newps:
1753 raise error.Abort(
1753 raise error.Abort(
1754 _(
1754 _(
1755 b'cannot rebase %d:%s without '
1755 b'cannot rebase %d:%s without '
1756 b'moving at least one of its parents'
1756 b'moving at least one of its parents'
1757 )
1757 )
1758 % (rev, repo[rev])
1758 % (rev, repo[rev])
1759 )
1759 )
1760
1760
1761 # Source should not be ancestor of dest. The check here guarantees it's
1761 # Source should not be ancestor of dest. The check here guarantees it's
1762 # impossible. With multi-dest, the initial check does not cover complex
1762 # impossible. With multi-dest, the initial check does not cover complex
1763 # cases since we don't have abstractions to dry-run rebase cheaply.
1763 # cases since we don't have abstractions to dry-run rebase cheaply.
1764 if any(p != nullrev and isancestor(rev, p) for p in newps):
1764 if any(p != nullrev and isancestor(rev, p) for p in newps):
1765 raise error.Abort(_(b'source is ancestor of destination'))
1765 raise error.Abort(_(b'source is ancestor of destination'))
1766
1766
1767 # "rebasenode" updates to new p1, use the corresponding merge base.
1767 # "rebasenode" updates to new p1, use the corresponding merge base.
1768 if bases[0] != nullrev:
1768 if bases[0] != nullrev:
1769 base = bases[0]
1769 base = bases[0]
1770 else:
1770 else:
1771 base = None
1771 base = None
1772
1772
1773 # Check if the merge will contain unwanted changes. That may happen if
1773 # Check if the merge will contain unwanted changes. That may happen if
1774 # there are multiple special (non-changelog ancestor) merge bases, which
1774 # there are multiple special (non-changelog ancestor) merge bases, which
1775 # cannot be handled well by the 3-way merge algorithm. For example:
1775 # cannot be handled well by the 3-way merge algorithm. For example:
1776 #
1776 #
1777 # F
1777 # F
1778 # /|
1778 # /|
1779 # D E # "rebase -r D+E+F -d Z", when rebasing F, if "D" was chosen
1779 # D E # "rebase -r D+E+F -d Z", when rebasing F, if "D" was chosen
1780 # | | # as merge base, the difference between D and F will include
1780 # | | # as merge base, the difference between D and F will include
1781 # B C # C, so the rebased F will contain C surprisingly. If "E" was
1781 # B C # C, so the rebased F will contain C surprisingly. If "E" was
1782 # |/ # chosen, the rebased F will contain B.
1782 # |/ # chosen, the rebased F will contain B.
1783 # A Z
1783 # A Z
1784 #
1784 #
1785 # But our merge base candidates (D and E in above case) could still be
1785 # But our merge base candidates (D and E in above case) could still be
1786 # better than the default (ancestor(F, Z) == null). Therefore still
1786 # better than the default (ancestor(F, Z) == null). Therefore still
1787 # pick one (so choose p1 above).
1787 # pick one (so choose p1 above).
1788 if sum(1 for b in set(bases) if b != nullrev) > 1:
1788 if sum(1 for b in set(bases) if b != nullrev) > 1:
1789 unwanted = [None, None] # unwanted[i]: unwanted revs if choose bases[i]
1789 unwanted = [None, None] # unwanted[i]: unwanted revs if choose bases[i]
1790 for i, base in enumerate(bases):
1790 for i, base in enumerate(bases):
1791 if base == nullrev:
1791 if base == nullrev:
1792 continue
1792 continue
1793 # Revisions in the side (not chosen as merge base) branch that
1793 # Revisions in the side (not chosen as merge base) branch that
1794 # might contain "surprising" contents
1794 # might contain "surprising" contents
1795 siderevs = list(
1795 siderevs = list(
1796 repo.revs(b'((%ld-%d) %% (%d+%d))', bases, base, base, dest)
1796 repo.revs(b'((%ld-%d) %% (%d+%d))', bases, base, base, dest)
1797 )
1797 )
1798
1798
1799 # If those revisions are covered by rebaseset, the result is good.
1799 # If those revisions are covered by rebaseset, the result is good.
1800 # A merge in rebaseset would be considered to cover its ancestors.
1800 # A merge in rebaseset would be considered to cover its ancestors.
1801 if siderevs:
1801 if siderevs:
1802 rebaseset = [
1802 rebaseset = [
1803 r for r, d in state.items() if d > 0 and r not in obsskipped
1803 r for r, d in state.items() if d > 0 and r not in obsskipped
1804 ]
1804 ]
1805 merges = [
1805 merges = [
1806 r for r in rebaseset if cl.parentrevs(r)[1] != nullrev
1806 r for r in rebaseset if cl.parentrevs(r)[1] != nullrev
1807 ]
1807 ]
1808 unwanted[i] = list(
1808 unwanted[i] = list(
1809 repo.revs(
1809 repo.revs(
1810 b'%ld - (::%ld) - %ld', siderevs, merges, rebaseset
1810 b'%ld - (::%ld) - %ld', siderevs, merges, rebaseset
1811 )
1811 )
1812 )
1812 )
1813
1813
1814 # Choose a merge base that has a minimal number of unwanted revs.
1814 # Choose a merge base that has a minimal number of unwanted revs.
1815 l, i = min(
1815 l, i = min(
1816 (len(revs), i)
1816 (len(revs), i)
1817 for i, revs in enumerate(unwanted)
1817 for i, revs in enumerate(unwanted)
1818 if revs is not None
1818 if revs is not None
1819 )
1819 )
1820 base = bases[i]
1820 base = bases[i]
1821
1821
1822 # newps[0] should match merge base if possible. Currently, if newps[i]
1822 # newps[0] should match merge base if possible. Currently, if newps[i]
1823 # is nullrev, the only case is newps[i] and newps[j] (j < i), one is
1823 # is nullrev, the only case is newps[i] and newps[j] (j < i), one is
1824 # the other's ancestor. In that case, it's fine to not swap newps here.
1824 # the other's ancestor. In that case, it's fine to not swap newps here.
1825 # (see CASE-1 and CASE-2 above)
1825 # (see CASE-1 and CASE-2 above)
1826 if i != 0 and newps[i] != nullrev:
1826 if i != 0 and newps[i] != nullrev:
1827 newps[0], newps[i] = newps[i], newps[0]
1827 newps[0], newps[i] = newps[i], newps[0]
1828
1828
1829 # The merge will include unwanted revisions. Abort now. Revisit this if
1829 # The merge will include unwanted revisions. Abort now. Revisit this if
1830 # we have a more advanced merge algorithm that handles multiple bases.
1830 # we have a more advanced merge algorithm that handles multiple bases.
1831 if l > 0:
1831 if l > 0:
1832 unwanteddesc = _(b' or ').join(
1832 unwanteddesc = _(b' or ').join(
1833 (
1833 (
1834 b', '.join(b'%d:%s' % (r, repo[r]) for r in revs)
1834 b', '.join(b'%d:%s' % (r, repo[r]) for r in revs)
1835 for revs in unwanted
1835 for revs in unwanted
1836 if revs is not None
1836 if revs is not None
1837 )
1837 )
1838 )
1838 )
1839 raise error.Abort(
1839 raise error.Abort(
1840 _(b'rebasing %d:%s will include unwanted changes from %s')
1840 _(b'rebasing %d:%s will include unwanted changes from %s')
1841 % (rev, repo[rev], unwanteddesc)
1841 % (rev, repo[rev], unwanteddesc)
1842 )
1842 )
1843
1843
1844 repo.ui.debug(b" future parents are %d and %d\n" % tuple(newps))
1844 repo.ui.debug(b" future parents are %d and %d\n" % tuple(newps))
1845
1845
1846 return newps[0], newps[1], base
1846 return newps[0], newps[1], base
1847
1847
1848
1848
1849 def isagitpatch(repo, patchname):
1849 def isagitpatch(repo, patchname):
1850 """Return true if the given patch is in git format"""
1850 """Return true if the given patch is in git format"""
1851 mqpatch = os.path.join(repo.mq.path, patchname)
1851 mqpatch = os.path.join(repo.mq.path, patchname)
1852 for line in patch.linereader(open(mqpatch, b'rb')):
1852 for line in patch.linereader(open(mqpatch, b'rb')):
1853 if line.startswith(b'diff --git'):
1853 if line.startswith(b'diff --git'):
1854 return True
1854 return True
1855 return False
1855 return False
1856
1856
1857
1857
1858 def updatemq(repo, state, skipped, **opts):
1858 def updatemq(repo, state, skipped, **opts):
1859 """Update rebased mq patches - finalize and then import them"""
1859 """Update rebased mq patches - finalize and then import them"""
1860 mqrebase = {}
1860 mqrebase = {}
1861 mq = repo.mq
1861 mq = repo.mq
1862 original_series = mq.fullseries[:]
1862 original_series = mq.fullseries[:]
1863 skippedpatches = set()
1863 skippedpatches = set()
1864
1864
1865 for p in mq.applied:
1865 for p in mq.applied:
1866 rev = repo[p.node].rev()
1866 rev = repo[p.node].rev()
1867 if rev in state:
1867 if rev in state:
1868 repo.ui.debug(
1868 repo.ui.debug(
1869 b'revision %d is an mq patch (%s), finalize it.\n'
1869 b'revision %d is an mq patch (%s), finalize it.\n'
1870 % (rev, p.name)
1870 % (rev, p.name)
1871 )
1871 )
1872 mqrebase[rev] = (p.name, isagitpatch(repo, p.name))
1872 mqrebase[rev] = (p.name, isagitpatch(repo, p.name))
1873 else:
1873 else:
1874 # Applied but not rebased, not sure this should happen
1874 # Applied but not rebased, not sure this should happen
1875 skippedpatches.add(p.name)
1875 skippedpatches.add(p.name)
1876
1876
1877 if mqrebase:
1877 if mqrebase:
1878 mq.finish(repo, mqrebase.keys())
1878 mq.finish(repo, mqrebase.keys())
1879
1879
1880 # We must start import from the newest revision
1880 # We must start import from the newest revision
1881 for rev in sorted(mqrebase, reverse=True):
1881 for rev in sorted(mqrebase, reverse=True):
1882 if rev not in skipped:
1882 if rev not in skipped:
1883 name, isgit = mqrebase[rev]
1883 name, isgit = mqrebase[rev]
1884 repo.ui.note(
1884 repo.ui.note(
1885 _(b'updating mq patch %s to %d:%s\n')
1885 _(b'updating mq patch %s to %d:%s\n')
1886 % (name, state[rev], repo[state[rev]])
1886 % (name, state[rev], repo[state[rev]])
1887 )
1887 )
1888 mq.qimport(
1888 mq.qimport(
1889 repo,
1889 repo,
1890 (),
1890 (),
1891 patchname=name,
1891 patchname=name,
1892 git=isgit,
1892 git=isgit,
1893 rev=[b"%d" % state[rev]],
1893 rev=[b"%d" % state[rev]],
1894 )
1894 )
1895 else:
1895 else:
1896 # Rebased and skipped
1896 # Rebased and skipped
1897 skippedpatches.add(mqrebase[rev][0])
1897 skippedpatches.add(mqrebase[rev][0])
1898
1898
1899 # Patches were either applied and rebased and imported in
1899 # Patches were either applied and rebased and imported in
1900 # order, applied and removed or unapplied. Discard the removed
1900 # order, applied and removed or unapplied. Discard the removed
1901 # ones while preserving the original series order and guards.
1901 # ones while preserving the original series order and guards.
1902 newseries = [
1902 newseries = [
1903 s
1903 s
1904 for s in original_series
1904 for s in original_series
1905 if mq.guard_re.split(s, 1)[0] not in skippedpatches
1905 if mq.guard_re.split(s, 1)[0] not in skippedpatches
1906 ]
1906 ]
1907 mq.fullseries[:] = newseries
1907 mq.fullseries[:] = newseries
1908 mq.seriesdirty = True
1908 mq.seriesdirty = True
1909 mq.savedirty()
1909 mq.savedirty()
1910
1910
1911
1911
1912 def storecollapsemsg(repo, collapsemsg):
1912 def storecollapsemsg(repo, collapsemsg):
1913 """Store the collapse message to allow recovery"""
1913 """Store the collapse message to allow recovery"""
1914 collapsemsg = collapsemsg or b''
1914 collapsemsg = collapsemsg or b''
1915 f = repo.vfs(b"last-message.txt", b"w")
1915 f = repo.vfs(b"last-message.txt", b"w")
1916 f.write(b"%s\n" % collapsemsg)
1916 f.write(b"%s\n" % collapsemsg)
1917 f.close()
1917 f.close()
1918
1918
1919
1919
1920 def clearcollapsemsg(repo):
1920 def clearcollapsemsg(repo):
1921 """Remove collapse message file"""
1921 """Remove collapse message file"""
1922 repo.vfs.unlinkpath(b"last-message.txt", ignoremissing=True)
1922 repo.vfs.unlinkpath(b"last-message.txt", ignoremissing=True)
1923
1923
1924
1924
1925 def restorecollapsemsg(repo, isabort):
1925 def restorecollapsemsg(repo, isabort):
1926 """Restore previously stored collapse message"""
1926 """Restore previously stored collapse message"""
1927 try:
1927 try:
1928 f = repo.vfs(b"last-message.txt")
1928 f = repo.vfs(b"last-message.txt")
1929 collapsemsg = f.readline().strip()
1929 collapsemsg = f.readline().strip()
1930 f.close()
1930 f.close()
1931 except IOError as err:
1931 except IOError as err:
1932 if err.errno != errno.ENOENT:
1932 if err.errno != errno.ENOENT:
1933 raise
1933 raise
1934 if isabort:
1934 if isabort:
1935 # Oh well, just abort like normal
1935 # Oh well, just abort like normal
1936 collapsemsg = b''
1936 collapsemsg = b''
1937 else:
1937 else:
1938 raise error.Abort(_(b'missing .hg/last-message.txt for rebase'))
1938 raise error.Abort(_(b'missing .hg/last-message.txt for rebase'))
1939 return collapsemsg
1939 return collapsemsg
1940
1940
1941
1941
1942 def clearstatus(repo):
1942 def clearstatus(repo):
1943 """Remove the status files"""
1943 """Remove the status files"""
1944 # Make sure the active transaction won't write the state file
1944 # Make sure the active transaction won't write the state file
1945 tr = repo.currenttransaction()
1945 tr = repo.currenttransaction()
1946 if tr:
1946 if tr:
1947 tr.removefilegenerator(b'rebasestate')
1947 tr.removefilegenerator(b'rebasestate')
1948 repo.vfs.unlinkpath(b"rebasestate", ignoremissing=True)
1948 repo.vfs.unlinkpath(b"rebasestate", ignoremissing=True)
1949
1949
1950
1950
1951 def needupdate(repo, state):
1951 def needupdate(repo, state):
1952 '''check whether we should `update --clean` away from a merge, or if
1952 '''check whether we should `update --clean` away from a merge, or if
1953 somehow the working dir got forcibly updated, e.g. by older hg'''
1953 somehow the working dir got forcibly updated, e.g. by older hg'''
1954 parents = [p.rev() for p in repo[None].parents()]
1954 parents = [p.rev() for p in repo[None].parents()]
1955
1955
1956 # Are we in a merge state at all?
1956 # Are we in a merge state at all?
1957 if len(parents) < 2:
1957 if len(parents) < 2:
1958 return False
1958 return False
1959
1959
1960 # We should be standing on the first as-of-yet unrebased commit.
1960 # We should be standing on the first as-of-yet unrebased commit.
1961 firstunrebased = min(
1961 firstunrebased = min(
1962 [old for old, new in pycompat.iteritems(state) if new == nullrev]
1962 [old for old, new in pycompat.iteritems(state) if new == nullrev]
1963 )
1963 )
1964 if firstunrebased in parents:
1964 if firstunrebased in parents:
1965 return True
1965 return True
1966
1966
1967 return False
1967 return False
1968
1968
1969
1969
1970 def sortsource(destmap):
1970 def sortsource(destmap):
1971 """yield source revisions in an order that we only rebase things once
1971 """yield source revisions in an order that we only rebase things once
1972
1972
1973 If source and destination overlaps, we should filter out revisions
1973 If source and destination overlaps, we should filter out revisions
1974 depending on other revisions which hasn't been rebased yet.
1974 depending on other revisions which hasn't been rebased yet.
1975
1975
1976 Yield a sorted list of revisions each time.
1976 Yield a sorted list of revisions each time.
1977
1977
1978 For example, when rebasing A to B, B to C. This function yields [B], then
1978 For example, when rebasing A to B, B to C. This function yields [B], then
1979 [A], indicating B needs to be rebased first.
1979 [A], indicating B needs to be rebased first.
1980
1980
1981 Raise if there is a cycle so the rebase is impossible.
1981 Raise if there is a cycle so the rebase is impossible.
1982 """
1982 """
1983 srcset = set(destmap)
1983 srcset = set(destmap)
1984 while srcset:
1984 while srcset:
1985 srclist = sorted(srcset)
1985 srclist = sorted(srcset)
1986 result = []
1986 result = []
1987 for r in srclist:
1987 for r in srclist:
1988 if destmap[r] not in srcset:
1988 if destmap[r] not in srcset:
1989 result.append(r)
1989 result.append(r)
1990 if not result:
1990 if not result:
1991 raise error.Abort(_(b'source and destination form a cycle'))
1991 raise error.Abort(_(b'source and destination form a cycle'))
1992 srcset -= set(result)
1992 srcset -= set(result)
1993 yield result
1993 yield result
1994
1994
1995
1995
1996 def buildstate(repo, destmap, collapse):
1996 def buildstate(repo, destmap, collapse):
1997 '''Define which revisions are going to be rebased and where
1997 '''Define which revisions are going to be rebased and where
1998
1998
1999 repo: repo
1999 repo: repo
2000 destmap: {srcrev: destrev}
2000 destmap: {srcrev: destrev}
2001 '''
2001 '''
2002 rebaseset = destmap.keys()
2002 rebaseset = destmap.keys()
2003 originalwd = repo[b'.'].rev()
2003 originalwd = repo[b'.'].rev()
2004
2004
2005 # This check isn't strictly necessary, since mq detects commits over an
2005 # This check isn't strictly necessary, since mq detects commits over an
2006 # applied patch. But it prevents messing up the working directory when
2006 # applied patch. But it prevents messing up the working directory when
2007 # a partially completed rebase is blocked by mq.
2007 # a partially completed rebase is blocked by mq.
2008 if b'qtip' in repo.tags():
2008 if b'qtip' in repo.tags():
2009 mqapplied = set(repo[s.node].rev() for s in repo.mq.applied)
2009 mqapplied = set(repo[s.node].rev() for s in repo.mq.applied)
2010 if set(destmap.values()) & mqapplied:
2010 if set(destmap.values()) & mqapplied:
2011 raise error.Abort(_(b'cannot rebase onto an applied mq patch'))
2011 raise error.Abort(_(b'cannot rebase onto an applied mq patch'))
2012
2012
2013 # Get "cycle" error early by exhausting the generator.
2013 # Get "cycle" error early by exhausting the generator.
2014 sortedsrc = list(sortsource(destmap)) # a list of sorted revs
2014 sortedsrc = list(sortsource(destmap)) # a list of sorted revs
2015 if not sortedsrc:
2015 if not sortedsrc:
2016 raise error.Abort(_(b'no matching revisions'))
2016 raise error.Abort(_(b'no matching revisions'))
2017
2017
2018 # Only check the first batch of revisions to rebase not depending on other
2018 # Only check the first batch of revisions to rebase not depending on other
2019 # rebaseset. This means "source is ancestor of destination" for the second
2019 # rebaseset. This means "source is ancestor of destination" for the second
2020 # (and following) batches of revisions are not checked here. We rely on
2020 # (and following) batches of revisions are not checked here. We rely on
2021 # "defineparents" to do that check.
2021 # "defineparents" to do that check.
2022 roots = list(repo.set(b'roots(%ld)', sortedsrc[0]))
2022 roots = list(repo.set(b'roots(%ld)', sortedsrc[0]))
2023 if not roots:
2023 if not roots:
2024 raise error.Abort(_(b'no matching revisions'))
2024 raise error.Abort(_(b'no matching revisions'))
2025
2025
2026 def revof(r):
2026 def revof(r):
2027 return r.rev()
2027 return r.rev()
2028
2028
2029 roots = sorted(roots, key=revof)
2029 roots = sorted(roots, key=revof)
2030 state = dict.fromkeys(rebaseset, revtodo)
2030 state = dict.fromkeys(rebaseset, revtodo)
2031 emptyrebase = len(sortedsrc) == 1
2031 emptyrebase = len(sortedsrc) == 1
2032 for root in roots:
2032 for root in roots:
2033 dest = repo[destmap[root.rev()]]
2033 dest = repo[destmap[root.rev()]]
2034 commonbase = root.ancestor(dest)
2034 commonbase = root.ancestor(dest)
2035 if commonbase == root:
2035 if commonbase == root:
2036 raise error.Abort(_(b'source is ancestor of destination'))
2036 raise error.Abort(_(b'source is ancestor of destination'))
2037 if commonbase == dest:
2037 if commonbase == dest:
2038 wctx = repo[None]
2038 wctx = repo[None]
2039 if dest == wctx.p1():
2039 if dest == wctx.p1():
2040 # when rebasing to '.', it will use the current wd branch name
2040 # when rebasing to '.', it will use the current wd branch name
2041 samebranch = root.branch() == wctx.branch()
2041 samebranch = root.branch() == wctx.branch()
2042 else:
2042 else:
2043 samebranch = root.branch() == dest.branch()
2043 samebranch = root.branch() == dest.branch()
2044 if not collapse and samebranch and dest in root.parents():
2044 if not collapse and samebranch and dest in root.parents():
2045 # mark the revision as done by setting its new revision
2045 # mark the revision as done by setting its new revision
2046 # equal to its old (current) revisions
2046 # equal to its old (current) revisions
2047 state[root.rev()] = root.rev()
2047 state[root.rev()] = root.rev()
2048 repo.ui.debug(b'source is a child of destination\n')
2048 repo.ui.debug(b'source is a child of destination\n')
2049 continue
2049 continue
2050
2050
2051 emptyrebase = False
2051 emptyrebase = False
2052 repo.ui.debug(b'rebase onto %s starting from %s\n' % (dest, root))
2052 repo.ui.debug(b'rebase onto %s starting from %s\n' % (dest, root))
2053 if emptyrebase:
2053 if emptyrebase:
2054 return None
2054 return None
2055 for rev in sorted(state):
2055 for rev in sorted(state):
2056 parents = [p for p in repo.changelog.parentrevs(rev) if p != nullrev]
2056 parents = [p for p in repo.changelog.parentrevs(rev) if p != nullrev]
2057 # if all parents of this revision are done, then so is this revision
2057 # if all parents of this revision are done, then so is this revision
2058 if parents and all((state.get(p) == p for p in parents)):
2058 if parents and all((state.get(p) == p for p in parents)):
2059 state[rev] = rev
2059 state[rev] = rev
2060 return originalwd, destmap, state
2060 return originalwd, destmap, state
2061
2061
2062
2062
2063 def clearrebased(
2063 def clearrebased(
2064 ui,
2064 ui,
2065 repo,
2065 repo,
2066 destmap,
2066 destmap,
2067 state,
2067 state,
2068 skipped,
2068 skipped,
2069 collapsedas=None,
2069 collapsedas=None,
2070 keepf=False,
2070 keepf=False,
2071 fm=None,
2071 fm=None,
2072 backup=True,
2072 backup=True,
2073 ):
2073 ):
2074 """dispose of rebased revision at the end of the rebase
2074 """dispose of rebased revision at the end of the rebase
2075
2075
2076 If `collapsedas` is not None, the rebase was a collapse whose result if the
2076 If `collapsedas` is not None, the rebase was a collapse whose result if the
2077 `collapsedas` node.
2077 `collapsedas` node.
2078
2078
2079 If `keepf` is not True, the rebase has --keep set and no nodes should be
2079 If `keepf` is not True, the rebase has --keep set and no nodes should be
2080 removed (but bookmarks still need to be moved).
2080 removed (but bookmarks still need to be moved).
2081
2081
2082 If `backup` is False, no backup will be stored when stripping rebased
2082 If `backup` is False, no backup will be stored when stripping rebased
2083 revisions.
2083 revisions.
2084 """
2084 """
2085 tonode = repo.changelog.node
2085 tonode = repo.changelog.node
2086 replacements = {}
2086 replacements = {}
2087 moves = {}
2087 moves = {}
2088 stripcleanup = not obsolete.isenabled(repo, obsolete.createmarkersopt)
2088 stripcleanup = not obsolete.isenabled(repo, obsolete.createmarkersopt)
2089
2089
2090 collapsednodes = []
2090 collapsednodes = []
2091 for rev, newrev in sorted(state.items()):
2091 for rev, newrev in sorted(state.items()):
2092 if newrev >= 0 and newrev != rev:
2092 if newrev >= 0 and newrev != rev:
2093 oldnode = tonode(rev)
2093 oldnode = tonode(rev)
2094 newnode = collapsedas or tonode(newrev)
2094 newnode = collapsedas or tonode(newrev)
2095 moves[oldnode] = newnode
2095 moves[oldnode] = newnode
2096 succs = None
2096 succs = None
2097 if rev in skipped:
2097 if rev in skipped:
2098 if stripcleanup or not repo[rev].obsolete():
2098 if stripcleanup or not repo[rev].obsolete():
2099 succs = ()
2099 succs = ()
2100 elif collapsedas:
2100 elif collapsedas:
2101 collapsednodes.append(oldnode)
2101 collapsednodes.append(oldnode)
2102 else:
2102 else:
2103 succs = (newnode,)
2103 succs = (newnode,)
2104 if succs is not None:
2104 if succs is not None:
2105 replacements[(oldnode,)] = succs
2105 replacements[(oldnode,)] = succs
2106 if collapsednodes:
2106 if collapsednodes:
2107 replacements[tuple(collapsednodes)] = (collapsedas,)
2107 replacements[tuple(collapsednodes)] = (collapsedas,)
2108 if fm:
2108 if fm:
2109 hf = fm.hexfunc
2109 hf = fm.hexfunc
2110 fl = fm.formatlist
2110 fl = fm.formatlist
2111 fd = fm.formatdict
2111 fd = fm.formatdict
2112 changes = {}
2112 changes = {}
2113 for oldns, newn in pycompat.iteritems(replacements):
2113 for oldns, newn in pycompat.iteritems(replacements):
2114 for oldn in oldns:
2114 for oldn in oldns:
2115 changes[hf(oldn)] = fl([hf(n) for n in newn], name=b'node')
2115 changes[hf(oldn)] = fl([hf(n) for n in newn], name=b'node')
2116 nodechanges = fd(changes, key=b"oldnode", value=b"newnodes")
2116 nodechanges = fd(changes, key=b"oldnode", value=b"newnodes")
2117 fm.data(nodechanges=nodechanges)
2117 fm.data(nodechanges=nodechanges)
2118 if keepf:
2118 if keepf:
2119 replacements = {}
2119 replacements = {}
2120 scmutil.cleanupnodes(repo, replacements, b'rebase', moves, backup=backup)
2120 scmutil.cleanupnodes(repo, replacements, b'rebase', moves, backup=backup)
2121
2121
2122
2122
2123 def pullrebase(orig, ui, repo, *args, **opts):
2123 def pullrebase(orig, ui, repo, *args, **opts):
2124 """Call rebase after pull if the latter has been invoked with --rebase"""
2124 """Call rebase after pull if the latter has been invoked with --rebase"""
2125 if opts.get('rebase'):
2125 if opts.get('rebase'):
2126 if ui.configbool(b'commands', b'rebase.requiredest'):
2126 if ui.configbool(b'commands', b'rebase.requiredest'):
2127 msg = _(b'rebase destination required by configuration')
2127 msg = _(b'rebase destination required by configuration')
2128 hint = _(b'use hg pull followed by hg rebase -d DEST')
2128 hint = _(b'use hg pull followed by hg rebase -d DEST')
2129 raise error.Abort(msg, hint=hint)
2129 raise error.Abort(msg, hint=hint)
2130
2130
2131 with repo.wlock(), repo.lock():
2131 with repo.wlock(), repo.lock():
2132 if opts.get('update'):
2132 if opts.get('update'):
2133 del opts['update']
2133 del opts['update']
2134 ui.debug(
2134 ui.debug(
2135 b'--update and --rebase are not compatible, ignoring '
2135 b'--update and --rebase are not compatible, ignoring '
2136 b'the update flag\n'
2136 b'the update flag\n'
2137 )
2137 )
2138
2138
2139 cmdutil.checkunfinished(repo, skipmerge=True)
2139 cmdutil.checkunfinished(repo, skipmerge=True)
2140 cmdutil.bailifchanged(
2140 cmdutil.bailifchanged(
2141 repo,
2141 repo,
2142 hint=_(
2142 hint=_(
2143 b'cannot pull with rebase: '
2143 b'cannot pull with rebase: '
2144 b'please commit or shelve your changes first'
2144 b'please commit or shelve your changes first'
2145 ),
2145 ),
2146 )
2146 )
2147
2147
2148 revsprepull = len(repo)
2148 revsprepull = len(repo)
2149 origpostincoming = commands.postincoming
2149 origpostincoming = commands.postincoming
2150
2150
2151 def _dummy(*args, **kwargs):
2151 def _dummy(*args, **kwargs):
2152 pass
2152 pass
2153
2153
2154 commands.postincoming = _dummy
2154 commands.postincoming = _dummy
2155 try:
2155 try:
2156 ret = orig(ui, repo, *args, **opts)
2156 ret = orig(ui, repo, *args, **opts)
2157 finally:
2157 finally:
2158 commands.postincoming = origpostincoming
2158 commands.postincoming = origpostincoming
2159 revspostpull = len(repo)
2159 revspostpull = len(repo)
2160 if revspostpull > revsprepull:
2160 if revspostpull > revsprepull:
2161 # --rev option from pull conflict with rebase own --rev
2161 # --rev option from pull conflict with rebase own --rev
2162 # dropping it
2162 # dropping it
2163 if 'rev' in opts:
2163 if 'rev' in opts:
2164 del opts['rev']
2164 del opts['rev']
2165 # positional argument from pull conflicts with rebase's own
2165 # positional argument from pull conflicts with rebase's own
2166 # --source.
2166 # --source.
2167 if 'source' in opts:
2167 if 'source' in opts:
2168 del opts['source']
2168 del opts['source']
2169 # revsprepull is the len of the repo, not revnum of tip.
2169 # revsprepull is the len of the repo, not revnum of tip.
2170 destspace = list(repo.changelog.revs(start=revsprepull))
2170 destspace = list(repo.changelog.revs(start=revsprepull))
2171 opts['_destspace'] = destspace
2171 opts['_destspace'] = destspace
2172 try:
2172 try:
2173 rebase(ui, repo, **opts)
2173 rebase(ui, repo, **opts)
2174 except error.NoMergeDestAbort:
2174 except error.NoMergeDestAbort:
2175 # we can maybe update instead
2175 # we can maybe update instead
2176 rev, _a, _b = destutil.destupdate(repo)
2176 rev, _a, _b = destutil.destupdate(repo)
2177 if rev == repo[b'.'].rev():
2177 if rev == repo[b'.'].rev():
2178 ui.status(_(b'nothing to rebase\n'))
2178 ui.status(_(b'nothing to rebase\n'))
2179 else:
2179 else:
2180 ui.status(_(b'nothing to rebase - updating instead\n'))
2180 ui.status(_(b'nothing to rebase - updating instead\n'))
2181 # not passing argument to get the bare update behavior
2181 # not passing argument to get the bare update behavior
2182 # with warning and trumpets
2182 # with warning and trumpets
2183 commands.update(ui, repo)
2183 commands.update(ui, repo)
2184 else:
2184 else:
2185 if opts.get('tool'):
2185 if opts.get('tool'):
2186 raise error.Abort(_(b'--tool can only be used with --rebase'))
2186 raise error.Abort(_(b'--tool can only be used with --rebase'))
2187 ret = orig(ui, repo, *args, **opts)
2187 ret = orig(ui, repo, *args, **opts)
2188
2188
2189 return ret
2189 return ret
2190
2190
2191
2191
2192 def _filterobsoleterevs(repo, revs):
2192 def _filterobsoleterevs(repo, revs):
2193 """returns a set of the obsolete revisions in revs"""
2193 """returns a set of the obsolete revisions in revs"""
2194 return set(r for r in revs if repo[r].obsolete())
2194 return set(r for r in revs if repo[r].obsolete())
2195
2195
2196
2196
2197 def _computeobsoletenotrebased(repo, rebaseobsrevs, destmap):
2197 def _computeobsoletenotrebased(repo, rebaseobsrevs, destmap):
2198 """Return (obsoletenotrebased, obsoletewithoutsuccessorindestination).
2198 """Return (obsoletenotrebased, obsoletewithoutsuccessorindestination).
2199
2199
2200 `obsoletenotrebased` is a mapping mapping obsolete => successor for all
2200 `obsoletenotrebased` is a mapping mapping obsolete => successor for all
2201 obsolete nodes to be rebased given in `rebaseobsrevs`.
2201 obsolete nodes to be rebased given in `rebaseobsrevs`.
2202
2202
2203 `obsoletewithoutsuccessorindestination` is a set with obsolete revisions
2203 `obsoletewithoutsuccessorindestination` is a set with obsolete revisions
2204 without a successor in destination.
2204 without a successor in destination.
2205
2205
2206 `obsoleteextinctsuccessors` is a set of obsolete revisions with only
2206 `obsoleteextinctsuccessors` is a set of obsolete revisions with only
2207 obsolete successors.
2207 obsolete successors.
2208 """
2208 """
2209 obsoletenotrebased = {}
2209 obsoletenotrebased = {}
2210 obsoletewithoutsuccessorindestination = set()
2210 obsoletewithoutsuccessorindestination = set()
2211 obsoleteextinctsuccessors = set()
2211 obsoleteextinctsuccessors = set()
2212
2212
2213 assert repo.filtername is None
2213 assert repo.filtername is None
2214 cl = repo.changelog
2214 cl = repo.changelog
2215 get_rev = cl.index.get_rev
2215 get_rev = cl.index.get_rev
2216 extinctrevs = set(repo.revs(b'extinct()'))
2216 extinctrevs = set(repo.revs(b'extinct()'))
2217 for srcrev in rebaseobsrevs:
2217 for srcrev in rebaseobsrevs:
2218 srcnode = cl.node(srcrev)
2218 srcnode = cl.node(srcrev)
2219 # XXX: more advanced APIs are required to handle split correctly
2219 # XXX: more advanced APIs are required to handle split correctly
2220 successors = set(obsutil.allsuccessors(repo.obsstore, [srcnode]))
2220 successors = set(obsutil.allsuccessors(repo.obsstore, [srcnode]))
2221 # obsutil.allsuccessors includes node itself
2221 # obsutil.allsuccessors includes node itself
2222 successors.remove(srcnode)
2222 successors.remove(srcnode)
2223 succrevs = {get_rev(s) for s in successors}
2223 succrevs = {get_rev(s) for s in successors}
2224 succrevs.discard(None)
2224 succrevs.discard(None)
2225 if succrevs.issubset(extinctrevs):
2225 if succrevs.issubset(extinctrevs):
2226 # all successors are extinct
2226 # all successors are extinct
2227 obsoleteextinctsuccessors.add(srcrev)
2227 obsoleteextinctsuccessors.add(srcrev)
2228 if not successors:
2228 if not successors:
2229 # no successor
2229 # no successor
2230 obsoletenotrebased[srcrev] = None
2230 obsoletenotrebased[srcrev] = None
2231 else:
2231 else:
2232 dstrev = destmap[srcrev]
2232 dstrev = destmap[srcrev]
2233 for succrev in succrevs:
2233 for succrev in succrevs:
2234 if cl.isancestorrev(succrev, dstrev):
2234 if cl.isancestorrev(succrev, dstrev):
2235 obsoletenotrebased[srcrev] = succrev
2235 obsoletenotrebased[srcrev] = succrev
2236 break
2236 break
2237 else:
2237 else:
2238 # If 'srcrev' has a successor in rebase set but none in
2238 # If 'srcrev' has a successor in rebase set but none in
2239 # destination (which would be catched above), we shall skip it
2239 # destination (which would be catched above), we shall skip it
2240 # and its descendants to avoid divergence.
2240 # and its descendants to avoid divergence.
2241 if srcrev in extinctrevs or any(s in destmap for s in succrevs):
2241 if srcrev in extinctrevs or any(s in destmap for s in succrevs):
2242 obsoletewithoutsuccessorindestination.add(srcrev)
2242 obsoletewithoutsuccessorindestination.add(srcrev)
2243
2243
2244 return (
2244 return (
2245 obsoletenotrebased,
2245 obsoletenotrebased,
2246 obsoletewithoutsuccessorindestination,
2246 obsoletewithoutsuccessorindestination,
2247 obsoleteextinctsuccessors,
2247 obsoleteextinctsuccessors,
2248 )
2248 )
2249
2249
2250
2250
2251 def abortrebase(ui, repo):
2251 def abortrebase(ui, repo):
2252 with repo.wlock(), repo.lock():
2252 with repo.wlock(), repo.lock():
2253 rbsrt = rebaseruntime(repo, ui)
2253 rbsrt = rebaseruntime(repo, ui)
2254 rbsrt._prepareabortorcontinue(isabort=True)
2254 rbsrt._prepareabortorcontinue(isabort=True)
2255
2255
2256
2256
2257 def continuerebase(ui, repo):
2257 def continuerebase(ui, repo):
2258 with repo.wlock(), repo.lock():
2258 with repo.wlock(), repo.lock():
2259 rbsrt = rebaseruntime(repo, ui)
2259 rbsrt = rebaseruntime(repo, ui)
2260 ms = mergemod.mergestate.read(repo)
2260 ms = mergemod.mergestate.read(repo)
2261 mergeutil.checkunresolved(ms)
2261 mergeutil.checkunresolved(ms)
2262 retcode = rbsrt._prepareabortorcontinue(isabort=False)
2262 retcode = rbsrt._prepareabortorcontinue(isabort=False)
2263 if retcode is not None:
2263 if retcode is not None:
2264 return retcode
2264 return retcode
2265 rbsrt._performrebase(None)
2265 rbsrt._performrebase(None)
2266 rbsrt._finishrebase()
2266 rbsrt._finishrebase()
2267
2267
2268
2268
2269 def summaryhook(ui, repo):
2269 def summaryhook(ui, repo):
2270 if not repo.vfs.exists(b'rebasestate'):
2270 if not repo.vfs.exists(b'rebasestate'):
2271 return
2271 return
2272 try:
2272 try:
2273 rbsrt = rebaseruntime(repo, ui, {})
2273 rbsrt = rebaseruntime(repo, ui, {})
2274 rbsrt.restorestatus()
2274 rbsrt.restorestatus()
2275 state = rbsrt.state
2275 state = rbsrt.state
2276 except error.RepoLookupError:
2276 except error.RepoLookupError:
2277 # i18n: column positioning for "hg summary"
2277 # i18n: column positioning for "hg summary"
2278 msg = _(b'rebase: (use "hg rebase --abort" to clear broken state)\n')
2278 msg = _(b'rebase: (use "hg rebase --abort" to clear broken state)\n')
2279 ui.write(msg)
2279 ui.write(msg)
2280 return
2280 return
2281 numrebased = len([i for i in pycompat.itervalues(state) if i >= 0])
2281 numrebased = len([i for i in pycompat.itervalues(state) if i >= 0])
2282 # i18n: column positioning for "hg summary"
2282 # i18n: column positioning for "hg summary"
2283 ui.write(
2283 ui.write(
2284 _(b'rebase: %s, %s (rebase --continue)\n')
2284 _(b'rebase: %s, %s (rebase --continue)\n')
2285 % (
2285 % (
2286 ui.label(_(b'%d rebased'), b'rebase.rebased') % numrebased,
2286 ui.label(_(b'%d rebased'), b'rebase.rebased') % numrebased,
2287 ui.label(_(b'%d remaining'), b'rebase.remaining')
2287 ui.label(_(b'%d remaining'), b'rebase.remaining')
2288 % (len(state) - numrebased),
2288 % (len(state) - numrebased),
2289 )
2289 )
2290 )
2290 )
2291
2291
2292
2292
2293 def uisetup(ui):
2293 def uisetup(ui):
2294 # Replace pull with a decorator to provide --rebase option
2294 # Replace pull with a decorator to provide --rebase option
2295 entry = extensions.wrapcommand(commands.table, b'pull', pullrebase)
2295 entry = extensions.wrapcommand(commands.table, b'pull', pullrebase)
2296 entry[1].append(
2296 entry[1].append(
2297 (b'', b'rebase', None, _(b"rebase working directory to branch head"))
2297 (b'', b'rebase', None, _(b"rebase working directory to branch head"))
2298 )
2298 )
2299 entry[1].append((b't', b'tool', b'', _(b"specify merge tool for rebase")))
2299 entry[1].append((b't', b'tool', b'', _(b"specify merge tool for rebase")))
2300 cmdutil.summaryhooks.add(b'rebase', summaryhook)
2300 cmdutil.summaryhooks.add(b'rebase', summaryhook)
2301 statemod.addunfinished(
2301 statemod.addunfinished(
2302 b'rebase',
2302 b'rebase',
2303 fname=b'rebasestate',
2303 fname=b'rebasestate',
2304 stopflag=True,
2304 stopflag=True,
2305 continueflag=True,
2305 continueflag=True,
2306 abortfunc=abortrebase,
2306 abortfunc=abortrebase,
2307 continuefunc=continuerebase,
2307 continuefunc=continuerebase,
2308 )
2308 )
@@ -1,922 +1,922 b''
1 #require symlink execbit
1 #require symlink execbit
2 $ cat << EOF >> $HGRCPATH
2 $ cat << EOF >> $HGRCPATH
3 > [phases]
3 > [phases]
4 > publish=False
4 > publish=False
5 > [extensions]
5 > [extensions]
6 > amend=
6 > amend=
7 > rebase=
7 > rebase=
8 > debugdrawdag=$TESTDIR/drawdag.py
8 > debugdrawdag=$TESTDIR/drawdag.py
9 > strip=
9 > strip=
10 > [rebase]
10 > [rebase]
11 > experimental.inmemory=1
11 > experimental.inmemory=1
12 > [diff]
12 > [diff]
13 > git=1
13 > git=1
14 > [alias]
14 > [alias]
15 > tglog = log -G --template "{rev}: {node|short} '{desc}'\n"
15 > tglog = log -G --template "{rev}: {node|short} '{desc}'\n"
16 > EOF
16 > EOF
17
17
18 Rebase a simple DAG:
18 Rebase a simple DAG:
19 $ hg init repo1
19 $ hg init repo1
20 $ cd repo1
20 $ cd repo1
21 $ hg debugdrawdag <<'EOS'
21 $ hg debugdrawdag <<'EOS'
22 > c b
22 > c b
23 > |/
23 > |/
24 > d
24 > d
25 > |
25 > |
26 > a
26 > a
27 > EOS
27 > EOS
28 $ hg up -C a
28 $ hg up -C a
29 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
29 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
30 $ hg tglog
30 $ hg tglog
31 o 3: 814f6bd05178 'c'
31 o 3: 814f6bd05178 'c'
32 |
32 |
33 | o 2: db0e82a16a62 'b'
33 | o 2: db0e82a16a62 'b'
34 |/
34 |/
35 o 1: 02952614a83d 'd'
35 o 1: 02952614a83d 'd'
36 |
36 |
37 @ 0: b173517d0057 'a'
37 @ 0: b173517d0057 'a'
38
38
39 $ hg cat -r 3 c
39 $ hg cat -r 3 c
40 c (no-eol)
40 c (no-eol)
41 $ hg cat -r 2 b
41 $ hg cat -r 2 b
42 b (no-eol)
42 b (no-eol)
43 $ hg rebase --debug -r b -d c | grep rebasing
43 $ hg rebase --debug -r b -d c | grep rebasing
44 rebasing in-memory
44 rebasing in-memory
45 rebasing 2:db0e82a16a62 "b" (b)
45 rebasing 2:db0e82a16a62 "b" (b)
46 $ hg tglog
46 $ hg tglog
47 o 3: ca58782ad1e4 'b'
47 o 3: ca58782ad1e4 'b'
48 |
48 |
49 o 2: 814f6bd05178 'c'
49 o 2: 814f6bd05178 'c'
50 |
50 |
51 o 1: 02952614a83d 'd'
51 o 1: 02952614a83d 'd'
52 |
52 |
53 @ 0: b173517d0057 'a'
53 @ 0: b173517d0057 'a'
54
54
55 $ hg cat -r 3 b
55 $ hg cat -r 3 b
56 b (no-eol)
56 b (no-eol)
57 $ hg cat -r 2 c
57 $ hg cat -r 2 c
58 c (no-eol)
58 c (no-eol)
59 $ cd ..
59 $ cd ..
60
60
61 Case 2:
61 Case 2:
62 $ hg init repo2
62 $ hg init repo2
63 $ cd repo2
63 $ cd repo2
64 $ hg debugdrawdag <<'EOS'
64 $ hg debugdrawdag <<'EOS'
65 > c b
65 > c b
66 > |/
66 > |/
67 > d
67 > d
68 > |
68 > |
69 > a
69 > a
70 > EOS
70 > EOS
71
71
72 Add a symlink and executable file:
72 Add a symlink and executable file:
73 $ hg up -C c
73 $ hg up -C c
74 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
74 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
75 $ ln -s somefile e
75 $ ln -s somefile e
76 $ echo f > f
76 $ echo f > f
77 $ chmod +x f
77 $ chmod +x f
78 $ hg add e f
78 $ hg add e f
79 $ hg amend -q
79 $ hg amend -q
80 $ hg up -Cq a
80 $ hg up -Cq a
81
81
82 Write files to the working copy, and ensure they're still there after the rebase
82 Write files to the working copy, and ensure they're still there after the rebase
83 $ echo "abc" > a
83 $ echo "abc" > a
84 $ ln -s def b
84 $ ln -s def b
85 $ echo "ghi" > c
85 $ echo "ghi" > c
86 $ echo "jkl" > d
86 $ echo "jkl" > d
87 $ echo "mno" > e
87 $ echo "mno" > e
88 $ hg tglog
88 $ hg tglog
89 o 3: f56b71190a8f 'c'
89 o 3: f56b71190a8f 'c'
90 |
90 |
91 | o 2: db0e82a16a62 'b'
91 | o 2: db0e82a16a62 'b'
92 |/
92 |/
93 o 1: 02952614a83d 'd'
93 o 1: 02952614a83d 'd'
94 |
94 |
95 @ 0: b173517d0057 'a'
95 @ 0: b173517d0057 'a'
96
96
97 $ hg cat -r 3 c
97 $ hg cat -r 3 c
98 c (no-eol)
98 c (no-eol)
99 $ hg cat -r 2 b
99 $ hg cat -r 2 b
100 b (no-eol)
100 b (no-eol)
101 $ hg cat -r 3 e
101 $ hg cat -r 3 e
102 somefile (no-eol)
102 somefile (no-eol)
103 $ hg rebase --debug -s b -d a | grep rebasing
103 $ hg rebase --debug -s b -d a | grep rebasing
104 rebasing in-memory
104 rebasing in-memory
105 rebasing 2:db0e82a16a62 "b" (b)
105 rebasing 2:db0e82a16a62 "b" (b)
106 $ hg tglog
106 $ hg tglog
107 o 3: fc055c3b4d33 'b'
107 o 3: fc055c3b4d33 'b'
108 |
108 |
109 | o 2: f56b71190a8f 'c'
109 | o 2: f56b71190a8f 'c'
110 | |
110 | |
111 | o 1: 02952614a83d 'd'
111 | o 1: 02952614a83d 'd'
112 |/
112 |/
113 @ 0: b173517d0057 'a'
113 @ 0: b173517d0057 'a'
114
114
115 $ hg cat -r 2 c
115 $ hg cat -r 2 c
116 c (no-eol)
116 c (no-eol)
117 $ hg cat -r 3 b
117 $ hg cat -r 3 b
118 b (no-eol)
118 b (no-eol)
119 $ hg rebase --debug -s 1 -d 3 | grep rebasing
119 $ hg rebase --debug -s 1 -d 3 | grep rebasing
120 rebasing in-memory
120 rebasing in-memory
121 rebasing 1:02952614a83d "d" (d)
121 rebasing 1:02952614a83d "d" (d)
122 rebasing 2:f56b71190a8f "c"
122 rebasing 2:f56b71190a8f "c"
123 $ hg tglog
123 $ hg tglog
124 o 3: 753feb6fd12a 'c'
124 o 3: 753feb6fd12a 'c'
125 |
125 |
126 o 2: 09c044d2cb43 'd'
126 o 2: 09c044d2cb43 'd'
127 |
127 |
128 o 1: fc055c3b4d33 'b'
128 o 1: fc055c3b4d33 'b'
129 |
129 |
130 @ 0: b173517d0057 'a'
130 @ 0: b173517d0057 'a'
131
131
132 Ensure working copy files are still there:
132 Ensure working copy files are still there:
133 $ cat a
133 $ cat a
134 abc
134 abc
135 $ readlink.py b
135 $ readlink.py b
136 b -> def
136 b -> def
137 $ cat e
137 $ cat e
138 mno
138 mno
139
139
140 Ensure symlink and executable files were rebased properly:
140 Ensure symlink and executable files were rebased properly:
141 $ hg up -Cq 3
141 $ hg up -Cq 3
142 $ readlink.py e
142 $ readlink.py e
143 e -> somefile
143 e -> somefile
144 $ ls -l f | cut -c -10
144 $ ls -l f | cut -c -10
145 -rwxr-xr-x
145 -rwxr-xr-x
146
146
147 Rebase the working copy parent
147 Rebase the working copy parent
148 $ hg up -C 3
148 $ hg up -C 3
149 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
149 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
150 $ hg rebase -r 3 -d 0 --debug | grep rebasing
150 $ hg rebase -r 3 -d 0 --debug | grep rebasing
151 rebasing in-memory
151 rebasing in-memory
152 rebasing 3:753feb6fd12a "c" (tip)
152 rebasing 3:753feb6fd12a "c" (tip)
153 $ hg tglog
153 $ hg tglog
154 @ 3: 844a7de3e617 'c'
154 @ 3: 844a7de3e617 'c'
155 |
155 |
156 | o 2: 09c044d2cb43 'd'
156 | o 2: 09c044d2cb43 'd'
157 | |
157 | |
158 | o 1: fc055c3b4d33 'b'
158 | o 1: fc055c3b4d33 'b'
159 |/
159 |/
160 o 0: b173517d0057 'a'
160 o 0: b173517d0057 'a'
161
161
162
162
163 Test reporting of path conflicts
163 Test reporting of path conflicts
164
164
165 $ hg rm a
165 $ hg rm a
166 $ mkdir a
166 $ mkdir a
167 $ touch a/a
167 $ touch a/a
168 $ hg ci -Am "a/a"
168 $ hg ci -Am "a/a"
169 adding a/a
169 adding a/a
170 $ hg tglog
170 $ hg tglog
171 @ 4: daf7dfc139cb 'a/a'
171 @ 4: daf7dfc139cb 'a/a'
172 |
172 |
173 o 3: 844a7de3e617 'c'
173 o 3: 844a7de3e617 'c'
174 |
174 |
175 | o 2: 09c044d2cb43 'd'
175 | o 2: 09c044d2cb43 'd'
176 | |
176 | |
177 | o 1: fc055c3b4d33 'b'
177 | o 1: fc055c3b4d33 'b'
178 |/
178 |/
179 o 0: b173517d0057 'a'
179 o 0: b173517d0057 'a'
180
180
181 $ hg rebase -r . -d 2
181 $ hg rebase -r . -d 2
182 rebasing 4:daf7dfc139cb "a/a" (tip)
182 rebasing 4:daf7dfc139cb "a/a" (tip)
183 saved backup bundle to $TESTTMP/repo2/.hg/strip-backup/daf7dfc139cb-fdbfcf4f-rebase.hg
183 saved backup bundle to $TESTTMP/repo2/.hg/strip-backup/daf7dfc139cb-fdbfcf4f-rebase.hg
184
184
185 $ hg tglog
185 $ hg tglog
186 @ 4: c6ad37a4f250 'a/a'
186 @ 4: c6ad37a4f250 'a/a'
187 |
187 |
188 | o 3: 844a7de3e617 'c'
188 | o 3: 844a7de3e617 'c'
189 | |
189 | |
190 o | 2: 09c044d2cb43 'd'
190 o | 2: 09c044d2cb43 'd'
191 | |
191 | |
192 o | 1: fc055c3b4d33 'b'
192 o | 1: fc055c3b4d33 'b'
193 |/
193 |/
194 o 0: b173517d0057 'a'
194 o 0: b173517d0057 'a'
195
195
196 $ echo foo > foo
196 $ echo foo > foo
197 $ hg ci -Aqm "added foo"
197 $ hg ci -Aqm "added foo"
198 $ hg up '.^'
198 $ hg up '.^'
199 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
199 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
200 $ echo bar > bar
200 $ echo bar > bar
201 $ hg ci -Aqm "added bar"
201 $ hg ci -Aqm "added bar"
202 $ hg rm a/a
202 $ hg rm a/a
203 $ echo a > a
203 $ echo a > a
204 $ hg ci -Aqm "added a back!"
204 $ hg ci -Aqm "added a back!"
205 $ hg tglog
205 $ hg tglog
206 @ 7: 855e9797387e 'added a back!'
206 @ 7: 855e9797387e 'added a back!'
207 |
207 |
208 o 6: d14530e5e3e6 'added bar'
208 o 6: d14530e5e3e6 'added bar'
209 |
209 |
210 | o 5: 9b94b9373deb 'added foo'
210 | o 5: 9b94b9373deb 'added foo'
211 |/
211 |/
212 o 4: c6ad37a4f250 'a/a'
212 o 4: c6ad37a4f250 'a/a'
213 |
213 |
214 | o 3: 844a7de3e617 'c'
214 | o 3: 844a7de3e617 'c'
215 | |
215 | |
216 o | 2: 09c044d2cb43 'd'
216 o | 2: 09c044d2cb43 'd'
217 | |
217 | |
218 o | 1: fc055c3b4d33 'b'
218 o | 1: fc055c3b4d33 'b'
219 |/
219 |/
220 o 0: b173517d0057 'a'
220 o 0: b173517d0057 'a'
221
221
222 $ hg rebase -r . -d 5
222 $ hg rebase -r . -d 5
223 rebasing 7:855e9797387e "added a back!" (tip)
223 rebasing 7:855e9797387e "added a back!" (tip)
224 saved backup bundle to $TESTTMP/repo2/.hg/strip-backup/855e9797387e-81ee4c5d-rebase.hg
224 saved backup bundle to $TESTTMP/repo2/.hg/strip-backup/855e9797387e-81ee4c5d-rebase.hg
225
225
226 $ hg tglog
226 $ hg tglog
227 @ 7: bb3f02be2688 'added a back!'
227 @ 7: bb3f02be2688 'added a back!'
228 |
228 |
229 | o 6: d14530e5e3e6 'added bar'
229 | o 6: d14530e5e3e6 'added bar'
230 | |
230 | |
231 o | 5: 9b94b9373deb 'added foo'
231 o | 5: 9b94b9373deb 'added foo'
232 |/
232 |/
233 o 4: c6ad37a4f250 'a/a'
233 o 4: c6ad37a4f250 'a/a'
234 |
234 |
235 | o 3: 844a7de3e617 'c'
235 | o 3: 844a7de3e617 'c'
236 | |
236 | |
237 o | 2: 09c044d2cb43 'd'
237 o | 2: 09c044d2cb43 'd'
238 | |
238 | |
239 o | 1: fc055c3b4d33 'b'
239 o | 1: fc055c3b4d33 'b'
240 |/
240 |/
241 o 0: b173517d0057 'a'
241 o 0: b173517d0057 'a'
242
242
243 $ mkdir -p c/subdir
243 $ mkdir -p c/subdir
244 $ echo c > c/subdir/file.txt
244 $ echo c > c/subdir/file.txt
245 $ hg add c/subdir/file.txt
245 $ hg add c/subdir/file.txt
246 $ hg ci -m 'c/subdir/file.txt'
246 $ hg ci -m 'c/subdir/file.txt'
247 $ hg rebase -r . -d 3 -n
247 $ hg rebase -r . -d 3 -n
248 starting dry-run rebase; repository will not be changed
248 starting dry-run rebase; repository will not be changed
249 rebasing 8:e147e6e3c490 "c/subdir/file.txt" (tip)
249 rebasing 8:e147e6e3c490 "c/subdir/file.txt" (tip)
250 abort: error: 'c/subdir/file.txt' conflicts with file 'c' in 3.
250 abort: error: 'c/subdir/file.txt' conflicts with file 'c' in 3.
251 [255]
251 [255]
252 FIXME: shouldn't need this, but when we hit path conflicts in dryrun mode, we
252 FIXME: shouldn't need this, but when we hit path conflicts in dryrun mode, we
253 don't clean up rebasestate.
253 don't clean up rebasestate.
254 $ hg rebase --abort
254 $ hg rebase --abort
255 rebase aborted
255 rebase aborted
256 $ hg rebase -r 3 -d . -n
256 $ hg rebase -r 3 -d . -n
257 starting dry-run rebase; repository will not be changed
257 starting dry-run rebase; repository will not be changed
258 rebasing 3:844a7de3e617 "c"
258 rebasing 3:844a7de3e617 "c"
259 abort: error: file 'c' cannot be written because 'c/' is a directory in e147e6e3c490 (containing 1 entries: c/subdir/file.txt)
259 abort: error: file 'c' cannot be written because 'c/' is a directory in e147e6e3c490 (containing 1 entries: c/subdir/file.txt)
260 [255]
260 [255]
261
261
262 $ cd ..
262 $ cd ..
263
263
264 Test path auditing (issue5818)
264 Test path auditing (issue5818)
265
265
266 $ mkdir lib_
266 $ mkdir lib_
267 $ ln -s lib_ lib
267 $ ln -s lib_ lib
268 $ hg init repo
268 $ hg init repo
269 $ cd repo
269 $ cd repo
270 $ mkdir -p ".$TESTTMP/lib"
270 $ mkdir -p ".$TESTTMP/lib"
271 $ touch ".$TESTTMP/lib/a"
271 $ touch ".$TESTTMP/lib/a"
272 $ hg add ".$TESTTMP/lib/a"
272 $ hg add ".$TESTTMP/lib/a"
273 $ hg ci -m 'a'
273 $ hg ci -m 'a'
274
274
275 $ touch ".$TESTTMP/lib/b"
275 $ touch ".$TESTTMP/lib/b"
276 $ hg add ".$TESTTMP/lib/b"
276 $ hg add ".$TESTTMP/lib/b"
277 $ hg ci -m 'b'
277 $ hg ci -m 'b'
278
278
279 $ hg up -q '.^'
279 $ hg up -q '.^'
280 $ touch ".$TESTTMP/lib/c"
280 $ touch ".$TESTTMP/lib/c"
281 $ hg add ".$TESTTMP/lib/c"
281 $ hg add ".$TESTTMP/lib/c"
282 $ hg ci -m 'c'
282 $ hg ci -m 'c'
283 created new head
283 created new head
284 $ hg rebase -s 1 -d .
284 $ hg rebase -s 1 -d .
285 rebasing 1:* "b" (glob)
285 rebasing 1:* "b" (glob)
286 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-rebase.hg (glob)
286 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-rebase.hg (glob)
287 $ cd ..
287 $ cd ..
288
288
289 Test dry-run rebasing
289 Test dry-run rebasing
290
290
291 $ hg init repo3
291 $ hg init repo3
292 $ cd repo3
292 $ cd repo3
293 $ echo a>a
293 $ echo a>a
294 $ hg ci -Aqma
294 $ hg ci -Aqma
295 $ echo b>b
295 $ echo b>b
296 $ hg ci -Aqmb
296 $ hg ci -Aqmb
297 $ echo c>c
297 $ echo c>c
298 $ hg ci -Aqmc
298 $ hg ci -Aqmc
299 $ echo d>d
299 $ echo d>d
300 $ hg ci -Aqmd
300 $ hg ci -Aqmd
301 $ echo e>e
301 $ echo e>e
302 $ hg ci -Aqme
302 $ hg ci -Aqme
303
303
304 $ hg up 1 -q
304 $ hg up 1 -q
305 $ echo f>f
305 $ echo f>f
306 $ hg ci -Amf
306 $ hg ci -Amf
307 adding f
307 adding f
308 created new head
308 created new head
309 $ echo g>g
309 $ echo g>g
310 $ hg ci -Aqmg
310 $ hg ci -Aqmg
311 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
311 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
312 @ 6:baf10c5166d4 test
312 @ 6:baf10c5166d4 test
313 | g
313 | g
314 |
314 |
315 o 5:6343ca3eff20 test
315 o 5:6343ca3eff20 test
316 | f
316 | f
317 |
317 |
318 | o 4:e860deea161a test
318 | o 4:e860deea161a test
319 | | e
319 | | e
320 | |
320 | |
321 | o 3:055a42cdd887 test
321 | o 3:055a42cdd887 test
322 | | d
322 | | d
323 | |
323 | |
324 | o 2:177f92b77385 test
324 | o 2:177f92b77385 test
325 |/ c
325 |/ c
326 |
326 |
327 o 1:d2ae7f538514 test
327 o 1:d2ae7f538514 test
328 | b
328 | b
329 |
329 |
330 o 0:cb9a9f314b8b test
330 o 0:cb9a9f314b8b test
331 a
331 a
332
332
333 Make sure it throws error while passing --continue or --abort with --dry-run
333 Make sure it throws error while passing --continue or --abort with --dry-run
334 $ hg rebase -s 2 -d 6 -n --continue
334 $ hg rebase -s 2 -d 6 -n --continue
335 abort: cannot specify both --dry-run and --continue
335 abort: cannot specify both --continue and --dry-run
336 [255]
336 [255]
337 $ hg rebase -s 2 -d 6 -n --abort
337 $ hg rebase -s 2 -d 6 -n --abort
338 abort: cannot specify both --dry-run and --abort
338 abort: cannot specify both --abort and --dry-run
339 [255]
339 [255]
340
340
341 Check dryrun gives correct results when there is no conflict in rebasing
341 Check dryrun gives correct results when there is no conflict in rebasing
342 $ hg rebase -s 2 -d 6 -n
342 $ hg rebase -s 2 -d 6 -n
343 starting dry-run rebase; repository will not be changed
343 starting dry-run rebase; repository will not be changed
344 rebasing 2:177f92b77385 "c"
344 rebasing 2:177f92b77385 "c"
345 rebasing 3:055a42cdd887 "d"
345 rebasing 3:055a42cdd887 "d"
346 rebasing 4:e860deea161a "e"
346 rebasing 4:e860deea161a "e"
347 dry-run rebase completed successfully; run without -n/--dry-run to perform this rebase
347 dry-run rebase completed successfully; run without -n/--dry-run to perform this rebase
348
348
349 $ hg diff
349 $ hg diff
350 $ hg status
350 $ hg status
351
351
352 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
352 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
353 @ 6:baf10c5166d4 test
353 @ 6:baf10c5166d4 test
354 | g
354 | g
355 |
355 |
356 o 5:6343ca3eff20 test
356 o 5:6343ca3eff20 test
357 | f
357 | f
358 |
358 |
359 | o 4:e860deea161a test
359 | o 4:e860deea161a test
360 | | e
360 | | e
361 | |
361 | |
362 | o 3:055a42cdd887 test
362 | o 3:055a42cdd887 test
363 | | d
363 | | d
364 | |
364 | |
365 | o 2:177f92b77385 test
365 | o 2:177f92b77385 test
366 |/ c
366 |/ c
367 |
367 |
368 o 1:d2ae7f538514 test
368 o 1:d2ae7f538514 test
369 | b
369 | b
370 |
370 |
371 o 0:cb9a9f314b8b test
371 o 0:cb9a9f314b8b test
372 a
372 a
373
373
374 Check dryrun working with --collapse when there is no conflict
374 Check dryrun working with --collapse when there is no conflict
375 $ hg rebase -s 2 -d 6 -n --collapse
375 $ hg rebase -s 2 -d 6 -n --collapse
376 starting dry-run rebase; repository will not be changed
376 starting dry-run rebase; repository will not be changed
377 rebasing 2:177f92b77385 "c"
377 rebasing 2:177f92b77385 "c"
378 rebasing 3:055a42cdd887 "d"
378 rebasing 3:055a42cdd887 "d"
379 rebasing 4:e860deea161a "e"
379 rebasing 4:e860deea161a "e"
380 dry-run rebase completed successfully; run without -n/--dry-run to perform this rebase
380 dry-run rebase completed successfully; run without -n/--dry-run to perform this rebase
381
381
382 Check dryrun gives correct results when there is conflict in rebasing
382 Check dryrun gives correct results when there is conflict in rebasing
383 Make a conflict:
383 Make a conflict:
384 $ hg up 6 -q
384 $ hg up 6 -q
385 $ echo conflict>e
385 $ echo conflict>e
386 $ hg ci -Aqm "conflict with e"
386 $ hg ci -Aqm "conflict with e"
387 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
387 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
388 @ 7:d2c195b28050 test
388 @ 7:d2c195b28050 test
389 | conflict with e
389 | conflict with e
390 |
390 |
391 o 6:baf10c5166d4 test
391 o 6:baf10c5166d4 test
392 | g
392 | g
393 |
393 |
394 o 5:6343ca3eff20 test
394 o 5:6343ca3eff20 test
395 | f
395 | f
396 |
396 |
397 | o 4:e860deea161a test
397 | o 4:e860deea161a test
398 | | e
398 | | e
399 | |
399 | |
400 | o 3:055a42cdd887 test
400 | o 3:055a42cdd887 test
401 | | d
401 | | d
402 | |
402 | |
403 | o 2:177f92b77385 test
403 | o 2:177f92b77385 test
404 |/ c
404 |/ c
405 |
405 |
406 o 1:d2ae7f538514 test
406 o 1:d2ae7f538514 test
407 | b
407 | b
408 |
408 |
409 o 0:cb9a9f314b8b test
409 o 0:cb9a9f314b8b test
410 a
410 a
411
411
412 $ hg rebase -s 2 -d 7 -n
412 $ hg rebase -s 2 -d 7 -n
413 starting dry-run rebase; repository will not be changed
413 starting dry-run rebase; repository will not be changed
414 rebasing 2:177f92b77385 "c"
414 rebasing 2:177f92b77385 "c"
415 rebasing 3:055a42cdd887 "d"
415 rebasing 3:055a42cdd887 "d"
416 rebasing 4:e860deea161a "e"
416 rebasing 4:e860deea161a "e"
417 merging e
417 merging e
418 transaction abort!
418 transaction abort!
419 rollback completed
419 rollback completed
420 hit a merge conflict
420 hit a merge conflict
421 [1]
421 [1]
422 $ hg diff
422 $ hg diff
423 $ hg status
423 $ hg status
424 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
424 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
425 @ 7:d2c195b28050 test
425 @ 7:d2c195b28050 test
426 | conflict with e
426 | conflict with e
427 |
427 |
428 o 6:baf10c5166d4 test
428 o 6:baf10c5166d4 test
429 | g
429 | g
430 |
430 |
431 o 5:6343ca3eff20 test
431 o 5:6343ca3eff20 test
432 | f
432 | f
433 |
433 |
434 | o 4:e860deea161a test
434 | o 4:e860deea161a test
435 | | e
435 | | e
436 | |
436 | |
437 | o 3:055a42cdd887 test
437 | o 3:055a42cdd887 test
438 | | d
438 | | d
439 | |
439 | |
440 | o 2:177f92b77385 test
440 | o 2:177f92b77385 test
441 |/ c
441 |/ c
442 |
442 |
443 o 1:d2ae7f538514 test
443 o 1:d2ae7f538514 test
444 | b
444 | b
445 |
445 |
446 o 0:cb9a9f314b8b test
446 o 0:cb9a9f314b8b test
447 a
447 a
448
448
449 Check dryrun working with --collapse when there is conflicts
449 Check dryrun working with --collapse when there is conflicts
450 $ hg rebase -s 2 -d 7 -n --collapse
450 $ hg rebase -s 2 -d 7 -n --collapse
451 starting dry-run rebase; repository will not be changed
451 starting dry-run rebase; repository will not be changed
452 rebasing 2:177f92b77385 "c"
452 rebasing 2:177f92b77385 "c"
453 rebasing 3:055a42cdd887 "d"
453 rebasing 3:055a42cdd887 "d"
454 rebasing 4:e860deea161a "e"
454 rebasing 4:e860deea161a "e"
455 merging e
455 merging e
456 hit a merge conflict
456 hit a merge conflict
457 [1]
457 [1]
458
458
459 In-memory rebase that fails due to merge conflicts
459 In-memory rebase that fails due to merge conflicts
460
460
461 $ hg rebase -s 2 -d 7
461 $ hg rebase -s 2 -d 7
462 rebasing 2:177f92b77385 "c"
462 rebasing 2:177f92b77385 "c"
463 rebasing 3:055a42cdd887 "d"
463 rebasing 3:055a42cdd887 "d"
464 rebasing 4:e860deea161a "e"
464 rebasing 4:e860deea161a "e"
465 merging e
465 merging e
466 transaction abort!
466 transaction abort!
467 rollback completed
467 rollback completed
468 hit merge conflicts; re-running rebase without in-memory merge
468 hit merge conflicts; re-running rebase without in-memory merge
469 rebasing 2:177f92b77385 "c"
469 rebasing 2:177f92b77385 "c"
470 rebasing 3:055a42cdd887 "d"
470 rebasing 3:055a42cdd887 "d"
471 rebasing 4:e860deea161a "e"
471 rebasing 4:e860deea161a "e"
472 merging e
472 merging e
473 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
473 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
474 unresolved conflicts (see hg resolve, then hg rebase --continue)
474 unresolved conflicts (see hg resolve, then hg rebase --continue)
475 [1]
475 [1]
476 $ hg rebase --abort
476 $ hg rebase --abort
477 saved backup bundle to $TESTTMP/repo3/.hg/strip-backup/c1e524d4287c-f91f82e1-backup.hg
477 saved backup bundle to $TESTTMP/repo3/.hg/strip-backup/c1e524d4287c-f91f82e1-backup.hg
478 rebase aborted
478 rebase aborted
479
479
480 Retrying without in-memory merge won't lose working copy changes
480 Retrying without in-memory merge won't lose working copy changes
481 $ cd ..
481 $ cd ..
482 $ hg clone repo3 repo3-dirty -q
482 $ hg clone repo3 repo3-dirty -q
483 $ cd repo3-dirty
483 $ cd repo3-dirty
484 $ echo dirty > a
484 $ echo dirty > a
485 $ hg rebase -s 2 -d 7
485 $ hg rebase -s 2 -d 7
486 rebasing 2:177f92b77385 "c"
486 rebasing 2:177f92b77385 "c"
487 rebasing 3:055a42cdd887 "d"
487 rebasing 3:055a42cdd887 "d"
488 rebasing 4:e860deea161a "e"
488 rebasing 4:e860deea161a "e"
489 merging e
489 merging e
490 transaction abort!
490 transaction abort!
491 rollback completed
491 rollback completed
492 hit merge conflicts; re-running rebase without in-memory merge
492 hit merge conflicts; re-running rebase without in-memory merge
493 abort: uncommitted changes
493 abort: uncommitted changes
494 [255]
494 [255]
495 $ cat a
495 $ cat a
496 dirty
496 dirty
497
497
498 Retrying without in-memory merge won't lose merge state
498 Retrying without in-memory merge won't lose merge state
499 $ cd ..
499 $ cd ..
500 $ hg clone repo3 repo3-merge-state -q
500 $ hg clone repo3 repo3-merge-state -q
501 $ cd repo3-merge-state
501 $ cd repo3-merge-state
502 $ hg merge 4
502 $ hg merge 4
503 merging e
503 merging e
504 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
504 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
505 2 files updated, 0 files merged, 0 files removed, 1 files unresolved
505 2 files updated, 0 files merged, 0 files removed, 1 files unresolved
506 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
506 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
507 [1]
507 [1]
508 $ hg resolve -l
508 $ hg resolve -l
509 U e
509 U e
510 $ hg rebase -s 2 -d 7
510 $ hg rebase -s 2 -d 7
511 abort: outstanding uncommitted merge
511 abort: outstanding uncommitted merge
512 (use 'hg commit' or 'hg merge --abort')
512 (use 'hg commit' or 'hg merge --abort')
513 [255]
513 [255]
514 $ hg resolve -l
514 $ hg resolve -l
515 U e
515 U e
516
516
517 ==========================
517 ==========================
518 Test for --confirm option|
518 Test for --confirm option|
519 ==========================
519 ==========================
520 $ cd ..
520 $ cd ..
521 $ hg clone repo3 repo4 -q
521 $ hg clone repo3 repo4 -q
522 $ cd repo4
522 $ cd repo4
523 $ hg strip 7 -q
523 $ hg strip 7 -q
524 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
524 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
525 @ 6:baf10c5166d4 test
525 @ 6:baf10c5166d4 test
526 | g
526 | g
527 |
527 |
528 o 5:6343ca3eff20 test
528 o 5:6343ca3eff20 test
529 | f
529 | f
530 |
530 |
531 | o 4:e860deea161a test
531 | o 4:e860deea161a test
532 | | e
532 | | e
533 | |
533 | |
534 | o 3:055a42cdd887 test
534 | o 3:055a42cdd887 test
535 | | d
535 | | d
536 | |
536 | |
537 | o 2:177f92b77385 test
537 | o 2:177f92b77385 test
538 |/ c
538 |/ c
539 |
539 |
540 o 1:d2ae7f538514 test
540 o 1:d2ae7f538514 test
541 | b
541 | b
542 |
542 |
543 o 0:cb9a9f314b8b test
543 o 0:cb9a9f314b8b test
544 a
544 a
545
545
546 Check it gives error when both --dryrun and --confirm is used:
546 Check it gives error when both --dryrun and --confirm is used:
547 $ hg rebase -s 2 -d . --confirm --dry-run
547 $ hg rebase -s 2 -d . --confirm --dry-run
548 abort: cannot specify both --confirm and --dry-run
548 abort: cannot specify both --confirm and --dry-run
549 [255]
549 [255]
550 $ hg rebase -s 2 -d . --confirm --abort
550 $ hg rebase -s 2 -d . --confirm --abort
551 abort: cannot specify both --confirm and --abort
551 abort: cannot specify both --abort and --confirm
552 [255]
552 [255]
553 $ hg rebase -s 2 -d . --confirm --continue
553 $ hg rebase -s 2 -d . --confirm --continue
554 abort: cannot specify both --confirm and --continue
554 abort: cannot specify both --continue and --confirm
555 [255]
555 [255]
556
556
557 Test --confirm option when there are no conflicts:
557 Test --confirm option when there are no conflicts:
558 $ hg rebase -s 2 -d . --keep --config ui.interactive=True --confirm << EOF
558 $ hg rebase -s 2 -d . --keep --config ui.interactive=True --confirm << EOF
559 > n
559 > n
560 > EOF
560 > EOF
561 starting in-memory rebase
561 starting in-memory rebase
562 rebasing 2:177f92b77385 "c"
562 rebasing 2:177f92b77385 "c"
563 rebasing 3:055a42cdd887 "d"
563 rebasing 3:055a42cdd887 "d"
564 rebasing 4:e860deea161a "e"
564 rebasing 4:e860deea161a "e"
565 rebase completed successfully
565 rebase completed successfully
566 apply changes (yn)? n
566 apply changes (yn)? n
567 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
567 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
568 @ 6:baf10c5166d4 test
568 @ 6:baf10c5166d4 test
569 | g
569 | g
570 |
570 |
571 o 5:6343ca3eff20 test
571 o 5:6343ca3eff20 test
572 | f
572 | f
573 |
573 |
574 | o 4:e860deea161a test
574 | o 4:e860deea161a test
575 | | e
575 | | e
576 | |
576 | |
577 | o 3:055a42cdd887 test
577 | o 3:055a42cdd887 test
578 | | d
578 | | d
579 | |
579 | |
580 | o 2:177f92b77385 test
580 | o 2:177f92b77385 test
581 |/ c
581 |/ c
582 |
582 |
583 o 1:d2ae7f538514 test
583 o 1:d2ae7f538514 test
584 | b
584 | b
585 |
585 |
586 o 0:cb9a9f314b8b test
586 o 0:cb9a9f314b8b test
587 a
587 a
588
588
589 $ hg rebase -s 2 -d . --keep --config ui.interactive=True --confirm << EOF
589 $ hg rebase -s 2 -d . --keep --config ui.interactive=True --confirm << EOF
590 > y
590 > y
591 > EOF
591 > EOF
592 starting in-memory rebase
592 starting in-memory rebase
593 rebasing 2:177f92b77385 "c"
593 rebasing 2:177f92b77385 "c"
594 rebasing 3:055a42cdd887 "d"
594 rebasing 3:055a42cdd887 "d"
595 rebasing 4:e860deea161a "e"
595 rebasing 4:e860deea161a "e"
596 rebase completed successfully
596 rebase completed successfully
597 apply changes (yn)? y
597 apply changes (yn)? y
598 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
598 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
599 o 9:9fd28f55f6dc test
599 o 9:9fd28f55f6dc test
600 | e
600 | e
601 |
601 |
602 o 8:12cbf031f469 test
602 o 8:12cbf031f469 test
603 | d
603 | d
604 |
604 |
605 o 7:c83b1da5b1ae test
605 o 7:c83b1da5b1ae test
606 | c
606 | c
607 |
607 |
608 @ 6:baf10c5166d4 test
608 @ 6:baf10c5166d4 test
609 | g
609 | g
610 |
610 |
611 o 5:6343ca3eff20 test
611 o 5:6343ca3eff20 test
612 | f
612 | f
613 |
613 |
614 | o 4:e860deea161a test
614 | o 4:e860deea161a test
615 | | e
615 | | e
616 | |
616 | |
617 | o 3:055a42cdd887 test
617 | o 3:055a42cdd887 test
618 | | d
618 | | d
619 | |
619 | |
620 | o 2:177f92b77385 test
620 | o 2:177f92b77385 test
621 |/ c
621 |/ c
622 |
622 |
623 o 1:d2ae7f538514 test
623 o 1:d2ae7f538514 test
624 | b
624 | b
625 |
625 |
626 o 0:cb9a9f314b8b test
626 o 0:cb9a9f314b8b test
627 a
627 a
628
628
629 Test --confirm option when there is a conflict
629 Test --confirm option when there is a conflict
630 $ hg up tip -q
630 $ hg up tip -q
631 $ echo ee>e
631 $ echo ee>e
632 $ hg ci --amend -m "conflict with e" -q
632 $ hg ci --amend -m "conflict with e" -q
633 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
633 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
634 @ 9:906d72f66a59 test
634 @ 9:906d72f66a59 test
635 | conflict with e
635 | conflict with e
636 |
636 |
637 o 8:12cbf031f469 test
637 o 8:12cbf031f469 test
638 | d
638 | d
639 |
639 |
640 o 7:c83b1da5b1ae test
640 o 7:c83b1da5b1ae test
641 | c
641 | c
642 |
642 |
643 o 6:baf10c5166d4 test
643 o 6:baf10c5166d4 test
644 | g
644 | g
645 |
645 |
646 o 5:6343ca3eff20 test
646 o 5:6343ca3eff20 test
647 | f
647 | f
648 |
648 |
649 | o 4:e860deea161a test
649 | o 4:e860deea161a test
650 | | e
650 | | e
651 | |
651 | |
652 | o 3:055a42cdd887 test
652 | o 3:055a42cdd887 test
653 | | d
653 | | d
654 | |
654 | |
655 | o 2:177f92b77385 test
655 | o 2:177f92b77385 test
656 |/ c
656 |/ c
657 |
657 |
658 o 1:d2ae7f538514 test
658 o 1:d2ae7f538514 test
659 | b
659 | b
660 |
660 |
661 o 0:cb9a9f314b8b test
661 o 0:cb9a9f314b8b test
662 a
662 a
663
663
664 $ hg rebase -s 4 -d . --keep --confirm
664 $ hg rebase -s 4 -d . --keep --confirm
665 starting in-memory rebase
665 starting in-memory rebase
666 rebasing 4:e860deea161a "e"
666 rebasing 4:e860deea161a "e"
667 merging e
667 merging e
668 hit a merge conflict
668 hit a merge conflict
669 [1]
669 [1]
670 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
670 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
671 @ 9:906d72f66a59 test
671 @ 9:906d72f66a59 test
672 | conflict with e
672 | conflict with e
673 |
673 |
674 o 8:12cbf031f469 test
674 o 8:12cbf031f469 test
675 | d
675 | d
676 |
676 |
677 o 7:c83b1da5b1ae test
677 o 7:c83b1da5b1ae test
678 | c
678 | c
679 |
679 |
680 o 6:baf10c5166d4 test
680 o 6:baf10c5166d4 test
681 | g
681 | g
682 |
682 |
683 o 5:6343ca3eff20 test
683 o 5:6343ca3eff20 test
684 | f
684 | f
685 |
685 |
686 | o 4:e860deea161a test
686 | o 4:e860deea161a test
687 | | e
687 | | e
688 | |
688 | |
689 | o 3:055a42cdd887 test
689 | o 3:055a42cdd887 test
690 | | d
690 | | d
691 | |
691 | |
692 | o 2:177f92b77385 test
692 | o 2:177f92b77385 test
693 |/ c
693 |/ c
694 |
694 |
695 o 1:d2ae7f538514 test
695 o 1:d2ae7f538514 test
696 | b
696 | b
697 |
697 |
698 o 0:cb9a9f314b8b test
698 o 0:cb9a9f314b8b test
699 a
699 a
700
700
701 Test a metadata-only in-memory merge
701 Test a metadata-only in-memory merge
702 $ cd $TESTTMP
702 $ cd $TESTTMP
703 $ hg init no_exception
703 $ hg init no_exception
704 $ cd no_exception
704 $ cd no_exception
705 # Produce the following graph:
705 # Produce the following graph:
706 # o 'add +x to foo.txt'
706 # o 'add +x to foo.txt'
707 # | o r1 (adds bar.txt, just for something to rebase to)
707 # | o r1 (adds bar.txt, just for something to rebase to)
708 # |/
708 # |/
709 # o r0 (adds foo.txt, no +x)
709 # o r0 (adds foo.txt, no +x)
710 $ echo hi > foo.txt
710 $ echo hi > foo.txt
711 $ hg ci -qAm r0
711 $ hg ci -qAm r0
712 $ echo hi > bar.txt
712 $ echo hi > bar.txt
713 $ hg ci -qAm r1
713 $ hg ci -qAm r1
714 $ hg co -qr ".^"
714 $ hg co -qr ".^"
715 $ chmod +x foo.txt
715 $ chmod +x foo.txt
716 $ hg ci -qAm 'add +x to foo.txt'
716 $ hg ci -qAm 'add +x to foo.txt'
717 issue5960: this was raising an AttributeError exception
717 issue5960: this was raising an AttributeError exception
718 $ hg rebase -r . -d 1
718 $ hg rebase -r . -d 1
719 rebasing 2:539b93e77479 "add +x to foo.txt" (tip)
719 rebasing 2:539b93e77479 "add +x to foo.txt" (tip)
720 saved backup bundle to $TESTTMP/no_exception/.hg/strip-backup/*.hg (glob)
720 saved backup bundle to $TESTTMP/no_exception/.hg/strip-backup/*.hg (glob)
721 $ hg diff -c tip
721 $ hg diff -c tip
722 diff --git a/foo.txt b/foo.txt
722 diff --git a/foo.txt b/foo.txt
723 old mode 100644
723 old mode 100644
724 new mode 100755
724 new mode 100755
725
725
726 Test rebasing a commit with copy information, but no content changes
726 Test rebasing a commit with copy information, but no content changes
727
727
728 $ cd ..
728 $ cd ..
729 $ hg clone -q repo1 merge-and-rename
729 $ hg clone -q repo1 merge-and-rename
730 $ cd merge-and-rename
730 $ cd merge-and-rename
731 $ cat << EOF >> .hg/hgrc
731 $ cat << EOF >> .hg/hgrc
732 > [experimental]
732 > [experimental]
733 > evolution.createmarkers=True
733 > evolution.createmarkers=True
734 > evolution.allowunstable=True
734 > evolution.allowunstable=True
735 > EOF
735 > EOF
736 $ hg co -q 1
736 $ hg co -q 1
737 $ hg mv d e
737 $ hg mv d e
738 $ hg ci -qm 'rename d to e'
738 $ hg ci -qm 'rename d to e'
739 $ hg co -q 3
739 $ hg co -q 3
740 $ hg merge -q 4
740 $ hg merge -q 4
741 $ hg ci -m 'merge'
741 $ hg ci -m 'merge'
742 $ hg co -q 2
742 $ hg co -q 2
743 $ mv d e
743 $ mv d e
744 $ hg addremove -qs 0
744 $ hg addremove -qs 0
745 $ hg ci -qm 'untracked rename of d to e'
745 $ hg ci -qm 'untracked rename of d to e'
746 $ hg debugobsolete -q `hg log -T '{node}' -r 4` `hg log -T '{node}' -r .`
746 $ hg debugobsolete -q `hg log -T '{node}' -r 4` `hg log -T '{node}' -r .`
747 1 new orphan changesets
747 1 new orphan changesets
748 $ hg tglog
748 $ hg tglog
749 @ 6: 676538af172d 'untracked rename of d to e'
749 @ 6: 676538af172d 'untracked rename of d to e'
750 |
750 |
751 | * 5: 574d92ad16fc 'merge'
751 | * 5: 574d92ad16fc 'merge'
752 | |\
752 | |\
753 | | x 4: 2c8b5dad7956 'rename d to e'
753 | | x 4: 2c8b5dad7956 'rename d to e'
754 | | |
754 | | |
755 | o | 3: ca58782ad1e4 'b'
755 | o | 3: ca58782ad1e4 'b'
756 |/ /
756 |/ /
757 o / 2: 814f6bd05178 'c'
757 o / 2: 814f6bd05178 'c'
758 |/
758 |/
759 o 1: 02952614a83d 'd'
759 o 1: 02952614a83d 'd'
760 |
760 |
761 o 0: b173517d0057 'a'
761 o 0: b173517d0057 'a'
762
762
763 $ hg rebase -b 5 -d tip
763 $ hg rebase -b 5 -d tip
764 rebasing 3:ca58782ad1e4 "b"
764 rebasing 3:ca58782ad1e4 "b"
765 rebasing 5:574d92ad16fc "merge"
765 rebasing 5:574d92ad16fc "merge"
766 note: not rebasing 5:574d92ad16fc "merge", its destination already has all its changes
766 note: not rebasing 5:574d92ad16fc "merge", its destination already has all its changes
767
767
768 $ cd ..
768 $ cd ..
769
769
770 Test rebasing a commit with copy information
770 Test rebasing a commit with copy information
771
771
772 $ hg init rebase-rename
772 $ hg init rebase-rename
773 $ cd rebase-rename
773 $ cd rebase-rename
774 $ echo a > a
774 $ echo a > a
775 $ hg ci -Aqm 'add a'
775 $ hg ci -Aqm 'add a'
776 $ echo a2 > a
776 $ echo a2 > a
777 $ hg ci -m 'modify a'
777 $ hg ci -m 'modify a'
778 $ hg co -q 0
778 $ hg co -q 0
779 $ hg mv a b
779 $ hg mv a b
780 $ hg ci -qm 'rename a to b'
780 $ hg ci -qm 'rename a to b'
781 $ hg rebase -d 1
781 $ hg rebase -d 1
782 rebasing 2:b977edf6f839 "rename a to b" (tip)
782 rebasing 2:b977edf6f839 "rename a to b" (tip)
783 merging a and b to b
783 merging a and b to b
784 saved backup bundle to $TESTTMP/rebase-rename/.hg/strip-backup/b977edf6f839-0864f570-rebase.hg
784 saved backup bundle to $TESTTMP/rebase-rename/.hg/strip-backup/b977edf6f839-0864f570-rebase.hg
785 $ hg st --copies --change .
785 $ hg st --copies --change .
786 A b
786 A b
787 a
787 a
788 R a
788 R a
789 $ cd ..
789 $ cd ..
790
790
791 Test rebasing a commit with copy information, where the target is empty
791 Test rebasing a commit with copy information, where the target is empty
792
792
793 $ hg init rebase-rename-empty
793 $ hg init rebase-rename-empty
794 $ cd rebase-rename-empty
794 $ cd rebase-rename-empty
795 $ echo a > a
795 $ echo a > a
796 $ hg ci -Aqm 'add a'
796 $ hg ci -Aqm 'add a'
797 $ cat > a
797 $ cat > a
798 $ hg ci -m 'make a empty'
798 $ hg ci -m 'make a empty'
799 $ hg co -q 0
799 $ hg co -q 0
800 $ hg mv a b
800 $ hg mv a b
801 $ hg ci -qm 'rename a to b'
801 $ hg ci -qm 'rename a to b'
802 $ hg rebase -d 1
802 $ hg rebase -d 1
803 rebasing 2:b977edf6f839 "rename a to b" (tip)
803 rebasing 2:b977edf6f839 "rename a to b" (tip)
804 merging a and b to b
804 merging a and b to b
805 saved backup bundle to $TESTTMP/rebase-rename-empty/.hg/strip-backup/b977edf6f839-0864f570-rebase.hg
805 saved backup bundle to $TESTTMP/rebase-rename-empty/.hg/strip-backup/b977edf6f839-0864f570-rebase.hg
806 $ hg st --copies --change .
806 $ hg st --copies --change .
807 A b
807 A b
808 a
808 a
809 R a
809 R a
810 $ cd ..
810 $ cd ..
811 Rebase across a copy with --collapse
811 Rebase across a copy with --collapse
812
812
813 $ hg init rebase-rename-collapse
813 $ hg init rebase-rename-collapse
814 $ cd rebase-rename-collapse
814 $ cd rebase-rename-collapse
815 $ echo a > a
815 $ echo a > a
816 $ hg ci -Aqm 'add a'
816 $ hg ci -Aqm 'add a'
817 $ hg mv a b
817 $ hg mv a b
818 $ hg ci -m 'rename a to b'
818 $ hg ci -m 'rename a to b'
819 $ hg co -q 0
819 $ hg co -q 0
820 $ echo a2 > a
820 $ echo a2 > a
821 $ hg ci -qm 'modify a'
821 $ hg ci -qm 'modify a'
822 $ hg rebase -r . -d 1 --collapse
822 $ hg rebase -r . -d 1 --collapse
823 rebasing 2:41c4ea50d4cf "modify a" (tip)
823 rebasing 2:41c4ea50d4cf "modify a" (tip)
824 merging b and a to b
824 merging b and a to b
825 saved backup bundle to $TESTTMP/rebase-rename-collapse/.hg/strip-backup/41c4ea50d4cf-b90b7994-rebase.hg
825 saved backup bundle to $TESTTMP/rebase-rename-collapse/.hg/strip-backup/41c4ea50d4cf-b90b7994-rebase.hg
826 $ cd ..
826 $ cd ..
827
827
828 Test rebasing when the file we are merging in destination is empty
828 Test rebasing when the file we are merging in destination is empty
829
829
830 $ hg init test
830 $ hg init test
831 $ cd test
831 $ cd test
832 $ echo a > foo
832 $ echo a > foo
833 $ hg ci -Aqm 'added a to foo'
833 $ hg ci -Aqm 'added a to foo'
834
834
835 $ rm foo
835 $ rm foo
836 $ touch foo
836 $ touch foo
837 $ hg di
837 $ hg di
838 diff --git a/foo b/foo
838 diff --git a/foo b/foo
839 --- a/foo
839 --- a/foo
840 +++ b/foo
840 +++ b/foo
841 @@ -1,1 +0,0 @@
841 @@ -1,1 +0,0 @@
842 -a
842 -a
843
843
844 $ hg ci -m "make foo an empty file"
844 $ hg ci -m "make foo an empty file"
845
845
846 $ hg up '.^'
846 $ hg up '.^'
847 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
847 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
848 $ echo b > foo
848 $ echo b > foo
849 $ hg di
849 $ hg di
850 diff --git a/foo b/foo
850 diff --git a/foo b/foo
851 --- a/foo
851 --- a/foo
852 +++ b/foo
852 +++ b/foo
853 @@ -1,1 +1,1 @@
853 @@ -1,1 +1,1 @@
854 -a
854 -a
855 +b
855 +b
856 $ hg ci -m "add b to foo"
856 $ hg ci -m "add b to foo"
857 created new head
857 created new head
858
858
859 $ hg rebase -r . -d 1 --config ui.merge=internal:merge3
859 $ hg rebase -r . -d 1 --config ui.merge=internal:merge3
860 rebasing 2:fb62b706688e "add b to foo" (tip)
860 rebasing 2:fb62b706688e "add b to foo" (tip)
861 merging foo
861 merging foo
862 hit merge conflicts; re-running rebase without in-memory merge
862 hit merge conflicts; re-running rebase without in-memory merge
863 rebasing 2:fb62b706688e "add b to foo" (tip)
863 rebasing 2:fb62b706688e "add b to foo" (tip)
864 merging foo
864 merging foo
865 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
865 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
866 unresolved conflicts (see hg resolve, then hg rebase --continue)
866 unresolved conflicts (see hg resolve, then hg rebase --continue)
867 [1]
867 [1]
868
868
869 $ cd $TESTTMP
869 $ cd $TESTTMP
870
870
871 Test rebasing when we're in the middle of a rebase already
871 Test rebasing when we're in the middle of a rebase already
872 $ hg init test_issue6214
872 $ hg init test_issue6214
873 $ cd test_issue6214
873 $ cd test_issue6214
874 $ echo r0 > r0
874 $ echo r0 > r0
875 $ hg ci -qAm 'r0'
875 $ hg ci -qAm 'r0'
876 $ echo hi > foo
876 $ echo hi > foo
877 $ hg ci -qAm 'hi from foo'
877 $ hg ci -qAm 'hi from foo'
878 $ hg co -q '.^'
878 $ hg co -q '.^'
879 $ echo bye > foo
879 $ echo bye > foo
880 $ hg ci -qAm 'bye from foo'
880 $ hg ci -qAm 'bye from foo'
881 $ hg co -q '.^'
881 $ hg co -q '.^'
882 $ echo unrelated > some_other_file
882 $ echo unrelated > some_other_file
883 $ hg ci -qAm 'some unrelated changes'
883 $ hg ci -qAm 'some unrelated changes'
884 $ hg log -G -T'{rev}: {desc}\n{files%"{file}\n"}'
884 $ hg log -G -T'{rev}: {desc}\n{files%"{file}\n"}'
885 @ 3: some unrelated changes
885 @ 3: some unrelated changes
886 | some_other_file
886 | some_other_file
887 | o 2: bye from foo
887 | o 2: bye from foo
888 |/ foo
888 |/ foo
889 | o 1: hi from foo
889 | o 1: hi from foo
890 |/ foo
890 |/ foo
891 o 0: r0
891 o 0: r0
892 r0
892 r0
893 $ hg rebase -r 2 -d 1 -t:merge3
893 $ hg rebase -r 2 -d 1 -t:merge3
894 rebasing 2:b4d249fbf8dd "bye from foo"
894 rebasing 2:b4d249fbf8dd "bye from foo"
895 merging foo
895 merging foo
896 hit merge conflicts; re-running rebase without in-memory merge
896 hit merge conflicts; re-running rebase without in-memory merge
897 rebasing 2:b4d249fbf8dd "bye from foo"
897 rebasing 2:b4d249fbf8dd "bye from foo"
898 merging foo
898 merging foo
899 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
899 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
900 unresolved conflicts (see hg resolve, then hg rebase --continue)
900 unresolved conflicts (see hg resolve, then hg rebase --continue)
901 [1]
901 [1]
902 $ hg rebase -r 3 -d 1 -t:merge3
902 $ hg rebase -r 3 -d 1 -t:merge3
903 abort: rebase in progress
903 abort: rebase in progress
904 (use 'hg rebase --continue' or 'hg rebase --abort')
904 (use 'hg rebase --continue' or 'hg rebase --abort')
905 [255]
905 [255]
906 $ hg resolve --list
906 $ hg resolve --list
907 U foo
907 U foo
908 $ hg resolve --all --re-merge -t:other
908 $ hg resolve --all --re-merge -t:other
909 (no more unresolved files)
909 (no more unresolved files)
910 continue: hg rebase --continue
910 continue: hg rebase --continue
911 $ hg rebase --continue
911 $ hg rebase --continue
912 rebasing 2:b4d249fbf8dd "bye from foo"
912 rebasing 2:b4d249fbf8dd "bye from foo"
913 saved backup bundle to $TESTTMP/test_issue6214/.hg/strip-backup/b4d249fbf8dd-299ec25c-rebase.hg
913 saved backup bundle to $TESTTMP/test_issue6214/.hg/strip-backup/b4d249fbf8dd-299ec25c-rebase.hg
914 $ hg log -G -T'{rev}: {desc}\n{files%"{file}\n"}'
914 $ hg log -G -T'{rev}: {desc}\n{files%"{file}\n"}'
915 o 3: bye from foo
915 o 3: bye from foo
916 | foo
916 | foo
917 | @ 2: some unrelated changes
917 | @ 2: some unrelated changes
918 | | some_other_file
918 | | some_other_file
919 o | 1: hi from foo
919 o | 1: hi from foo
920 |/ foo
920 |/ foo
921 o 0: r0
921 o 0: r0
922 r0
922 r0
@@ -1,2142 +1,2142 b''
1 ==========================
1 ==========================
2 Test rebase with obsolete
2 Test rebase with obsolete
3 ==========================
3 ==========================
4
4
5 Enable obsolete
5 Enable obsolete
6
6
7 $ cat >> $HGRCPATH << EOF
7 $ cat >> $HGRCPATH << EOF
8 > [ui]
8 > [ui]
9 > logtemplate= {rev}:{node|short} {desc|firstline}{if(obsolete,' ({obsfate})')}
9 > logtemplate= {rev}:{node|short} {desc|firstline}{if(obsolete,' ({obsfate})')}
10 > [experimental]
10 > [experimental]
11 > evolution.createmarkers=True
11 > evolution.createmarkers=True
12 > evolution.allowunstable=True
12 > evolution.allowunstable=True
13 > [phases]
13 > [phases]
14 > publish=False
14 > publish=False
15 > [extensions]
15 > [extensions]
16 > rebase=
16 > rebase=
17 > drawdag=$TESTDIR/drawdag.py
17 > drawdag=$TESTDIR/drawdag.py
18 > strip=
18 > strip=
19 > EOF
19 > EOF
20
20
21 Setup rebase canonical repo
21 Setup rebase canonical repo
22
22
23 $ hg init base
23 $ hg init base
24 $ cd base
24 $ cd base
25 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
25 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
26 adding changesets
26 adding changesets
27 adding manifests
27 adding manifests
28 adding file changes
28 adding file changes
29 added 8 changesets with 7 changes to 7 files (+2 heads)
29 added 8 changesets with 7 changes to 7 files (+2 heads)
30 new changesets cd010b8cd998:02de42196ebe (8 drafts)
30 new changesets cd010b8cd998:02de42196ebe (8 drafts)
31 (run 'hg heads' to see heads, 'hg merge' to merge)
31 (run 'hg heads' to see heads, 'hg merge' to merge)
32 $ hg up tip
32 $ hg up tip
33 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
33 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
34 $ hg log -G
34 $ hg log -G
35 @ 7:02de42196ebe H
35 @ 7:02de42196ebe H
36 |
36 |
37 | o 6:eea13746799a G
37 | o 6:eea13746799a G
38 |/|
38 |/|
39 o | 5:24b6387c8c8c F
39 o | 5:24b6387c8c8c F
40 | |
40 | |
41 | o 4:9520eea781bc E
41 | o 4:9520eea781bc E
42 |/
42 |/
43 | o 3:32af7686d403 D
43 | o 3:32af7686d403 D
44 | |
44 | |
45 | o 2:5fddd98957c8 C
45 | o 2:5fddd98957c8 C
46 | |
46 | |
47 | o 1:42ccdea3bb16 B
47 | o 1:42ccdea3bb16 B
48 |/
48 |/
49 o 0:cd010b8cd998 A
49 o 0:cd010b8cd998 A
50
50
51 $ cd ..
51 $ cd ..
52
52
53 simple rebase
53 simple rebase
54 ---------------------------------
54 ---------------------------------
55
55
56 $ hg clone base simple
56 $ hg clone base simple
57 updating to branch default
57 updating to branch default
58 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
58 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
59 $ cd simple
59 $ cd simple
60 $ hg up 32af7686d403
60 $ hg up 32af7686d403
61 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
61 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
62 $ hg rebase -d eea13746799a
62 $ hg rebase -d eea13746799a
63 rebasing 1:42ccdea3bb16 "B"
63 rebasing 1:42ccdea3bb16 "B"
64 rebasing 2:5fddd98957c8 "C"
64 rebasing 2:5fddd98957c8 "C"
65 rebasing 3:32af7686d403 "D"
65 rebasing 3:32af7686d403 "D"
66 $ hg log -G
66 $ hg log -G
67 @ 10:8eeb3c33ad33 D
67 @ 10:8eeb3c33ad33 D
68 |
68 |
69 o 9:2327fea05063 C
69 o 9:2327fea05063 C
70 |
70 |
71 o 8:e4e5be0395b2 B
71 o 8:e4e5be0395b2 B
72 |
72 |
73 | o 7:02de42196ebe H
73 | o 7:02de42196ebe H
74 | |
74 | |
75 o | 6:eea13746799a G
75 o | 6:eea13746799a G
76 |\|
76 |\|
77 | o 5:24b6387c8c8c F
77 | o 5:24b6387c8c8c F
78 | |
78 | |
79 o | 4:9520eea781bc E
79 o | 4:9520eea781bc E
80 |/
80 |/
81 o 0:cd010b8cd998 A
81 o 0:cd010b8cd998 A
82
82
83 $ hg log --hidden -G
83 $ hg log --hidden -G
84 @ 10:8eeb3c33ad33 D
84 @ 10:8eeb3c33ad33 D
85 |
85 |
86 o 9:2327fea05063 C
86 o 9:2327fea05063 C
87 |
87 |
88 o 8:e4e5be0395b2 B
88 o 8:e4e5be0395b2 B
89 |
89 |
90 | o 7:02de42196ebe H
90 | o 7:02de42196ebe H
91 | |
91 | |
92 o | 6:eea13746799a G
92 o | 6:eea13746799a G
93 |\|
93 |\|
94 | o 5:24b6387c8c8c F
94 | o 5:24b6387c8c8c F
95 | |
95 | |
96 o | 4:9520eea781bc E
96 o | 4:9520eea781bc E
97 |/
97 |/
98 | x 3:32af7686d403 D (rewritten using rebase as 10:8eeb3c33ad33)
98 | x 3:32af7686d403 D (rewritten using rebase as 10:8eeb3c33ad33)
99 | |
99 | |
100 | x 2:5fddd98957c8 C (rewritten using rebase as 9:2327fea05063)
100 | x 2:5fddd98957c8 C (rewritten using rebase as 9:2327fea05063)
101 | |
101 | |
102 | x 1:42ccdea3bb16 B (rewritten using rebase as 8:e4e5be0395b2)
102 | x 1:42ccdea3bb16 B (rewritten using rebase as 8:e4e5be0395b2)
103 |/
103 |/
104 o 0:cd010b8cd998 A
104 o 0:cd010b8cd998 A
105
105
106 $ hg debugobsolete
106 $ hg debugobsolete
107 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 e4e5be0395b2cbd471ed22a26b1b6a1a0658a794 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
107 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 e4e5be0395b2cbd471ed22a26b1b6a1a0658a794 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
108 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 2327fea05063f39961b14cb69435a9898dc9a245 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
108 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 2327fea05063f39961b14cb69435a9898dc9a245 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
109 32af7686d403cf45b5d95f2d70cebea587ac806a 8eeb3c33ad33d452c89e5dcf611c347f978fb42b 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
109 32af7686d403cf45b5d95f2d70cebea587ac806a 8eeb3c33ad33d452c89e5dcf611c347f978fb42b 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
110
110
111
111
112 $ cd ..
112 $ cd ..
113
113
114 empty changeset
114 empty changeset
115 ---------------------------------
115 ---------------------------------
116
116
117 $ hg clone base empty
117 $ hg clone base empty
118 updating to branch default
118 updating to branch default
119 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
119 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
120 $ cd empty
120 $ cd empty
121 $ hg up eea13746799a
121 $ hg up eea13746799a
122 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
122 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
123
123
124 We make a copy of both the first changeset in the rebased and some other in the
124 We make a copy of both the first changeset in the rebased and some other in the
125 set.
125 set.
126
126
127 $ hg graft 42ccdea3bb16 32af7686d403
127 $ hg graft 42ccdea3bb16 32af7686d403
128 grafting 1:42ccdea3bb16 "B"
128 grafting 1:42ccdea3bb16 "B"
129 grafting 3:32af7686d403 "D"
129 grafting 3:32af7686d403 "D"
130 $ hg rebase -s 42ccdea3bb16 -d .
130 $ hg rebase -s 42ccdea3bb16 -d .
131 rebasing 1:42ccdea3bb16 "B"
131 rebasing 1:42ccdea3bb16 "B"
132 note: not rebasing 1:42ccdea3bb16 "B", its destination already has all its changes
132 note: not rebasing 1:42ccdea3bb16 "B", its destination already has all its changes
133 rebasing 2:5fddd98957c8 "C"
133 rebasing 2:5fddd98957c8 "C"
134 rebasing 3:32af7686d403 "D"
134 rebasing 3:32af7686d403 "D"
135 note: not rebasing 3:32af7686d403 "D", its destination already has all its changes
135 note: not rebasing 3:32af7686d403 "D", its destination already has all its changes
136 $ hg log -G
136 $ hg log -G
137 o 10:5ae4c968c6ac C
137 o 10:5ae4c968c6ac C
138 |
138 |
139 @ 9:08483444fef9 D
139 @ 9:08483444fef9 D
140 |
140 |
141 o 8:8877864f1edb B
141 o 8:8877864f1edb B
142 |
142 |
143 | o 7:02de42196ebe H
143 | o 7:02de42196ebe H
144 | |
144 | |
145 o | 6:eea13746799a G
145 o | 6:eea13746799a G
146 |\|
146 |\|
147 | o 5:24b6387c8c8c F
147 | o 5:24b6387c8c8c F
148 | |
148 | |
149 o | 4:9520eea781bc E
149 o | 4:9520eea781bc E
150 |/
150 |/
151 o 0:cd010b8cd998 A
151 o 0:cd010b8cd998 A
152
152
153 $ hg log --hidden -G
153 $ hg log --hidden -G
154 o 10:5ae4c968c6ac C
154 o 10:5ae4c968c6ac C
155 |
155 |
156 @ 9:08483444fef9 D
156 @ 9:08483444fef9 D
157 |
157 |
158 o 8:8877864f1edb B
158 o 8:8877864f1edb B
159 |
159 |
160 | o 7:02de42196ebe H
160 | o 7:02de42196ebe H
161 | |
161 | |
162 o | 6:eea13746799a G
162 o | 6:eea13746799a G
163 |\|
163 |\|
164 | o 5:24b6387c8c8c F
164 | o 5:24b6387c8c8c F
165 | |
165 | |
166 o | 4:9520eea781bc E
166 o | 4:9520eea781bc E
167 |/
167 |/
168 | x 3:32af7686d403 D (pruned using rebase)
168 | x 3:32af7686d403 D (pruned using rebase)
169 | |
169 | |
170 | x 2:5fddd98957c8 C (rewritten using rebase as 10:5ae4c968c6ac)
170 | x 2:5fddd98957c8 C (rewritten using rebase as 10:5ae4c968c6ac)
171 | |
171 | |
172 | x 1:42ccdea3bb16 B (pruned using rebase)
172 | x 1:42ccdea3bb16 B (pruned using rebase)
173 |/
173 |/
174 o 0:cd010b8cd998 A
174 o 0:cd010b8cd998 A
175
175
176 $ hg debugobsolete
176 $ hg debugobsolete
177 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
177 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
178 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
178 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
179 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
179 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
180
180
181
181
182 More complex case where part of the rebase set were already rebased
182 More complex case where part of the rebase set were already rebased
183
183
184 $ hg rebase --rev 'desc(D)' --dest 'desc(H)'
184 $ hg rebase --rev 'desc(D)' --dest 'desc(H)'
185 rebasing 9:08483444fef9 "D"
185 rebasing 9:08483444fef9 "D"
186 1 new orphan changesets
186 1 new orphan changesets
187 $ hg debugobsolete
187 $ hg debugobsolete
188 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
188 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
189 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
189 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
190 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
190 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
191 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
191 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
192 $ hg log -G
192 $ hg log -G
193 @ 11:4596109a6a43 D
193 @ 11:4596109a6a43 D
194 |
194 |
195 | * 10:5ae4c968c6ac C
195 | * 10:5ae4c968c6ac C
196 | |
196 | |
197 | x 9:08483444fef9 D (rewritten using rebase as 11:4596109a6a43)
197 | x 9:08483444fef9 D (rewritten using rebase as 11:4596109a6a43)
198 | |
198 | |
199 | o 8:8877864f1edb B
199 | o 8:8877864f1edb B
200 | |
200 | |
201 o | 7:02de42196ebe H
201 o | 7:02de42196ebe H
202 | |
202 | |
203 | o 6:eea13746799a G
203 | o 6:eea13746799a G
204 |/|
204 |/|
205 o | 5:24b6387c8c8c F
205 o | 5:24b6387c8c8c F
206 | |
206 | |
207 | o 4:9520eea781bc E
207 | o 4:9520eea781bc E
208 |/
208 |/
209 o 0:cd010b8cd998 A
209 o 0:cd010b8cd998 A
210
210
211 $ hg rebase --source 'desc(B)' --dest 'tip' --config experimental.rebaseskipobsolete=True
211 $ hg rebase --source 'desc(B)' --dest 'tip' --config experimental.rebaseskipobsolete=True
212 rebasing 8:8877864f1edb "B"
212 rebasing 8:8877864f1edb "B"
213 note: not rebasing 9:08483444fef9 "D", already in destination as 11:4596109a6a43 "D" (tip)
213 note: not rebasing 9:08483444fef9 "D", already in destination as 11:4596109a6a43 "D" (tip)
214 rebasing 10:5ae4c968c6ac "C"
214 rebasing 10:5ae4c968c6ac "C"
215 $ hg debugobsolete
215 $ hg debugobsolete
216 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
216 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {cd010b8cd998f3981a5a8115f94f8da4ab506089} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
217 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
217 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
218 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
218 32af7686d403cf45b5d95f2d70cebea587ac806a 0 {5fddd98957c8a54a4d436dfe1da9d87f21a1b97b} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'operation': 'rebase', 'user': 'test'}
219 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
219 08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
220 8877864f1edb05d0e07dc4ba77b67a80a7b86672 462a34d07e599b87ea08676a449373fe4e2e1347 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
220 8877864f1edb05d0e07dc4ba77b67a80a7b86672 462a34d07e599b87ea08676a449373fe4e2e1347 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
221 5ae4c968c6aca831df823664e706c9d4aa34473d 98f6af4ee9539e14da4465128f894c274900b6e5 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
221 5ae4c968c6aca831df823664e706c9d4aa34473d 98f6af4ee9539e14da4465128f894c274900b6e5 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
222 $ hg log --rev 'contentdivergent()'
222 $ hg log --rev 'contentdivergent()'
223 $ hg log -G
223 $ hg log -G
224 o 13:98f6af4ee953 C
224 o 13:98f6af4ee953 C
225 |
225 |
226 o 12:462a34d07e59 B
226 o 12:462a34d07e59 B
227 |
227 |
228 @ 11:4596109a6a43 D
228 @ 11:4596109a6a43 D
229 |
229 |
230 o 7:02de42196ebe H
230 o 7:02de42196ebe H
231 |
231 |
232 | o 6:eea13746799a G
232 | o 6:eea13746799a G
233 |/|
233 |/|
234 o | 5:24b6387c8c8c F
234 o | 5:24b6387c8c8c F
235 | |
235 | |
236 | o 4:9520eea781bc E
236 | o 4:9520eea781bc E
237 |/
237 |/
238 o 0:cd010b8cd998 A
238 o 0:cd010b8cd998 A
239
239
240 $ hg log --style default --debug -r 4596109a6a4328c398bde3a4a3b6737cfade3003
240 $ hg log --style default --debug -r 4596109a6a4328c398bde3a4a3b6737cfade3003
241 changeset: 11:4596109a6a4328c398bde3a4a3b6737cfade3003
241 changeset: 11:4596109a6a4328c398bde3a4a3b6737cfade3003
242 phase: draft
242 phase: draft
243 parent: 7:02de42196ebee42ef284b6780a87cdc96e8eaab6
243 parent: 7:02de42196ebee42ef284b6780a87cdc96e8eaab6
244 parent: -1:0000000000000000000000000000000000000000
244 parent: -1:0000000000000000000000000000000000000000
245 manifest: 11:a91006e3a02f1edf631f7018e6e5684cf27dd905
245 manifest: 11:a91006e3a02f1edf631f7018e6e5684cf27dd905
246 user: Nicolas Dumazet <nicdumz.commits@gmail.com>
246 user: Nicolas Dumazet <nicdumz.commits@gmail.com>
247 date: Sat Apr 30 15:24:48 2011 +0200
247 date: Sat Apr 30 15:24:48 2011 +0200
248 files+: D
248 files+: D
249 extra: branch=default
249 extra: branch=default
250 extra: rebase_source=08483444fef91d6224f6655ee586a65d263ad34c
250 extra: rebase_source=08483444fef91d6224f6655ee586a65d263ad34c
251 extra: source=32af7686d403cf45b5d95f2d70cebea587ac806a
251 extra: source=32af7686d403cf45b5d95f2d70cebea587ac806a
252 description:
252 description:
253 D
253 D
254
254
255
255
256 $ hg up -qr 'desc(G)'
256 $ hg up -qr 'desc(G)'
257 $ hg graft 4596109a6a4328c398bde3a4a3b6737cfade3003
257 $ hg graft 4596109a6a4328c398bde3a4a3b6737cfade3003
258 grafting 11:4596109a6a43 "D"
258 grafting 11:4596109a6a43 "D"
259 $ hg up -qr 'desc(E)'
259 $ hg up -qr 'desc(E)'
260 $ hg rebase -s tip -d .
260 $ hg rebase -s tip -d .
261 rebasing 14:9e36056a46e3 "D" (tip)
261 rebasing 14:9e36056a46e3 "D" (tip)
262 $ hg log --style default --debug -r tip
262 $ hg log --style default --debug -r tip
263 changeset: 15:627d4614809036ba22b9e7cb31638ddc06ab99ab
263 changeset: 15:627d4614809036ba22b9e7cb31638ddc06ab99ab
264 tag: tip
264 tag: tip
265 phase: draft
265 phase: draft
266 parent: 4:9520eea781bcca16c1e15acc0ba14335a0e8e5ba
266 parent: 4:9520eea781bcca16c1e15acc0ba14335a0e8e5ba
267 parent: -1:0000000000000000000000000000000000000000
267 parent: -1:0000000000000000000000000000000000000000
268 manifest: 15:648e8ede73ae3e497d093d3a4c8fcc2daa864f42
268 manifest: 15:648e8ede73ae3e497d093d3a4c8fcc2daa864f42
269 user: Nicolas Dumazet <nicdumz.commits@gmail.com>
269 user: Nicolas Dumazet <nicdumz.commits@gmail.com>
270 date: Sat Apr 30 15:24:48 2011 +0200
270 date: Sat Apr 30 15:24:48 2011 +0200
271 files+: D
271 files+: D
272 extra: branch=default
272 extra: branch=default
273 extra: intermediate-source=4596109a6a4328c398bde3a4a3b6737cfade3003
273 extra: intermediate-source=4596109a6a4328c398bde3a4a3b6737cfade3003
274 extra: rebase_source=9e36056a46e37c9776168c7375734eebc70e294f
274 extra: rebase_source=9e36056a46e37c9776168c7375734eebc70e294f
275 extra: source=32af7686d403cf45b5d95f2d70cebea587ac806a
275 extra: source=32af7686d403cf45b5d95f2d70cebea587ac806a
276 description:
276 description:
277 D
277 D
278
278
279
279
280 Start rebase from a commit that is obsolete but not hidden only because it's
280 Start rebase from a commit that is obsolete but not hidden only because it's
281 a working copy parent. We should be moved back to the starting commit as usual
281 a working copy parent. We should be moved back to the starting commit as usual
282 even though it is hidden (until we're moved there).
282 even though it is hidden (until we're moved there).
283
283
284 $ hg --hidden up -qr 'first(hidden())'
284 $ hg --hidden up -qr 'first(hidden())'
285 updated to hidden changeset 42ccdea3bb16
285 updated to hidden changeset 42ccdea3bb16
286 (hidden revision '42ccdea3bb16' is pruned)
286 (hidden revision '42ccdea3bb16' is pruned)
287 $ hg rebase --rev 13 --dest 15
287 $ hg rebase --rev 13 --dest 15
288 rebasing 13:98f6af4ee953 "C"
288 rebasing 13:98f6af4ee953 "C"
289 $ hg log -G
289 $ hg log -G
290 o 16:294a2b93eb4d C
290 o 16:294a2b93eb4d C
291 |
291 |
292 o 15:627d46148090 D
292 o 15:627d46148090 D
293 |
293 |
294 | o 12:462a34d07e59 B
294 | o 12:462a34d07e59 B
295 | |
295 | |
296 | o 11:4596109a6a43 D
296 | o 11:4596109a6a43 D
297 | |
297 | |
298 | o 7:02de42196ebe H
298 | o 7:02de42196ebe H
299 | |
299 | |
300 +---o 6:eea13746799a G
300 +---o 6:eea13746799a G
301 | |/
301 | |/
302 | o 5:24b6387c8c8c F
302 | o 5:24b6387c8c8c F
303 | |
303 | |
304 o | 4:9520eea781bc E
304 o | 4:9520eea781bc E
305 |/
305 |/
306 | @ 1:42ccdea3bb16 B (pruned using rebase)
306 | @ 1:42ccdea3bb16 B (pruned using rebase)
307 |/
307 |/
308 o 0:cd010b8cd998 A
308 o 0:cd010b8cd998 A
309
309
310
310
311 $ cd ..
311 $ cd ..
312
312
313 collapse rebase
313 collapse rebase
314 ---------------------------------
314 ---------------------------------
315
315
316 $ hg clone base collapse
316 $ hg clone base collapse
317 updating to branch default
317 updating to branch default
318 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
318 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
319 $ cd collapse
319 $ cd collapse
320 $ hg rebase -s 42ccdea3bb16 -d eea13746799a --collapse
320 $ hg rebase -s 42ccdea3bb16 -d eea13746799a --collapse
321 rebasing 1:42ccdea3bb16 "B"
321 rebasing 1:42ccdea3bb16 "B"
322 rebasing 2:5fddd98957c8 "C"
322 rebasing 2:5fddd98957c8 "C"
323 rebasing 3:32af7686d403 "D"
323 rebasing 3:32af7686d403 "D"
324 $ hg log -G
324 $ hg log -G
325 o 8:4dc2197e807b Collapsed revision
325 o 8:4dc2197e807b Collapsed revision
326 |
326 |
327 | @ 7:02de42196ebe H
327 | @ 7:02de42196ebe H
328 | |
328 | |
329 o | 6:eea13746799a G
329 o | 6:eea13746799a G
330 |\|
330 |\|
331 | o 5:24b6387c8c8c F
331 | o 5:24b6387c8c8c F
332 | |
332 | |
333 o | 4:9520eea781bc E
333 o | 4:9520eea781bc E
334 |/
334 |/
335 o 0:cd010b8cd998 A
335 o 0:cd010b8cd998 A
336
336
337 $ hg log --hidden -G
337 $ hg log --hidden -G
338 o 8:4dc2197e807b Collapsed revision
338 o 8:4dc2197e807b Collapsed revision
339 |
339 |
340 | @ 7:02de42196ebe H
340 | @ 7:02de42196ebe H
341 | |
341 | |
342 o | 6:eea13746799a G
342 o | 6:eea13746799a G
343 |\|
343 |\|
344 | o 5:24b6387c8c8c F
344 | o 5:24b6387c8c8c F
345 | |
345 | |
346 o | 4:9520eea781bc E
346 o | 4:9520eea781bc E
347 |/
347 |/
348 | x 3:32af7686d403 D (rewritten using rebase as 8:4dc2197e807b)
348 | x 3:32af7686d403 D (rewritten using rebase as 8:4dc2197e807b)
349 | |
349 | |
350 | x 2:5fddd98957c8 C (rewritten using rebase as 8:4dc2197e807b)
350 | x 2:5fddd98957c8 C (rewritten using rebase as 8:4dc2197e807b)
351 | |
351 | |
352 | x 1:42ccdea3bb16 B (rewritten using rebase as 8:4dc2197e807b)
352 | x 1:42ccdea3bb16 B (rewritten using rebase as 8:4dc2197e807b)
353 |/
353 |/
354 o 0:cd010b8cd998 A
354 o 0:cd010b8cd998 A
355
355
356 $ hg id --debug -r tip
356 $ hg id --debug -r tip
357 4dc2197e807bae9817f09905b50ab288be2dbbcf tip
357 4dc2197e807bae9817f09905b50ab288be2dbbcf tip
358 $ hg debugobsolete
358 $ hg debugobsolete
359 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'fold-id': '6fb65cdc', 'fold-idx': '1', 'fold-size': '3', 'operation': 'rebase', 'user': 'test'}
359 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'fold-id': '6fb65cdc', 'fold-idx': '1', 'fold-size': '3', 'operation': 'rebase', 'user': 'test'}
360 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'fold-id': '6fb65cdc', 'fold-idx': '2', 'fold-size': '3', 'operation': 'rebase', 'user': 'test'}
360 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'fold-id': '6fb65cdc', 'fold-idx': '2', 'fold-size': '3', 'operation': 'rebase', 'user': 'test'}
361 32af7686d403cf45b5d95f2d70cebea587ac806a 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'fold-id': '6fb65cdc', 'fold-idx': '3', 'fold-size': '3', 'operation': 'rebase', 'user': 'test'}
361 32af7686d403cf45b5d95f2d70cebea587ac806a 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '13', 'fold-id': '6fb65cdc', 'fold-idx': '3', 'fold-size': '3', 'operation': 'rebase', 'user': 'test'}
362
362
363 $ cd ..
363 $ cd ..
364
364
365 Rebase set has hidden descendants
365 Rebase set has hidden descendants
366 ---------------------------------
366 ---------------------------------
367
367
368 We rebase a changeset which has hidden descendants. Hidden changesets must not
368 We rebase a changeset which has hidden descendants. Hidden changesets must not
369 be rebased.
369 be rebased.
370
370
371 $ hg clone base hidden
371 $ hg clone base hidden
372 updating to branch default
372 updating to branch default
373 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
373 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
374 $ cd hidden
374 $ cd hidden
375 $ hg log -G
375 $ hg log -G
376 @ 7:02de42196ebe H
376 @ 7:02de42196ebe H
377 |
377 |
378 | o 6:eea13746799a G
378 | o 6:eea13746799a G
379 |/|
379 |/|
380 o | 5:24b6387c8c8c F
380 o | 5:24b6387c8c8c F
381 | |
381 | |
382 | o 4:9520eea781bc E
382 | o 4:9520eea781bc E
383 |/
383 |/
384 | o 3:32af7686d403 D
384 | o 3:32af7686d403 D
385 | |
385 | |
386 | o 2:5fddd98957c8 C
386 | o 2:5fddd98957c8 C
387 | |
387 | |
388 | o 1:42ccdea3bb16 B
388 | o 1:42ccdea3bb16 B
389 |/
389 |/
390 o 0:cd010b8cd998 A
390 o 0:cd010b8cd998 A
391
391
392 $ hg rebase -s 5fddd98957c8 -d eea13746799a
392 $ hg rebase -s 5fddd98957c8 -d eea13746799a
393 rebasing 2:5fddd98957c8 "C"
393 rebasing 2:5fddd98957c8 "C"
394 rebasing 3:32af7686d403 "D"
394 rebasing 3:32af7686d403 "D"
395 $ hg log -G
395 $ hg log -G
396 o 9:cf44d2f5a9f4 D
396 o 9:cf44d2f5a9f4 D
397 |
397 |
398 o 8:e273c5e7d2d2 C
398 o 8:e273c5e7d2d2 C
399 |
399 |
400 | @ 7:02de42196ebe H
400 | @ 7:02de42196ebe H
401 | |
401 | |
402 o | 6:eea13746799a G
402 o | 6:eea13746799a G
403 |\|
403 |\|
404 | o 5:24b6387c8c8c F
404 | o 5:24b6387c8c8c F
405 | |
405 | |
406 o | 4:9520eea781bc E
406 o | 4:9520eea781bc E
407 |/
407 |/
408 | o 1:42ccdea3bb16 B
408 | o 1:42ccdea3bb16 B
409 |/
409 |/
410 o 0:cd010b8cd998 A
410 o 0:cd010b8cd998 A
411
411
412 $ hg rebase -s 42ccdea3bb16 -d 02de42196ebe
412 $ hg rebase -s 42ccdea3bb16 -d 02de42196ebe
413 rebasing 1:42ccdea3bb16 "B"
413 rebasing 1:42ccdea3bb16 "B"
414 $ hg log -G
414 $ hg log -G
415 o 10:7c6027df6a99 B
415 o 10:7c6027df6a99 B
416 |
416 |
417 | o 9:cf44d2f5a9f4 D
417 | o 9:cf44d2f5a9f4 D
418 | |
418 | |
419 | o 8:e273c5e7d2d2 C
419 | o 8:e273c5e7d2d2 C
420 | |
420 | |
421 @ | 7:02de42196ebe H
421 @ | 7:02de42196ebe H
422 | |
422 | |
423 | o 6:eea13746799a G
423 | o 6:eea13746799a G
424 |/|
424 |/|
425 o | 5:24b6387c8c8c F
425 o | 5:24b6387c8c8c F
426 | |
426 | |
427 | o 4:9520eea781bc E
427 | o 4:9520eea781bc E
428 |/
428 |/
429 o 0:cd010b8cd998 A
429 o 0:cd010b8cd998 A
430
430
431 $ hg log --hidden -G
431 $ hg log --hidden -G
432 o 10:7c6027df6a99 B
432 o 10:7c6027df6a99 B
433 |
433 |
434 | o 9:cf44d2f5a9f4 D
434 | o 9:cf44d2f5a9f4 D
435 | |
435 | |
436 | o 8:e273c5e7d2d2 C
436 | o 8:e273c5e7d2d2 C
437 | |
437 | |
438 @ | 7:02de42196ebe H
438 @ | 7:02de42196ebe H
439 | |
439 | |
440 | o 6:eea13746799a G
440 | o 6:eea13746799a G
441 |/|
441 |/|
442 o | 5:24b6387c8c8c F
442 o | 5:24b6387c8c8c F
443 | |
443 | |
444 | o 4:9520eea781bc E
444 | o 4:9520eea781bc E
445 |/
445 |/
446 | x 3:32af7686d403 D (rewritten using rebase as 9:cf44d2f5a9f4)
446 | x 3:32af7686d403 D (rewritten using rebase as 9:cf44d2f5a9f4)
447 | |
447 | |
448 | x 2:5fddd98957c8 C (rewritten using rebase as 8:e273c5e7d2d2)
448 | x 2:5fddd98957c8 C (rewritten using rebase as 8:e273c5e7d2d2)
449 | |
449 | |
450 | x 1:42ccdea3bb16 B (rewritten using rebase as 10:7c6027df6a99)
450 | x 1:42ccdea3bb16 B (rewritten using rebase as 10:7c6027df6a99)
451 |/
451 |/
452 o 0:cd010b8cd998 A
452 o 0:cd010b8cd998 A
453
453
454 $ hg debugobsolete
454 $ hg debugobsolete
455 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b e273c5e7d2d29df783dce9f9eaa3ac4adc69c15d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
455 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b e273c5e7d2d29df783dce9f9eaa3ac4adc69c15d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
456 32af7686d403cf45b5d95f2d70cebea587ac806a cf44d2f5a9f4297a62be94cbdd3dff7c7dc54258 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
456 32af7686d403cf45b5d95f2d70cebea587ac806a cf44d2f5a9f4297a62be94cbdd3dff7c7dc54258 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
457 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 7c6027df6a99d93f461868e5433f63bde20b6dfb 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
457 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 7c6027df6a99d93f461868e5433f63bde20b6dfb 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
458
458
459 Test that rewriting leaving instability behind is allowed
459 Test that rewriting leaving instability behind is allowed
460 ---------------------------------------------------------------------
460 ---------------------------------------------------------------------
461
461
462 $ hg log -r 'children(8)'
462 $ hg log -r 'children(8)'
463 9:cf44d2f5a9f4 D (no-eol)
463 9:cf44d2f5a9f4 D (no-eol)
464 $ hg rebase -r 8
464 $ hg rebase -r 8
465 rebasing 8:e273c5e7d2d2 "C"
465 rebasing 8:e273c5e7d2d2 "C"
466 1 new orphan changesets
466 1 new orphan changesets
467 $ hg log -G
467 $ hg log -G
468 o 11:0d8f238b634c C
468 o 11:0d8f238b634c C
469 |
469 |
470 o 10:7c6027df6a99 B
470 o 10:7c6027df6a99 B
471 |
471 |
472 | * 9:cf44d2f5a9f4 D
472 | * 9:cf44d2f5a9f4 D
473 | |
473 | |
474 | x 8:e273c5e7d2d2 C (rewritten using rebase as 11:0d8f238b634c)
474 | x 8:e273c5e7d2d2 C (rewritten using rebase as 11:0d8f238b634c)
475 | |
475 | |
476 @ | 7:02de42196ebe H
476 @ | 7:02de42196ebe H
477 | |
477 | |
478 | o 6:eea13746799a G
478 | o 6:eea13746799a G
479 |/|
479 |/|
480 o | 5:24b6387c8c8c F
480 o | 5:24b6387c8c8c F
481 | |
481 | |
482 | o 4:9520eea781bc E
482 | o 4:9520eea781bc E
483 |/
483 |/
484 o 0:cd010b8cd998 A
484 o 0:cd010b8cd998 A
485
485
486 $ cd ..
486 $ cd ..
487 $ cp -R hidden stabilize
487 $ cp -R hidden stabilize
488 $ cd stabilize
488 $ cd stabilize
489 $ hg rebase --auto-orphans '0::' -d 10
489 $ hg rebase --auto-orphans '0::' -d 10
490 abort: --auto-orphans is incompatible with --dest
490 abort: --auto-orphans is incompatible with --dest
491 [255]
491 [255]
492 $ hg rebase --auto-orphans '0::'
492 $ hg rebase --auto-orphans '0::'
493 rebasing 9:cf44d2f5a9f4 "D"
493 rebasing 9:cf44d2f5a9f4 "D"
494 $ hg log -G
494 $ hg log -G
495 o 12:7e3935feaa68 D
495 o 12:7e3935feaa68 D
496 |
496 |
497 o 11:0d8f238b634c C
497 o 11:0d8f238b634c C
498 |
498 |
499 o 10:7c6027df6a99 B
499 o 10:7c6027df6a99 B
500 |
500 |
501 @ 7:02de42196ebe H
501 @ 7:02de42196ebe H
502 |
502 |
503 | o 6:eea13746799a G
503 | o 6:eea13746799a G
504 |/|
504 |/|
505 o | 5:24b6387c8c8c F
505 o | 5:24b6387c8c8c F
506 | |
506 | |
507 | o 4:9520eea781bc E
507 | o 4:9520eea781bc E
508 |/
508 |/
509 o 0:cd010b8cd998 A
509 o 0:cd010b8cd998 A
510
510
511
511
512 $ cd ../hidden
512 $ cd ../hidden
513 $ rm -r ../stabilize
513 $ rm -r ../stabilize
514
514
515 Test multiple root handling
515 Test multiple root handling
516 ------------------------------------
516 ------------------------------------
517
517
518 $ hg rebase --dest 4 --rev '7+11+9'
518 $ hg rebase --dest 4 --rev '7+11+9'
519 rebasing 9:cf44d2f5a9f4 "D"
519 rebasing 9:cf44d2f5a9f4 "D"
520 rebasing 7:02de42196ebe "H"
520 rebasing 7:02de42196ebe "H"
521 rebasing 11:0d8f238b634c "C" (tip)
521 rebasing 11:0d8f238b634c "C" (tip)
522 $ hg log -G
522 $ hg log -G
523 o 14:1e8370e38cca C
523 o 14:1e8370e38cca C
524 |
524 |
525 @ 13:bfe264faf697 H
525 @ 13:bfe264faf697 H
526 |
526 |
527 | o 12:102b4c1d889b D
527 | o 12:102b4c1d889b D
528 |/
528 |/
529 | * 10:7c6027df6a99 B
529 | * 10:7c6027df6a99 B
530 | |
530 | |
531 | x 7:02de42196ebe H (rewritten using rebase as 13:bfe264faf697)
531 | x 7:02de42196ebe H (rewritten using rebase as 13:bfe264faf697)
532 | |
532 | |
533 +---o 6:eea13746799a G
533 +---o 6:eea13746799a G
534 | |/
534 | |/
535 | o 5:24b6387c8c8c F
535 | o 5:24b6387c8c8c F
536 | |
536 | |
537 o | 4:9520eea781bc E
537 o | 4:9520eea781bc E
538 |/
538 |/
539 o 0:cd010b8cd998 A
539 o 0:cd010b8cd998 A
540
540
541 $ cd ..
541 $ cd ..
542
542
543 Detach both parents
543 Detach both parents
544
544
545 $ hg init double-detach
545 $ hg init double-detach
546 $ cd double-detach
546 $ cd double-detach
547
547
548 $ hg debugdrawdag <<EOF
548 $ hg debugdrawdag <<EOF
549 > F
549 > F
550 > /|
550 > /|
551 > C E
551 > C E
552 > | |
552 > | |
553 > B D G
553 > B D G
554 > \|/
554 > \|/
555 > A
555 > A
556 > EOF
556 > EOF
557
557
558 $ hg rebase -d G -r 'B + D + F'
558 $ hg rebase -d G -r 'B + D + F'
559 rebasing 1:112478962961 "B" (B)
559 rebasing 1:112478962961 "B" (B)
560 rebasing 2:b18e25de2cf5 "D" (D)
560 rebasing 2:b18e25de2cf5 "D" (D)
561 rebasing 6:f15c3adaf214 "F" (F tip)
561 rebasing 6:f15c3adaf214 "F" (F tip)
562 abort: cannot rebase 6:f15c3adaf214 without moving at least one of its parents
562 abort: cannot rebase 6:f15c3adaf214 without moving at least one of its parents
563 [255]
563 [255]
564
564
565 $ cd ..
565 $ cd ..
566
566
567 test on rebase dropping a merge
567 test on rebase dropping a merge
568
568
569 (setup)
569 (setup)
570
570
571 $ hg init dropmerge
571 $ hg init dropmerge
572 $ cd dropmerge
572 $ cd dropmerge
573 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
573 $ hg unbundle "$TESTDIR/bundles/rebase.hg"
574 adding changesets
574 adding changesets
575 adding manifests
575 adding manifests
576 adding file changes
576 adding file changes
577 added 8 changesets with 7 changes to 7 files (+2 heads)
577 added 8 changesets with 7 changes to 7 files (+2 heads)
578 new changesets cd010b8cd998:02de42196ebe (8 drafts)
578 new changesets cd010b8cd998:02de42196ebe (8 drafts)
579 (run 'hg heads' to see heads, 'hg merge' to merge)
579 (run 'hg heads' to see heads, 'hg merge' to merge)
580 $ hg up 3
580 $ hg up 3
581 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
581 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
582 $ hg merge 7
582 $ hg merge 7
583 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
583 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
584 (branch merge, don't forget to commit)
584 (branch merge, don't forget to commit)
585 $ hg ci -m 'M'
585 $ hg ci -m 'M'
586 $ echo I > I
586 $ echo I > I
587 $ hg add I
587 $ hg add I
588 $ hg ci -m I
588 $ hg ci -m I
589 $ hg log -G
589 $ hg log -G
590 @ 9:4bde274eefcf I
590 @ 9:4bde274eefcf I
591 |
591 |
592 o 8:53a6a128b2b7 M
592 o 8:53a6a128b2b7 M
593 |\
593 |\
594 | o 7:02de42196ebe H
594 | o 7:02de42196ebe H
595 | |
595 | |
596 | | o 6:eea13746799a G
596 | | o 6:eea13746799a G
597 | |/|
597 | |/|
598 | o | 5:24b6387c8c8c F
598 | o | 5:24b6387c8c8c F
599 | | |
599 | | |
600 | | o 4:9520eea781bc E
600 | | o 4:9520eea781bc E
601 | |/
601 | |/
602 o | 3:32af7686d403 D
602 o | 3:32af7686d403 D
603 | |
603 | |
604 o | 2:5fddd98957c8 C
604 o | 2:5fddd98957c8 C
605 | |
605 | |
606 o | 1:42ccdea3bb16 B
606 o | 1:42ccdea3bb16 B
607 |/
607 |/
608 o 0:cd010b8cd998 A
608 o 0:cd010b8cd998 A
609
609
610 (actual test)
610 (actual test)
611
611
612 $ hg rebase --dest 6 --rev '((desc(H) + desc(D))::) - desc(M)'
612 $ hg rebase --dest 6 --rev '((desc(H) + desc(D))::) - desc(M)'
613 rebasing 3:32af7686d403 "D"
613 rebasing 3:32af7686d403 "D"
614 rebasing 7:02de42196ebe "H"
614 rebasing 7:02de42196ebe "H"
615 rebasing 9:4bde274eefcf "I" (tip)
615 rebasing 9:4bde274eefcf "I" (tip)
616 1 new orphan changesets
616 1 new orphan changesets
617 $ hg log -G
617 $ hg log -G
618 @ 12:acd174b7ab39 I
618 @ 12:acd174b7ab39 I
619 |
619 |
620 o 11:6c11a6218c97 H
620 o 11:6c11a6218c97 H
621 |
621 |
622 | o 10:b5313c85b22e D
622 | o 10:b5313c85b22e D
623 |/
623 |/
624 | * 8:53a6a128b2b7 M
624 | * 8:53a6a128b2b7 M
625 | |\
625 | |\
626 | | x 7:02de42196ebe H (rewritten using rebase as 11:6c11a6218c97)
626 | | x 7:02de42196ebe H (rewritten using rebase as 11:6c11a6218c97)
627 | | |
627 | | |
628 o---+ 6:eea13746799a G
628 o---+ 6:eea13746799a G
629 | | |
629 | | |
630 | | o 5:24b6387c8c8c F
630 | | o 5:24b6387c8c8c F
631 | | |
631 | | |
632 o---+ 4:9520eea781bc E
632 o---+ 4:9520eea781bc E
633 / /
633 / /
634 x | 3:32af7686d403 D (rewritten using rebase as 10:b5313c85b22e)
634 x | 3:32af7686d403 D (rewritten using rebase as 10:b5313c85b22e)
635 | |
635 | |
636 o | 2:5fddd98957c8 C
636 o | 2:5fddd98957c8 C
637 | |
637 | |
638 o | 1:42ccdea3bb16 B
638 o | 1:42ccdea3bb16 B
639 |/
639 |/
640 o 0:cd010b8cd998 A
640 o 0:cd010b8cd998 A
641
641
642
642
643 Test hidden changesets in the rebase set (issue4504)
643 Test hidden changesets in the rebase set (issue4504)
644
644
645 $ hg up --hidden 9
645 $ hg up --hidden 9
646 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
646 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
647 updated to hidden changeset 4bde274eefcf
647 updated to hidden changeset 4bde274eefcf
648 (hidden revision '4bde274eefcf' was rewritten as: acd174b7ab39)
648 (hidden revision '4bde274eefcf' was rewritten as: acd174b7ab39)
649 $ echo J > J
649 $ echo J > J
650 $ hg add J
650 $ hg add J
651 $ hg commit -m J
651 $ hg commit -m J
652 1 new orphan changesets
652 1 new orphan changesets
653 $ hg debugobsolete `hg log --rev . -T '{node}'`
653 $ hg debugobsolete `hg log --rev . -T '{node}'`
654 1 new obsolescence markers
654 1 new obsolescence markers
655 obsoleted 1 changesets
655 obsoleted 1 changesets
656
656
657 $ hg rebase --rev .~1::. --dest 'max(desc(D))' --traceback --config experimental.rebaseskipobsolete=off
657 $ hg rebase --rev .~1::. --dest 'max(desc(D))' --traceback --config experimental.rebaseskipobsolete=off
658 rebasing 9:4bde274eefcf "I"
658 rebasing 9:4bde274eefcf "I"
659 rebasing 13:06edfc82198f "J" (tip)
659 rebasing 13:06edfc82198f "J" (tip)
660 2 new content-divergent changesets
660 2 new content-divergent changesets
661 $ hg log -G
661 $ hg log -G
662 @ 15:5ae8a643467b J
662 @ 15:5ae8a643467b J
663 |
663 |
664 * 14:9ad579b4a5de I
664 * 14:9ad579b4a5de I
665 |
665 |
666 | * 12:acd174b7ab39 I
666 | * 12:acd174b7ab39 I
667 | |
667 | |
668 | o 11:6c11a6218c97 H
668 | o 11:6c11a6218c97 H
669 | |
669 | |
670 o | 10:b5313c85b22e D
670 o | 10:b5313c85b22e D
671 |/
671 |/
672 | * 8:53a6a128b2b7 M
672 | * 8:53a6a128b2b7 M
673 | |\
673 | |\
674 | | x 7:02de42196ebe H (rewritten using rebase as 11:6c11a6218c97)
674 | | x 7:02de42196ebe H (rewritten using rebase as 11:6c11a6218c97)
675 | | |
675 | | |
676 o---+ 6:eea13746799a G
676 o---+ 6:eea13746799a G
677 | | |
677 | | |
678 | | o 5:24b6387c8c8c F
678 | | o 5:24b6387c8c8c F
679 | | |
679 | | |
680 o---+ 4:9520eea781bc E
680 o---+ 4:9520eea781bc E
681 / /
681 / /
682 x | 3:32af7686d403 D (rewritten using rebase as 10:b5313c85b22e)
682 x | 3:32af7686d403 D (rewritten using rebase as 10:b5313c85b22e)
683 | |
683 | |
684 o | 2:5fddd98957c8 C
684 o | 2:5fddd98957c8 C
685 | |
685 | |
686 o | 1:42ccdea3bb16 B
686 o | 1:42ccdea3bb16 B
687 |/
687 |/
688 o 0:cd010b8cd998 A
688 o 0:cd010b8cd998 A
689
689
690 $ hg up 14 -C
690 $ hg up 14 -C
691 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
691 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
692 $ echo "K" > K
692 $ echo "K" > K
693 $ hg add K
693 $ hg add K
694 $ hg commit --amend -m "K"
694 $ hg commit --amend -m "K"
695 1 new orphan changesets
695 1 new orphan changesets
696 $ echo "L" > L
696 $ echo "L" > L
697 $ hg add L
697 $ hg add L
698 $ hg commit -m "L"
698 $ hg commit -m "L"
699 $ hg up '.^'
699 $ hg up '.^'
700 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
700 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
701 $ echo "M" > M
701 $ echo "M" > M
702 $ hg add M
702 $ hg add M
703 $ hg commit --amend -m "M"
703 $ hg commit --amend -m "M"
704 1 new orphan changesets
704 1 new orphan changesets
705 $ hg log -G
705 $ hg log -G
706 @ 18:bfaedf8eb73b M
706 @ 18:bfaedf8eb73b M
707 |
707 |
708 | * 17:97219452e4bd L
708 | * 17:97219452e4bd L
709 | |
709 | |
710 | x 16:fc37a630c901 K (rewritten using amend as 18:bfaedf8eb73b)
710 | x 16:fc37a630c901 K (rewritten using amend as 18:bfaedf8eb73b)
711 |/
711 |/
712 | * 15:5ae8a643467b J
712 | * 15:5ae8a643467b J
713 | |
713 | |
714 | x 14:9ad579b4a5de I (rewritten using amend as 16:fc37a630c901)
714 | x 14:9ad579b4a5de I (rewritten using amend as 16:fc37a630c901)
715 |/
715 |/
716 | * 12:acd174b7ab39 I
716 | * 12:acd174b7ab39 I
717 | |
717 | |
718 | o 11:6c11a6218c97 H
718 | o 11:6c11a6218c97 H
719 | |
719 | |
720 o | 10:b5313c85b22e D
720 o | 10:b5313c85b22e D
721 |/
721 |/
722 | * 8:53a6a128b2b7 M
722 | * 8:53a6a128b2b7 M
723 | |\
723 | |\
724 | | x 7:02de42196ebe H (rewritten using rebase as 11:6c11a6218c97)
724 | | x 7:02de42196ebe H (rewritten using rebase as 11:6c11a6218c97)
725 | | |
725 | | |
726 o---+ 6:eea13746799a G
726 o---+ 6:eea13746799a G
727 | | |
727 | | |
728 | | o 5:24b6387c8c8c F
728 | | o 5:24b6387c8c8c F
729 | | |
729 | | |
730 o---+ 4:9520eea781bc E
730 o---+ 4:9520eea781bc E
731 / /
731 / /
732 x | 3:32af7686d403 D (rewritten using rebase as 10:b5313c85b22e)
732 x | 3:32af7686d403 D (rewritten using rebase as 10:b5313c85b22e)
733 | |
733 | |
734 o | 2:5fddd98957c8 C
734 o | 2:5fddd98957c8 C
735 | |
735 | |
736 o | 1:42ccdea3bb16 B
736 o | 1:42ccdea3bb16 B
737 |/
737 |/
738 o 0:cd010b8cd998 A
738 o 0:cd010b8cd998 A
739
739
740 $ hg rebase -s 14 -d 17 --config experimental.rebaseskipobsolete=True
740 $ hg rebase -s 14 -d 17 --config experimental.rebaseskipobsolete=True
741 note: not rebasing 14:9ad579b4a5de "I", already in destination as 16:fc37a630c901 "K"
741 note: not rebasing 14:9ad579b4a5de "I", already in destination as 16:fc37a630c901 "K"
742 rebasing 15:5ae8a643467b "J"
742 rebasing 15:5ae8a643467b "J"
743 1 new orphan changesets
743 1 new orphan changesets
744
744
745 $ cd ..
745 $ cd ..
746
746
747 Skip obsolete changeset even with multiple hops
747 Skip obsolete changeset even with multiple hops
748 -----------------------------------------------
748 -----------------------------------------------
749
749
750 setup
750 setup
751
751
752 $ hg init obsskip
752 $ hg init obsskip
753 $ cd obsskip
753 $ cd obsskip
754 $ cat << EOF >> .hg/hgrc
754 $ cat << EOF >> .hg/hgrc
755 > [experimental]
755 > [experimental]
756 > rebaseskipobsolete = True
756 > rebaseskipobsolete = True
757 > [extensions]
757 > [extensions]
758 > strip =
758 > strip =
759 > EOF
759 > EOF
760 $ echo A > A
760 $ echo A > A
761 $ hg add A
761 $ hg add A
762 $ hg commit -m A
762 $ hg commit -m A
763 $ echo B > B
763 $ echo B > B
764 $ hg add B
764 $ hg add B
765 $ hg commit -m B0
765 $ hg commit -m B0
766 $ hg commit --amend -m B1
766 $ hg commit --amend -m B1
767 $ hg commit --amend -m B2
767 $ hg commit --amend -m B2
768 $ hg up --hidden 'desc(B0)'
768 $ hg up --hidden 'desc(B0)'
769 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
769 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
770 updated to hidden changeset a8b11f55fb19
770 updated to hidden changeset a8b11f55fb19
771 (hidden revision 'a8b11f55fb19' was rewritten as: 261e70097290)
771 (hidden revision 'a8b11f55fb19' was rewritten as: 261e70097290)
772 $ echo C > C
772 $ echo C > C
773 $ hg add C
773 $ hg add C
774 $ hg commit -m C
774 $ hg commit -m C
775 1 new orphan changesets
775 1 new orphan changesets
776 $ hg log -G
776 $ hg log -G
777 @ 4:212cb178bcbb C
777 @ 4:212cb178bcbb C
778 |
778 |
779 | o 3:261e70097290 B2
779 | o 3:261e70097290 B2
780 | |
780 | |
781 x | 1:a8b11f55fb19 B0 (rewritten using amend as 3:261e70097290)
781 x | 1:a8b11f55fb19 B0 (rewritten using amend as 3:261e70097290)
782 |/
782 |/
783 o 0:4a2df7238c3b A
783 o 0:4a2df7238c3b A
784
784
785
785
786 Rebase finds its way in a chain of marker
786 Rebase finds its way in a chain of marker
787
787
788 $ hg rebase -d 'desc(B2)'
788 $ hg rebase -d 'desc(B2)'
789 note: not rebasing 1:a8b11f55fb19 "B0", already in destination as 3:261e70097290 "B2"
789 note: not rebasing 1:a8b11f55fb19 "B0", already in destination as 3:261e70097290 "B2"
790 rebasing 4:212cb178bcbb "C" (tip)
790 rebasing 4:212cb178bcbb "C" (tip)
791
791
792 Even when the chain include missing node
792 Even when the chain include missing node
793
793
794 $ hg up --hidden 'desc(B0)'
794 $ hg up --hidden 'desc(B0)'
795 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
795 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
796 updated to hidden changeset a8b11f55fb19
796 updated to hidden changeset a8b11f55fb19
797 (hidden revision 'a8b11f55fb19' was rewritten as: 261e70097290)
797 (hidden revision 'a8b11f55fb19' was rewritten as: 261e70097290)
798 $ echo D > D
798 $ echo D > D
799 $ hg add D
799 $ hg add D
800 $ hg commit -m D
800 $ hg commit -m D
801 1 new orphan changesets
801 1 new orphan changesets
802 $ hg --hidden strip -r 'desc(B1)'
802 $ hg --hidden strip -r 'desc(B1)'
803 saved backup bundle to $TESTTMP/obsskip/.hg/strip-backup/86f6414ccda7-b1c452ee-backup.hg
803 saved backup bundle to $TESTTMP/obsskip/.hg/strip-backup/86f6414ccda7-b1c452ee-backup.hg
804 1 new orphan changesets
804 1 new orphan changesets
805 $ hg log -G
805 $ hg log -G
806 @ 5:1a79b7535141 D
806 @ 5:1a79b7535141 D
807 |
807 |
808 | o 4:ff2c4d47b71d C
808 | o 4:ff2c4d47b71d C
809 | |
809 | |
810 | o 2:261e70097290 B2
810 | o 2:261e70097290 B2
811 | |
811 | |
812 x | 1:a8b11f55fb19 B0 (rewritten using amend as 2:261e70097290)
812 x | 1:a8b11f55fb19 B0 (rewritten using amend as 2:261e70097290)
813 |/
813 |/
814 o 0:4a2df7238c3b A
814 o 0:4a2df7238c3b A
815
815
816
816
817 $ hg rebase -d 'desc(B2)'
817 $ hg rebase -d 'desc(B2)'
818 note: not rebasing 1:a8b11f55fb19 "B0", already in destination as 2:261e70097290 "B2"
818 note: not rebasing 1:a8b11f55fb19 "B0", already in destination as 2:261e70097290 "B2"
819 rebasing 5:1a79b7535141 "D" (tip)
819 rebasing 5:1a79b7535141 "D" (tip)
820 $ hg up 4
820 $ hg up 4
821 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
821 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
822 $ echo "O" > O
822 $ echo "O" > O
823 $ hg add O
823 $ hg add O
824 $ hg commit -m O
824 $ hg commit -m O
825 $ echo "P" > P
825 $ echo "P" > P
826 $ hg add P
826 $ hg add P
827 $ hg commit -m P
827 $ hg commit -m P
828 $ hg log -G
828 $ hg log -G
829 @ 8:8d47583e023f P
829 @ 8:8d47583e023f P
830 |
830 |
831 o 7:360bbaa7d3ce O
831 o 7:360bbaa7d3ce O
832 |
832 |
833 | o 6:9c48361117de D
833 | o 6:9c48361117de D
834 | |
834 | |
835 o | 4:ff2c4d47b71d C
835 o | 4:ff2c4d47b71d C
836 |/
836 |/
837 o 2:261e70097290 B2
837 o 2:261e70097290 B2
838 |
838 |
839 o 0:4a2df7238c3b A
839 o 0:4a2df7238c3b A
840
840
841 $ hg debugobsolete `hg log -r 7 -T '{node}\n'` --config experimental.evolution=true
841 $ hg debugobsolete `hg log -r 7 -T '{node}\n'` --config experimental.evolution=true
842 1 new obsolescence markers
842 1 new obsolescence markers
843 obsoleted 1 changesets
843 obsoleted 1 changesets
844 1 new orphan changesets
844 1 new orphan changesets
845 $ hg rebase -d 6 -r "4::"
845 $ hg rebase -d 6 -r "4::"
846 rebasing 4:ff2c4d47b71d "C"
846 rebasing 4:ff2c4d47b71d "C"
847 note: not rebasing 7:360bbaa7d3ce "O", it has no successor
847 note: not rebasing 7:360bbaa7d3ce "O", it has no successor
848 rebasing 8:8d47583e023f "P" (tip)
848 rebasing 8:8d47583e023f "P" (tip)
849
849
850 If all the changeset to be rebased are obsolete and present in the destination, we
850 If all the changeset to be rebased are obsolete and present in the destination, we
851 should display a friendly error message
851 should display a friendly error message
852
852
853 $ hg log -G
853 $ hg log -G
854 @ 10:121d9e3bc4c6 P
854 @ 10:121d9e3bc4c6 P
855 |
855 |
856 o 9:4be60e099a77 C
856 o 9:4be60e099a77 C
857 |
857 |
858 o 6:9c48361117de D
858 o 6:9c48361117de D
859 |
859 |
860 o 2:261e70097290 B2
860 o 2:261e70097290 B2
861 |
861 |
862 o 0:4a2df7238c3b A
862 o 0:4a2df7238c3b A
863
863
864
864
865 $ hg up 9
865 $ hg up 9
866 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
866 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
867 $ echo "non-relevant change" > nonrelevant
867 $ echo "non-relevant change" > nonrelevant
868 $ hg add nonrelevant
868 $ hg add nonrelevant
869 $ hg commit -m nonrelevant
869 $ hg commit -m nonrelevant
870 created new head
870 created new head
871 $ hg debugobsolete `hg log -r 11 -T '{node}\n'` --config experimental.evolution=true
871 $ hg debugobsolete `hg log -r 11 -T '{node}\n'` --config experimental.evolution=true
872 1 new obsolescence markers
872 1 new obsolescence markers
873 obsoleted 1 changesets
873 obsoleted 1 changesets
874 $ hg log -G
874 $ hg log -G
875 @ 11:f44da1f4954c nonrelevant (pruned)
875 @ 11:f44da1f4954c nonrelevant (pruned)
876 |
876 |
877 | o 10:121d9e3bc4c6 P
877 | o 10:121d9e3bc4c6 P
878 |/
878 |/
879 o 9:4be60e099a77 C
879 o 9:4be60e099a77 C
880 |
880 |
881 o 6:9c48361117de D
881 o 6:9c48361117de D
882 |
882 |
883 o 2:261e70097290 B2
883 o 2:261e70097290 B2
884 |
884 |
885 o 0:4a2df7238c3b A
885 o 0:4a2df7238c3b A
886
886
887 $ hg rebase -r . -d 10
887 $ hg rebase -r . -d 10
888 note: not rebasing 11:f44da1f4954c "nonrelevant" (tip), it has no successor
888 note: not rebasing 11:f44da1f4954c "nonrelevant" (tip), it has no successor
889
889
890 If a rebase is going to create divergence, it should abort
890 If a rebase is going to create divergence, it should abort
891
891
892 $ hg log -G
892 $ hg log -G
893 @ 10:121d9e3bc4c6 P
893 @ 10:121d9e3bc4c6 P
894 |
894 |
895 o 9:4be60e099a77 C
895 o 9:4be60e099a77 C
896 |
896 |
897 o 6:9c48361117de D
897 o 6:9c48361117de D
898 |
898 |
899 o 2:261e70097290 B2
899 o 2:261e70097290 B2
900 |
900 |
901 o 0:4a2df7238c3b A
901 o 0:4a2df7238c3b A
902
902
903
903
904 $ hg up 9
904 $ hg up 9
905 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
905 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
906 $ echo "john" > doe
906 $ echo "john" > doe
907 $ hg add doe
907 $ hg add doe
908 $ hg commit -m "john doe"
908 $ hg commit -m "john doe"
909 created new head
909 created new head
910 $ hg up 10
910 $ hg up 10
911 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
911 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
912 $ echo "foo" > bar
912 $ echo "foo" > bar
913 $ hg add bar
913 $ hg add bar
914 $ hg commit --amend -m "10'"
914 $ hg commit --amend -m "10'"
915 $ hg up 10 --hidden
915 $ hg up 10 --hidden
916 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
916 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
917 updated to hidden changeset 121d9e3bc4c6
917 updated to hidden changeset 121d9e3bc4c6
918 (hidden revision '121d9e3bc4c6' was rewritten as: 77d874d096a2)
918 (hidden revision '121d9e3bc4c6' was rewritten as: 77d874d096a2)
919 $ echo "bar" > foo
919 $ echo "bar" > foo
920 $ hg add foo
920 $ hg add foo
921 $ hg commit -m "bar foo"
921 $ hg commit -m "bar foo"
922 1 new orphan changesets
922 1 new orphan changesets
923 $ hg log -G
923 $ hg log -G
924 @ 14:73568ab6879d bar foo
924 @ 14:73568ab6879d bar foo
925 |
925 |
926 | o 13:77d874d096a2 10'
926 | o 13:77d874d096a2 10'
927 | |
927 | |
928 | | o 12:3eb461388009 john doe
928 | | o 12:3eb461388009 john doe
929 | |/
929 | |/
930 x | 10:121d9e3bc4c6 P (rewritten using amend as 13:77d874d096a2)
930 x | 10:121d9e3bc4c6 P (rewritten using amend as 13:77d874d096a2)
931 |/
931 |/
932 o 9:4be60e099a77 C
932 o 9:4be60e099a77 C
933 |
933 |
934 o 6:9c48361117de D
934 o 6:9c48361117de D
935 |
935 |
936 o 2:261e70097290 B2
936 o 2:261e70097290 B2
937 |
937 |
938 o 0:4a2df7238c3b A
938 o 0:4a2df7238c3b A
939
939
940 $ hg summary
940 $ hg summary
941 parent: 14:73568ab6879d tip (orphan)
941 parent: 14:73568ab6879d tip (orphan)
942 bar foo
942 bar foo
943 branch: default
943 branch: default
944 commit: (clean)
944 commit: (clean)
945 update: 2 new changesets, 3 branch heads (merge)
945 update: 2 new changesets, 3 branch heads (merge)
946 phases: 8 draft
946 phases: 8 draft
947 orphan: 1 changesets
947 orphan: 1 changesets
948 $ hg rebase -s 10 -d 12
948 $ hg rebase -s 10 -d 12
949 abort: this rebase will cause divergences from: 121d9e3bc4c6
949 abort: this rebase will cause divergences from: 121d9e3bc4c6
950 (to force the rebase please set experimental.evolution.allowdivergence=True)
950 (to force the rebase please set experimental.evolution.allowdivergence=True)
951 [255]
951 [255]
952 $ hg log -G
952 $ hg log -G
953 @ 14:73568ab6879d bar foo
953 @ 14:73568ab6879d bar foo
954 |
954 |
955 | o 13:77d874d096a2 10'
955 | o 13:77d874d096a2 10'
956 | |
956 | |
957 | | o 12:3eb461388009 john doe
957 | | o 12:3eb461388009 john doe
958 | |/
958 | |/
959 x | 10:121d9e3bc4c6 P (rewritten using amend as 13:77d874d096a2)
959 x | 10:121d9e3bc4c6 P (rewritten using amend as 13:77d874d096a2)
960 |/
960 |/
961 o 9:4be60e099a77 C
961 o 9:4be60e099a77 C
962 |
962 |
963 o 6:9c48361117de D
963 o 6:9c48361117de D
964 |
964 |
965 o 2:261e70097290 B2
965 o 2:261e70097290 B2
966 |
966 |
967 o 0:4a2df7238c3b A
967 o 0:4a2df7238c3b A
968
968
969 With experimental.evolution.allowdivergence=True, rebase can create divergence
969 With experimental.evolution.allowdivergence=True, rebase can create divergence
970
970
971 $ hg rebase -s 10 -d 12 --config experimental.evolution.allowdivergence=True
971 $ hg rebase -s 10 -d 12 --config experimental.evolution.allowdivergence=True
972 rebasing 10:121d9e3bc4c6 "P"
972 rebasing 10:121d9e3bc4c6 "P"
973 rebasing 14:73568ab6879d "bar foo" (tip)
973 rebasing 14:73568ab6879d "bar foo" (tip)
974 2 new content-divergent changesets
974 2 new content-divergent changesets
975 $ hg summary
975 $ hg summary
976 parent: 16:61bd55f69bc4 tip
976 parent: 16:61bd55f69bc4 tip
977 bar foo
977 bar foo
978 branch: default
978 branch: default
979 commit: (clean)
979 commit: (clean)
980 update: 1 new changesets, 2 branch heads (merge)
980 update: 1 new changesets, 2 branch heads (merge)
981 phases: 8 draft
981 phases: 8 draft
982 content-divergent: 2 changesets
982 content-divergent: 2 changesets
983
983
984 rebase --continue + skipped rev because their successors are in destination
984 rebase --continue + skipped rev because their successors are in destination
985 we make a change in trunk and work on conflicting changes to make rebase abort.
985 we make a change in trunk and work on conflicting changes to make rebase abort.
986
986
987 $ hg log -G -r 16::
987 $ hg log -G -r 16::
988 @ 16:61bd55f69bc4 bar foo
988 @ 16:61bd55f69bc4 bar foo
989 |
989 |
990 ~
990 ~
991
991
992 Create the two changes in trunk
992 Create the two changes in trunk
993 $ printf "a" > willconflict
993 $ printf "a" > willconflict
994 $ hg add willconflict
994 $ hg add willconflict
995 $ hg commit -m "willconflict first version"
995 $ hg commit -m "willconflict first version"
996
996
997 $ printf "dummy" > C
997 $ printf "dummy" > C
998 $ hg commit -m "dummy change successor"
998 $ hg commit -m "dummy change successor"
999
999
1000 Create the changes that we will rebase
1000 Create the changes that we will rebase
1001 $ hg update -C 16 -q
1001 $ hg update -C 16 -q
1002 $ printf "b" > willconflict
1002 $ printf "b" > willconflict
1003 $ hg add willconflict
1003 $ hg add willconflict
1004 $ hg commit -m "willconflict second version"
1004 $ hg commit -m "willconflict second version"
1005 created new head
1005 created new head
1006 $ printf "dummy" > K
1006 $ printf "dummy" > K
1007 $ hg add K
1007 $ hg add K
1008 $ hg commit -m "dummy change"
1008 $ hg commit -m "dummy change"
1009 $ printf "dummy" > L
1009 $ printf "dummy" > L
1010 $ hg add L
1010 $ hg add L
1011 $ hg commit -m "dummy change"
1011 $ hg commit -m "dummy change"
1012 $ hg debugobsolete `hg log -r ".^" -T '{node}'` `hg log -r 18 -T '{node}'` --config experimental.evolution=true
1012 $ hg debugobsolete `hg log -r ".^" -T '{node}'` `hg log -r 18 -T '{node}'` --config experimental.evolution=true
1013 1 new obsolescence markers
1013 1 new obsolescence markers
1014 obsoleted 1 changesets
1014 obsoleted 1 changesets
1015 1 new orphan changesets
1015 1 new orphan changesets
1016
1016
1017 $ hg log -G -r 16::
1017 $ hg log -G -r 16::
1018 @ 21:7bdc8a87673d dummy change
1018 @ 21:7bdc8a87673d dummy change
1019 |
1019 |
1020 x 20:8b31da3c4919 dummy change (rewritten as 18:601db7a18f51)
1020 x 20:8b31da3c4919 dummy change (rewritten as 18:601db7a18f51)
1021 |
1021 |
1022 o 19:b82fb57ea638 willconflict second version
1022 o 19:b82fb57ea638 willconflict second version
1023 |
1023 |
1024 | o 18:601db7a18f51 dummy change successor
1024 | o 18:601db7a18f51 dummy change successor
1025 | |
1025 | |
1026 | o 17:357ddf1602d5 willconflict first version
1026 | o 17:357ddf1602d5 willconflict first version
1027 |/
1027 |/
1028 o 16:61bd55f69bc4 bar foo
1028 o 16:61bd55f69bc4 bar foo
1029 |
1029 |
1030 ~
1030 ~
1031 $ hg rebase -r ".^^ + .^ + ." -d 18
1031 $ hg rebase -r ".^^ + .^ + ." -d 18
1032 rebasing 19:b82fb57ea638 "willconflict second version"
1032 rebasing 19:b82fb57ea638 "willconflict second version"
1033 merging willconflict
1033 merging willconflict
1034 warning: conflicts while merging willconflict! (edit, then use 'hg resolve --mark')
1034 warning: conflicts while merging willconflict! (edit, then use 'hg resolve --mark')
1035 unresolved conflicts (see hg resolve, then hg rebase --continue)
1035 unresolved conflicts (see hg resolve, then hg rebase --continue)
1036 [1]
1036 [1]
1037
1037
1038 $ hg resolve --mark willconflict
1038 $ hg resolve --mark willconflict
1039 (no more unresolved files)
1039 (no more unresolved files)
1040 continue: hg rebase --continue
1040 continue: hg rebase --continue
1041 $ hg rebase --continue
1041 $ hg rebase --continue
1042 rebasing 19:b82fb57ea638 "willconflict second version"
1042 rebasing 19:b82fb57ea638 "willconflict second version"
1043 note: not rebasing 20:8b31da3c4919 "dummy change", already in destination as 18:601db7a18f51 "dummy change successor"
1043 note: not rebasing 20:8b31da3c4919 "dummy change", already in destination as 18:601db7a18f51 "dummy change successor"
1044 rebasing 21:7bdc8a87673d "dummy change" (tip)
1044 rebasing 21:7bdc8a87673d "dummy change" (tip)
1045 $ cd ..
1045 $ cd ..
1046
1046
1047 Divergence cases due to obsolete changesets
1047 Divergence cases due to obsolete changesets
1048 -------------------------------------------
1048 -------------------------------------------
1049
1049
1050 We should ignore branches with unstable changesets when they are based on an
1050 We should ignore branches with unstable changesets when they are based on an
1051 obsolete changeset which successor is in rebase set.
1051 obsolete changeset which successor is in rebase set.
1052
1052
1053 $ hg init divergence
1053 $ hg init divergence
1054 $ cd divergence
1054 $ cd divergence
1055 $ cat >> .hg/hgrc << EOF
1055 $ cat >> .hg/hgrc << EOF
1056 > [extensions]
1056 > [extensions]
1057 > strip =
1057 > strip =
1058 > [alias]
1058 > [alias]
1059 > strip = strip --no-backup --quiet
1059 > strip = strip --no-backup --quiet
1060 > [templates]
1060 > [templates]
1061 > instabilities = '{rev}:{node|short} {desc|firstline}{if(instabilities," ({instabilities})")}\n'
1061 > instabilities = '{rev}:{node|short} {desc|firstline}{if(instabilities," ({instabilities})")}\n'
1062 > EOF
1062 > EOF
1063
1063
1064 $ hg debugdrawdag <<EOF
1064 $ hg debugdrawdag <<EOF
1065 > e f
1065 > e f
1066 > | |
1066 > | |
1067 > d' d # replace: d -> d'
1067 > d' d # replace: d -> d'
1068 > \ /
1068 > \ /
1069 > c
1069 > c
1070 > |
1070 > |
1071 > x b
1071 > x b
1072 > \|
1072 > \|
1073 > a
1073 > a
1074 > EOF
1074 > EOF
1075 1 new orphan changesets
1075 1 new orphan changesets
1076 $ hg log -G -r 'a'::
1076 $ hg log -G -r 'a'::
1077 * 7:1143e9adc121 f
1077 * 7:1143e9adc121 f
1078 |
1078 |
1079 | o 6:d60ebfa0f1cb e
1079 | o 6:d60ebfa0f1cb e
1080 | |
1080 | |
1081 | o 5:027ad6c5830d d'
1081 | o 5:027ad6c5830d d'
1082 | |
1082 | |
1083 x | 4:76be324c128b d (rewritten using replace as 5:027ad6c5830d)
1083 x | 4:76be324c128b d (rewritten using replace as 5:027ad6c5830d)
1084 |/
1084 |/
1085 o 3:a82ac2b38757 c
1085 o 3:a82ac2b38757 c
1086 |
1086 |
1087 | o 2:630d7c95eff7 x
1087 | o 2:630d7c95eff7 x
1088 | |
1088 | |
1089 o | 1:488e1b7e7341 b
1089 o | 1:488e1b7e7341 b
1090 |/
1090 |/
1091 o 0:b173517d0057 a
1091 o 0:b173517d0057 a
1092
1092
1093
1093
1094 Changeset d and its descendants are excluded to avoid divergence of d, which
1094 Changeset d and its descendants are excluded to avoid divergence of d, which
1095 would occur because the successor of d (d') is also in rebaseset. As a
1095 would occur because the successor of d (d') is also in rebaseset. As a
1096 consequence f (descendant of d) is left behind.
1096 consequence f (descendant of d) is left behind.
1097
1097
1098 $ hg rebase -b 'e' -d 'x'
1098 $ hg rebase -b 'e' -d 'x'
1099 rebasing 1:488e1b7e7341 "b" (b)
1099 rebasing 1:488e1b7e7341 "b" (b)
1100 rebasing 3:a82ac2b38757 "c" (c)
1100 rebasing 3:a82ac2b38757 "c" (c)
1101 rebasing 5:027ad6c5830d "d'" (d')
1101 rebasing 5:027ad6c5830d "d'" (d')
1102 rebasing 6:d60ebfa0f1cb "e" (e)
1102 rebasing 6:d60ebfa0f1cb "e" (e)
1103 note: not rebasing 4:76be324c128b "d" (d) and its descendants as this would cause divergence
1103 note: not rebasing 4:76be324c128b "d" (d) and its descendants as this would cause divergence
1104 $ hg log -G -r 'a'::
1104 $ hg log -G -r 'a'::
1105 o 11:eb6d63fc4ed5 e
1105 o 11:eb6d63fc4ed5 e
1106 |
1106 |
1107 o 10:44d8c724a70c d'
1107 o 10:44d8c724a70c d'
1108 |
1108 |
1109 o 9:d008e6b4d3fd c
1109 o 9:d008e6b4d3fd c
1110 |
1110 |
1111 o 8:67e8f4a16c49 b
1111 o 8:67e8f4a16c49 b
1112 |
1112 |
1113 | * 7:1143e9adc121 f
1113 | * 7:1143e9adc121 f
1114 | |
1114 | |
1115 | | x 6:d60ebfa0f1cb e (rewritten using rebase as 11:eb6d63fc4ed5)
1115 | | x 6:d60ebfa0f1cb e (rewritten using rebase as 11:eb6d63fc4ed5)
1116 | | |
1116 | | |
1117 | | x 5:027ad6c5830d d' (rewritten using rebase as 10:44d8c724a70c)
1117 | | x 5:027ad6c5830d d' (rewritten using rebase as 10:44d8c724a70c)
1118 | | |
1118 | | |
1119 | x | 4:76be324c128b d (rewritten using replace as 5:027ad6c5830d)
1119 | x | 4:76be324c128b d (rewritten using replace as 5:027ad6c5830d)
1120 | |/
1120 | |/
1121 | x 3:a82ac2b38757 c (rewritten using rebase as 9:d008e6b4d3fd)
1121 | x 3:a82ac2b38757 c (rewritten using rebase as 9:d008e6b4d3fd)
1122 | |
1122 | |
1123 o | 2:630d7c95eff7 x
1123 o | 2:630d7c95eff7 x
1124 | |
1124 | |
1125 | x 1:488e1b7e7341 b (rewritten using rebase as 8:67e8f4a16c49)
1125 | x 1:488e1b7e7341 b (rewritten using rebase as 8:67e8f4a16c49)
1126 |/
1126 |/
1127 o 0:b173517d0057 a
1127 o 0:b173517d0057 a
1128
1128
1129 $ hg strip -r 8:
1129 $ hg strip -r 8:
1130 $ hg log -G -r 'a'::
1130 $ hg log -G -r 'a'::
1131 * 7:1143e9adc121 f
1131 * 7:1143e9adc121 f
1132 |
1132 |
1133 | o 6:d60ebfa0f1cb e
1133 | o 6:d60ebfa0f1cb e
1134 | |
1134 | |
1135 | o 5:027ad6c5830d d'
1135 | o 5:027ad6c5830d d'
1136 | |
1136 | |
1137 x | 4:76be324c128b d (rewritten using replace as 5:027ad6c5830d)
1137 x | 4:76be324c128b d (rewritten using replace as 5:027ad6c5830d)
1138 |/
1138 |/
1139 o 3:a82ac2b38757 c
1139 o 3:a82ac2b38757 c
1140 |
1140 |
1141 | o 2:630d7c95eff7 x
1141 | o 2:630d7c95eff7 x
1142 | |
1142 | |
1143 o | 1:488e1b7e7341 b
1143 o | 1:488e1b7e7341 b
1144 |/
1144 |/
1145 o 0:b173517d0057 a
1145 o 0:b173517d0057 a
1146
1146
1147
1147
1148 If the rebase set has an obsolete (d) with a successor (d') outside the rebase
1148 If the rebase set has an obsolete (d) with a successor (d') outside the rebase
1149 set and none in destination, we still get the divergence warning.
1149 set and none in destination, we still get the divergence warning.
1150 By allowing divergence, we can perform the rebase.
1150 By allowing divergence, we can perform the rebase.
1151
1151
1152 $ hg rebase -r 'c'::'f' -d 'x'
1152 $ hg rebase -r 'c'::'f' -d 'x'
1153 abort: this rebase will cause divergences from: 76be324c128b
1153 abort: this rebase will cause divergences from: 76be324c128b
1154 (to force the rebase please set experimental.evolution.allowdivergence=True)
1154 (to force the rebase please set experimental.evolution.allowdivergence=True)
1155 [255]
1155 [255]
1156 $ hg rebase --config experimental.evolution.allowdivergence=true -r 'c'::'f' -d 'x'
1156 $ hg rebase --config experimental.evolution.allowdivergence=true -r 'c'::'f' -d 'x'
1157 rebasing 3:a82ac2b38757 "c" (c)
1157 rebasing 3:a82ac2b38757 "c" (c)
1158 rebasing 4:76be324c128b "d" (d)
1158 rebasing 4:76be324c128b "d" (d)
1159 rebasing 7:1143e9adc121 "f" (f tip)
1159 rebasing 7:1143e9adc121 "f" (f tip)
1160 1 new orphan changesets
1160 1 new orphan changesets
1161 2 new content-divergent changesets
1161 2 new content-divergent changesets
1162 $ hg log -G -r 'a':: -T instabilities
1162 $ hg log -G -r 'a':: -T instabilities
1163 o 10:e1744ea07510 f
1163 o 10:e1744ea07510 f
1164 |
1164 |
1165 * 9:e2b36ea9a0a0 d (content-divergent)
1165 * 9:e2b36ea9a0a0 d (content-divergent)
1166 |
1166 |
1167 o 8:6a0376de376e c
1167 o 8:6a0376de376e c
1168 |
1168 |
1169 | x 7:1143e9adc121 f
1169 | x 7:1143e9adc121 f
1170 | |
1170 | |
1171 | | * 6:d60ebfa0f1cb e (orphan)
1171 | | * 6:d60ebfa0f1cb e (orphan)
1172 | | |
1172 | | |
1173 | | * 5:027ad6c5830d d' (orphan content-divergent)
1173 | | * 5:027ad6c5830d d' (orphan content-divergent)
1174 | | |
1174 | | |
1175 | x | 4:76be324c128b d
1175 | x | 4:76be324c128b d
1176 | |/
1176 | |/
1177 | x 3:a82ac2b38757 c
1177 | x 3:a82ac2b38757 c
1178 | |
1178 | |
1179 o | 2:630d7c95eff7 x
1179 o | 2:630d7c95eff7 x
1180 | |
1180 | |
1181 | o 1:488e1b7e7341 b
1181 | o 1:488e1b7e7341 b
1182 |/
1182 |/
1183 o 0:b173517d0057 a
1183 o 0:b173517d0057 a
1184
1184
1185 $ hg strip -r 8:
1185 $ hg strip -r 8:
1186
1186
1187 (Not skipping obsoletes means that divergence is allowed.)
1187 (Not skipping obsoletes means that divergence is allowed.)
1188
1188
1189 $ hg rebase --config experimental.rebaseskipobsolete=false -r 'c'::'f' -d 'x'
1189 $ hg rebase --config experimental.rebaseskipobsolete=false -r 'c'::'f' -d 'x'
1190 rebasing 3:a82ac2b38757 "c" (c)
1190 rebasing 3:a82ac2b38757 "c" (c)
1191 rebasing 4:76be324c128b "d" (d)
1191 rebasing 4:76be324c128b "d" (d)
1192 rebasing 7:1143e9adc121 "f" (f tip)
1192 rebasing 7:1143e9adc121 "f" (f tip)
1193 1 new orphan changesets
1193 1 new orphan changesets
1194 2 new content-divergent changesets
1194 2 new content-divergent changesets
1195
1195
1196 $ hg strip -r 0:
1196 $ hg strip -r 0:
1197
1197
1198 Similar test on a more complex graph
1198 Similar test on a more complex graph
1199
1199
1200 $ hg debugdrawdag <<EOF
1200 $ hg debugdrawdag <<EOF
1201 > g
1201 > g
1202 > |
1202 > |
1203 > f e
1203 > f e
1204 > | |
1204 > | |
1205 > e' d # replace: e -> e'
1205 > e' d # replace: e -> e'
1206 > \ /
1206 > \ /
1207 > c
1207 > c
1208 > |
1208 > |
1209 > x b
1209 > x b
1210 > \|
1210 > \|
1211 > a
1211 > a
1212 > EOF
1212 > EOF
1213 1 new orphan changesets
1213 1 new orphan changesets
1214 $ hg log -G -r 'a':
1214 $ hg log -G -r 'a':
1215 * 8:2876ce66c6eb g
1215 * 8:2876ce66c6eb g
1216 |
1216 |
1217 | o 7:3ffec603ab53 f
1217 | o 7:3ffec603ab53 f
1218 | |
1218 | |
1219 x | 6:e36fae928aec e (rewritten using replace as 5:63324dc512ea)
1219 x | 6:e36fae928aec e (rewritten using replace as 5:63324dc512ea)
1220 | |
1220 | |
1221 | o 5:63324dc512ea e'
1221 | o 5:63324dc512ea e'
1222 | |
1222 | |
1223 o | 4:76be324c128b d
1223 o | 4:76be324c128b d
1224 |/
1224 |/
1225 o 3:a82ac2b38757 c
1225 o 3:a82ac2b38757 c
1226 |
1226 |
1227 | o 2:630d7c95eff7 x
1227 | o 2:630d7c95eff7 x
1228 | |
1228 | |
1229 o | 1:488e1b7e7341 b
1229 o | 1:488e1b7e7341 b
1230 |/
1230 |/
1231 o 0:b173517d0057 a
1231 o 0:b173517d0057 a
1232
1232
1233 $ hg rebase -b 'f' -d 'x'
1233 $ hg rebase -b 'f' -d 'x'
1234 rebasing 1:488e1b7e7341 "b" (b)
1234 rebasing 1:488e1b7e7341 "b" (b)
1235 rebasing 3:a82ac2b38757 "c" (c)
1235 rebasing 3:a82ac2b38757 "c" (c)
1236 rebasing 5:63324dc512ea "e'" (e')
1236 rebasing 5:63324dc512ea "e'" (e')
1237 rebasing 7:3ffec603ab53 "f" (f)
1237 rebasing 7:3ffec603ab53 "f" (f)
1238 rebasing 4:76be324c128b "d" (d)
1238 rebasing 4:76be324c128b "d" (d)
1239 note: not rebasing 6:e36fae928aec "e" (e) and its descendants as this would cause divergence
1239 note: not rebasing 6:e36fae928aec "e" (e) and its descendants as this would cause divergence
1240 $ hg log -G -r 'a':
1240 $ hg log -G -r 'a':
1241 o 13:a1707a5b7c2c d
1241 o 13:a1707a5b7c2c d
1242 |
1242 |
1243 | o 12:ef6251596616 f
1243 | o 12:ef6251596616 f
1244 | |
1244 | |
1245 | o 11:b6f172e64af9 e'
1245 | o 11:b6f172e64af9 e'
1246 |/
1246 |/
1247 o 10:d008e6b4d3fd c
1247 o 10:d008e6b4d3fd c
1248 |
1248 |
1249 o 9:67e8f4a16c49 b
1249 o 9:67e8f4a16c49 b
1250 |
1250 |
1251 | * 8:2876ce66c6eb g
1251 | * 8:2876ce66c6eb g
1252 | |
1252 | |
1253 | | x 7:3ffec603ab53 f (rewritten using rebase as 12:ef6251596616)
1253 | | x 7:3ffec603ab53 f (rewritten using rebase as 12:ef6251596616)
1254 | | |
1254 | | |
1255 | x | 6:e36fae928aec e (rewritten using replace as 5:63324dc512ea)
1255 | x | 6:e36fae928aec e (rewritten using replace as 5:63324dc512ea)
1256 | | |
1256 | | |
1257 | | x 5:63324dc512ea e' (rewritten using rebase as 11:b6f172e64af9)
1257 | | x 5:63324dc512ea e' (rewritten using rebase as 11:b6f172e64af9)
1258 | | |
1258 | | |
1259 | x | 4:76be324c128b d (rewritten using rebase as 13:a1707a5b7c2c)
1259 | x | 4:76be324c128b d (rewritten using rebase as 13:a1707a5b7c2c)
1260 | |/
1260 | |/
1261 | x 3:a82ac2b38757 c (rewritten using rebase as 10:d008e6b4d3fd)
1261 | x 3:a82ac2b38757 c (rewritten using rebase as 10:d008e6b4d3fd)
1262 | |
1262 | |
1263 o | 2:630d7c95eff7 x
1263 o | 2:630d7c95eff7 x
1264 | |
1264 | |
1265 | x 1:488e1b7e7341 b (rewritten using rebase as 9:67e8f4a16c49)
1265 | x 1:488e1b7e7341 b (rewritten using rebase as 9:67e8f4a16c49)
1266 |/
1266 |/
1267 o 0:b173517d0057 a
1267 o 0:b173517d0057 a
1268
1268
1269
1269
1270 issue5782
1270 issue5782
1271 $ hg strip -r 0:
1271 $ hg strip -r 0:
1272 $ hg debugdrawdag <<EOF
1272 $ hg debugdrawdag <<EOF
1273 > d
1273 > d
1274 > |
1274 > |
1275 > c1 c # replace: c -> c1
1275 > c1 c # replace: c -> c1
1276 > \ /
1276 > \ /
1277 > b
1277 > b
1278 > |
1278 > |
1279 > a
1279 > a
1280 > EOF
1280 > EOF
1281 1 new orphan changesets
1281 1 new orphan changesets
1282 $ hg debugobsolete `hg log -T "{node}" --hidden -r 'desc("c1")'`
1282 $ hg debugobsolete `hg log -T "{node}" --hidden -r 'desc("c1")'`
1283 1 new obsolescence markers
1283 1 new obsolescence markers
1284 obsoleted 1 changesets
1284 obsoleted 1 changesets
1285 $ hg log -G -r 'a': --hidden
1285 $ hg log -G -r 'a': --hidden
1286 * 4:76be324c128b d
1286 * 4:76be324c128b d
1287 |
1287 |
1288 | x 3:ef8a456de8fa c1 (pruned)
1288 | x 3:ef8a456de8fa c1 (pruned)
1289 | |
1289 | |
1290 x | 2:a82ac2b38757 c (rewritten using replace as 3:ef8a456de8fa)
1290 x | 2:a82ac2b38757 c (rewritten using replace as 3:ef8a456de8fa)
1291 |/
1291 |/
1292 o 1:488e1b7e7341 b
1292 o 1:488e1b7e7341 b
1293 |
1293 |
1294 o 0:b173517d0057 a
1294 o 0:b173517d0057 a
1295
1295
1296 $ hg rebase -d 0 -r 2
1296 $ hg rebase -d 0 -r 2
1297 rebasing 2:a82ac2b38757 "c" (c)
1297 rebasing 2:a82ac2b38757 "c" (c)
1298 $ hg log -G -r 'a': --hidden
1298 $ hg log -G -r 'a': --hidden
1299 o 5:69ad416a4a26 c
1299 o 5:69ad416a4a26 c
1300 |
1300 |
1301 | * 4:76be324c128b d
1301 | * 4:76be324c128b d
1302 | |
1302 | |
1303 | | x 3:ef8a456de8fa c1 (pruned)
1303 | | x 3:ef8a456de8fa c1 (pruned)
1304 | | |
1304 | | |
1305 | x | 2:a82ac2b38757 c (rewritten using replace as 3:ef8a456de8fa rewritten using rebase as 5:69ad416a4a26)
1305 | x | 2:a82ac2b38757 c (rewritten using replace as 3:ef8a456de8fa rewritten using rebase as 5:69ad416a4a26)
1306 | |/
1306 | |/
1307 | o 1:488e1b7e7341 b
1307 | o 1:488e1b7e7341 b
1308 |/
1308 |/
1309 o 0:b173517d0057 a
1309 o 0:b173517d0057 a
1310
1310
1311 $ cd ..
1311 $ cd ..
1312
1312
1313 Rebase merge where successor of one parent is equal to destination (issue5198)
1313 Rebase merge where successor of one parent is equal to destination (issue5198)
1314
1314
1315 $ hg init p1-succ-is-dest
1315 $ hg init p1-succ-is-dest
1316 $ cd p1-succ-is-dest
1316 $ cd p1-succ-is-dest
1317
1317
1318 $ hg debugdrawdag <<EOF
1318 $ hg debugdrawdag <<EOF
1319 > F
1319 > F
1320 > /|
1320 > /|
1321 > E D B # replace: D -> B
1321 > E D B # replace: D -> B
1322 > \|/
1322 > \|/
1323 > A
1323 > A
1324 > EOF
1324 > EOF
1325 1 new orphan changesets
1325 1 new orphan changesets
1326
1326
1327 $ hg rebase -d B -s D
1327 $ hg rebase -d B -s D
1328 note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" (B)
1328 note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" (B)
1329 rebasing 4:66f1a38021c9 "F" (F tip)
1329 rebasing 4:66f1a38021c9 "F" (F tip)
1330 $ hg log -G
1330 $ hg log -G
1331 o 5:50e9d60b99c6 F
1331 o 5:50e9d60b99c6 F
1332 |\
1332 |\
1333 | | x 4:66f1a38021c9 F (rewritten using rebase as 5:50e9d60b99c6)
1333 | | x 4:66f1a38021c9 F (rewritten using rebase as 5:50e9d60b99c6)
1334 | |/|
1334 | |/|
1335 | o | 3:7fb047a69f22 E
1335 | o | 3:7fb047a69f22 E
1336 | | |
1336 | | |
1337 | | x 2:b18e25de2cf5 D (rewritten using replace as 1:112478962961)
1337 | | x 2:b18e25de2cf5 D (rewritten using replace as 1:112478962961)
1338 | |/
1338 | |/
1339 o | 1:112478962961 B
1339 o | 1:112478962961 B
1340 |/
1340 |/
1341 o 0:426bada5c675 A
1341 o 0:426bada5c675 A
1342
1342
1343 $ cd ..
1343 $ cd ..
1344
1344
1345 Rebase merge where successor of other parent is equal to destination
1345 Rebase merge where successor of other parent is equal to destination
1346
1346
1347 $ hg init p2-succ-is-dest
1347 $ hg init p2-succ-is-dest
1348 $ cd p2-succ-is-dest
1348 $ cd p2-succ-is-dest
1349
1349
1350 $ hg debugdrawdag <<EOF
1350 $ hg debugdrawdag <<EOF
1351 > F
1351 > F
1352 > /|
1352 > /|
1353 > E D B # replace: E -> B
1353 > E D B # replace: E -> B
1354 > \|/
1354 > \|/
1355 > A
1355 > A
1356 > EOF
1356 > EOF
1357 1 new orphan changesets
1357 1 new orphan changesets
1358
1358
1359 $ hg rebase -d B -s E
1359 $ hg rebase -d B -s E
1360 note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" (B)
1360 note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" (B)
1361 rebasing 4:66f1a38021c9 "F" (F tip)
1361 rebasing 4:66f1a38021c9 "F" (F tip)
1362 $ hg log -G
1362 $ hg log -G
1363 o 5:aae1787dacee F
1363 o 5:aae1787dacee F
1364 |\
1364 |\
1365 | | x 4:66f1a38021c9 F (rewritten using rebase as 5:aae1787dacee)
1365 | | x 4:66f1a38021c9 F (rewritten using rebase as 5:aae1787dacee)
1366 | |/|
1366 | |/|
1367 | | x 3:7fb047a69f22 E (rewritten using replace as 1:112478962961)
1367 | | x 3:7fb047a69f22 E (rewritten using replace as 1:112478962961)
1368 | | |
1368 | | |
1369 | o | 2:b18e25de2cf5 D
1369 | o | 2:b18e25de2cf5 D
1370 | |/
1370 | |/
1371 o / 1:112478962961 B
1371 o / 1:112478962961 B
1372 |/
1372 |/
1373 o 0:426bada5c675 A
1373 o 0:426bada5c675 A
1374
1374
1375 $ cd ..
1375 $ cd ..
1376
1376
1377 Rebase merge where successor of one parent is ancestor of destination
1377 Rebase merge where successor of one parent is ancestor of destination
1378
1378
1379 $ hg init p1-succ-in-dest
1379 $ hg init p1-succ-in-dest
1380 $ cd p1-succ-in-dest
1380 $ cd p1-succ-in-dest
1381
1381
1382 $ hg debugdrawdag <<EOF
1382 $ hg debugdrawdag <<EOF
1383 > F C
1383 > F C
1384 > /| |
1384 > /| |
1385 > E D B # replace: D -> B
1385 > E D B # replace: D -> B
1386 > \|/
1386 > \|/
1387 > A
1387 > A
1388 > EOF
1388 > EOF
1389 1 new orphan changesets
1389 1 new orphan changesets
1390
1390
1391 $ hg rebase -d C -s D
1391 $ hg rebase -d C -s D
1392 note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" (B)
1392 note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" (B)
1393 rebasing 5:66f1a38021c9 "F" (F tip)
1393 rebasing 5:66f1a38021c9 "F" (F tip)
1394
1394
1395 $ hg log -G
1395 $ hg log -G
1396 o 6:0913febf6439 F
1396 o 6:0913febf6439 F
1397 |\
1397 |\
1398 +---x 5:66f1a38021c9 F (rewritten using rebase as 6:0913febf6439)
1398 +---x 5:66f1a38021c9 F (rewritten using rebase as 6:0913febf6439)
1399 | | |
1399 | | |
1400 | o | 4:26805aba1e60 C
1400 | o | 4:26805aba1e60 C
1401 | | |
1401 | | |
1402 o | | 3:7fb047a69f22 E
1402 o | | 3:7fb047a69f22 E
1403 | | |
1403 | | |
1404 +---x 2:b18e25de2cf5 D (rewritten using replace as 1:112478962961)
1404 +---x 2:b18e25de2cf5 D (rewritten using replace as 1:112478962961)
1405 | |
1405 | |
1406 | o 1:112478962961 B
1406 | o 1:112478962961 B
1407 |/
1407 |/
1408 o 0:426bada5c675 A
1408 o 0:426bada5c675 A
1409
1409
1410 $ cd ..
1410 $ cd ..
1411
1411
1412 Rebase merge where successor of other parent is ancestor of destination
1412 Rebase merge where successor of other parent is ancestor of destination
1413
1413
1414 $ hg init p2-succ-in-dest
1414 $ hg init p2-succ-in-dest
1415 $ cd p2-succ-in-dest
1415 $ cd p2-succ-in-dest
1416
1416
1417 $ hg debugdrawdag <<EOF
1417 $ hg debugdrawdag <<EOF
1418 > F C
1418 > F C
1419 > /| |
1419 > /| |
1420 > E D B # replace: E -> B
1420 > E D B # replace: E -> B
1421 > \|/
1421 > \|/
1422 > A
1422 > A
1423 > EOF
1423 > EOF
1424 1 new orphan changesets
1424 1 new orphan changesets
1425
1425
1426 $ hg rebase -d C -s E
1426 $ hg rebase -d C -s E
1427 note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" (B)
1427 note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" (B)
1428 rebasing 5:66f1a38021c9 "F" (F tip)
1428 rebasing 5:66f1a38021c9 "F" (F tip)
1429 $ hg log -G
1429 $ hg log -G
1430 o 6:c6ab0cc6d220 F
1430 o 6:c6ab0cc6d220 F
1431 |\
1431 |\
1432 +---x 5:66f1a38021c9 F (rewritten using rebase as 6:c6ab0cc6d220)
1432 +---x 5:66f1a38021c9 F (rewritten using rebase as 6:c6ab0cc6d220)
1433 | | |
1433 | | |
1434 | o | 4:26805aba1e60 C
1434 | o | 4:26805aba1e60 C
1435 | | |
1435 | | |
1436 | | x 3:7fb047a69f22 E (rewritten using replace as 1:112478962961)
1436 | | x 3:7fb047a69f22 E (rewritten using replace as 1:112478962961)
1437 | | |
1437 | | |
1438 o---+ 2:b18e25de2cf5 D
1438 o---+ 2:b18e25de2cf5 D
1439 / /
1439 / /
1440 o / 1:112478962961 B
1440 o / 1:112478962961 B
1441 |/
1441 |/
1442 o 0:426bada5c675 A
1442 o 0:426bada5c675 A
1443
1443
1444 $ cd ..
1444 $ cd ..
1445
1445
1446 Rebase merge where successor of one parent is ancestor of destination
1446 Rebase merge where successor of one parent is ancestor of destination
1447
1447
1448 $ hg init p1-succ-in-dest-b
1448 $ hg init p1-succ-in-dest-b
1449 $ cd p1-succ-in-dest-b
1449 $ cd p1-succ-in-dest-b
1450
1450
1451 $ hg debugdrawdag <<EOF
1451 $ hg debugdrawdag <<EOF
1452 > F C
1452 > F C
1453 > /| |
1453 > /| |
1454 > E D B # replace: E -> B
1454 > E D B # replace: E -> B
1455 > \|/
1455 > \|/
1456 > A
1456 > A
1457 > EOF
1457 > EOF
1458 1 new orphan changesets
1458 1 new orphan changesets
1459
1459
1460 $ hg rebase -d C -b F
1460 $ hg rebase -d C -b F
1461 rebasing 2:b18e25de2cf5 "D" (D)
1461 rebasing 2:b18e25de2cf5 "D" (D)
1462 note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" (B)
1462 note: not rebasing 3:7fb047a69f22 "E" (E), already in destination as 1:112478962961 "B" (B)
1463 rebasing 5:66f1a38021c9 "F" (F tip)
1463 rebasing 5:66f1a38021c9 "F" (F tip)
1464 note: not rebasing 5:66f1a38021c9 "F" (F tip), its destination already has all its changes
1464 note: not rebasing 5:66f1a38021c9 "F" (F tip), its destination already has all its changes
1465 $ hg log -G
1465 $ hg log -G
1466 o 6:8f47515dda15 D
1466 o 6:8f47515dda15 D
1467 |
1467 |
1468 | x 5:66f1a38021c9 F (pruned using rebase)
1468 | x 5:66f1a38021c9 F (pruned using rebase)
1469 | |\
1469 | |\
1470 o | | 4:26805aba1e60 C
1470 o | | 4:26805aba1e60 C
1471 | | |
1471 | | |
1472 | | x 3:7fb047a69f22 E (rewritten using replace as 1:112478962961)
1472 | | x 3:7fb047a69f22 E (rewritten using replace as 1:112478962961)
1473 | | |
1473 | | |
1474 | x | 2:b18e25de2cf5 D (rewritten using rebase as 6:8f47515dda15)
1474 | x | 2:b18e25de2cf5 D (rewritten using rebase as 6:8f47515dda15)
1475 | |/
1475 | |/
1476 o / 1:112478962961 B
1476 o / 1:112478962961 B
1477 |/
1477 |/
1478 o 0:426bada5c675 A
1478 o 0:426bada5c675 A
1479
1479
1480 $ cd ..
1480 $ cd ..
1481
1481
1482 Rebase merge where successor of other parent is ancestor of destination
1482 Rebase merge where successor of other parent is ancestor of destination
1483
1483
1484 $ hg init p2-succ-in-dest-b
1484 $ hg init p2-succ-in-dest-b
1485 $ cd p2-succ-in-dest-b
1485 $ cd p2-succ-in-dest-b
1486
1486
1487 $ hg debugdrawdag <<EOF
1487 $ hg debugdrawdag <<EOF
1488 > F C
1488 > F C
1489 > /| |
1489 > /| |
1490 > E D B # replace: D -> B
1490 > E D B # replace: D -> B
1491 > \|/
1491 > \|/
1492 > A
1492 > A
1493 > EOF
1493 > EOF
1494 1 new orphan changesets
1494 1 new orphan changesets
1495
1495
1496 $ hg rebase -d C -b F
1496 $ hg rebase -d C -b F
1497 note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" (B)
1497 note: not rebasing 2:b18e25de2cf5 "D" (D), already in destination as 1:112478962961 "B" (B)
1498 rebasing 3:7fb047a69f22 "E" (E)
1498 rebasing 3:7fb047a69f22 "E" (E)
1499 rebasing 5:66f1a38021c9 "F" (F tip)
1499 rebasing 5:66f1a38021c9 "F" (F tip)
1500 note: not rebasing 5:66f1a38021c9 "F" (F tip), its destination already has all its changes
1500 note: not rebasing 5:66f1a38021c9 "F" (F tip), its destination already has all its changes
1501
1501
1502 $ hg log -G
1502 $ hg log -G
1503 o 6:533690786a86 E
1503 o 6:533690786a86 E
1504 |
1504 |
1505 | x 5:66f1a38021c9 F (pruned using rebase)
1505 | x 5:66f1a38021c9 F (pruned using rebase)
1506 | |\
1506 | |\
1507 o | | 4:26805aba1e60 C
1507 o | | 4:26805aba1e60 C
1508 | | |
1508 | | |
1509 | | x 3:7fb047a69f22 E (rewritten using rebase as 6:533690786a86)
1509 | | x 3:7fb047a69f22 E (rewritten using rebase as 6:533690786a86)
1510 | | |
1510 | | |
1511 | x | 2:b18e25de2cf5 D (rewritten using replace as 1:112478962961)
1511 | x | 2:b18e25de2cf5 D (rewritten using replace as 1:112478962961)
1512 | |/
1512 | |/
1513 o / 1:112478962961 B
1513 o / 1:112478962961 B
1514 |/
1514 |/
1515 o 0:426bada5c675 A
1515 o 0:426bada5c675 A
1516
1516
1517 $ cd ..
1517 $ cd ..
1518
1518
1519 Rebase merge where extinct node has successor that is not an ancestor of
1519 Rebase merge where extinct node has successor that is not an ancestor of
1520 destination
1520 destination
1521
1521
1522 $ hg init extinct-with-succ-not-in-dest
1522 $ hg init extinct-with-succ-not-in-dest
1523 $ cd extinct-with-succ-not-in-dest
1523 $ cd extinct-with-succ-not-in-dest
1524
1524
1525 $ hg debugdrawdag <<EOF
1525 $ hg debugdrawdag <<EOF
1526 > E C # replace: C -> E
1526 > E C # replace: C -> E
1527 > | |
1527 > | |
1528 > D B
1528 > D B
1529 > |/
1529 > |/
1530 > A
1530 > A
1531 > EOF
1531 > EOF
1532
1532
1533 $ hg rebase -d D -s B
1533 $ hg rebase -d D -s B
1534 rebasing 1:112478962961 "B" (B)
1534 rebasing 1:112478962961 "B" (B)
1535 note: not rebasing 3:26805aba1e60 "C" (C) and its descendants as this would cause divergence
1535 note: not rebasing 3:26805aba1e60 "C" (C) and its descendants as this would cause divergence
1536
1536
1537 $ cd ..
1537 $ cd ..
1538
1538
1539 $ hg init p2-succ-in-dest-c
1539 $ hg init p2-succ-in-dest-c
1540 $ cd p2-succ-in-dest-c
1540 $ cd p2-succ-in-dest-c
1541
1541
1542 The scenario here was that B::D were developed on default. B was queued on
1542 The scenario here was that B::D were developed on default. B was queued on
1543 stable, but amended before being push to hg-committed. C was queued on default,
1543 stable, but amended before being push to hg-committed. C was queued on default,
1544 along with unrelated J.
1544 along with unrelated J.
1545
1545
1546 $ hg debugdrawdag <<EOF
1546 $ hg debugdrawdag <<EOF
1547 > J
1547 > J
1548 > |
1548 > |
1549 > F
1549 > F
1550 > |
1550 > |
1551 > E
1551 > E
1552 > | D
1552 > | D
1553 > | |
1553 > | |
1554 > | C # replace: C -> F
1554 > | C # replace: C -> F
1555 > | | H I # replace: B -> H -> I
1555 > | | H I # replace: B -> H -> I
1556 > | B |/
1556 > | B |/
1557 > |/ G
1557 > |/ G
1558 > A
1558 > A
1559 > EOF
1559 > EOF
1560 1 new orphan changesets
1560 1 new orphan changesets
1561
1561
1562 This strip seems to be the key to avoid an early divergence warning.
1562 This strip seems to be the key to avoid an early divergence warning.
1563 $ hg --config extensions.strip= --hidden strip -qr H
1563 $ hg --config extensions.strip= --hidden strip -qr H
1564 1 new orphan changesets
1564 1 new orphan changesets
1565
1565
1566 $ hg rebase -b 'desc("D")' -d 'desc("J")'
1566 $ hg rebase -b 'desc("D")' -d 'desc("J")'
1567 abort: this rebase will cause divergences from: 112478962961
1567 abort: this rebase will cause divergences from: 112478962961
1568 (to force the rebase please set experimental.evolution.allowdivergence=True)
1568 (to force the rebase please set experimental.evolution.allowdivergence=True)
1569 [255]
1569 [255]
1570
1570
1571 Rebase merge where both parents have successors in destination
1571 Rebase merge where both parents have successors in destination
1572
1572
1573 $ hg init p12-succ-in-dest
1573 $ hg init p12-succ-in-dest
1574 $ cd p12-succ-in-dest
1574 $ cd p12-succ-in-dest
1575 $ hg debugdrawdag <<'EOS'
1575 $ hg debugdrawdag <<'EOS'
1576 > E F
1576 > E F
1577 > /| /| # replace: A -> C
1577 > /| /| # replace: A -> C
1578 > A B C D # replace: B -> D
1578 > A B C D # replace: B -> D
1579 > | |
1579 > | |
1580 > X Y
1580 > X Y
1581 > EOS
1581 > EOS
1582 1 new orphan changesets
1582 1 new orphan changesets
1583 $ hg rebase -r A+B+E -d F
1583 $ hg rebase -r A+B+E -d F
1584 note: not rebasing 4:a3d17304151f "A" (A), already in destination as 0:96cc3511f894 "C" (C)
1584 note: not rebasing 4:a3d17304151f "A" (A), already in destination as 0:96cc3511f894 "C" (C)
1585 note: not rebasing 5:b23a2cc00842 "B" (B), already in destination as 1:058c1e1fb10a "D" (D)
1585 note: not rebasing 5:b23a2cc00842 "B" (B), already in destination as 1:058c1e1fb10a "D" (D)
1586 rebasing 7:dac5d11c5a7d "E" (E tip)
1586 rebasing 7:dac5d11c5a7d "E" (E tip)
1587 abort: rebasing 7:dac5d11c5a7d will include unwanted changes from 3:59c792af609c, 5:b23a2cc00842 or 2:ba2b7fa7166d, 4:a3d17304151f
1587 abort: rebasing 7:dac5d11c5a7d will include unwanted changes from 3:59c792af609c, 5:b23a2cc00842 or 2:ba2b7fa7166d, 4:a3d17304151f
1588 [255]
1588 [255]
1589 $ cd ..
1589 $ cd ..
1590
1590
1591 Rebase a non-clean merge. One parent has successor in destination, the other
1591 Rebase a non-clean merge. One parent has successor in destination, the other
1592 parent moves as requested.
1592 parent moves as requested.
1593
1593
1594 $ hg init p1-succ-p2-move
1594 $ hg init p1-succ-p2-move
1595 $ cd p1-succ-p2-move
1595 $ cd p1-succ-p2-move
1596 $ hg debugdrawdag <<'EOS'
1596 $ hg debugdrawdag <<'EOS'
1597 > D Z
1597 > D Z
1598 > /| | # replace: A -> C
1598 > /| | # replace: A -> C
1599 > A B C # D/D = D
1599 > A B C # D/D = D
1600 > EOS
1600 > EOS
1601 1 new orphan changesets
1601 1 new orphan changesets
1602 $ hg rebase -r A+B+D -d Z
1602 $ hg rebase -r A+B+D -d Z
1603 note: not rebasing 0:426bada5c675 "A" (A), already in destination as 2:96cc3511f894 "C" (C)
1603 note: not rebasing 0:426bada5c675 "A" (A), already in destination as 2:96cc3511f894 "C" (C)
1604 rebasing 1:fc2b737bb2e5 "B" (B)
1604 rebasing 1:fc2b737bb2e5 "B" (B)
1605 rebasing 3:b8ed089c80ad "D" (D)
1605 rebasing 3:b8ed089c80ad "D" (D)
1606
1606
1607 $ rm .hg/localtags
1607 $ rm .hg/localtags
1608 $ hg log -G
1608 $ hg log -G
1609 o 6:e4f78693cc88 D
1609 o 6:e4f78693cc88 D
1610 |
1610 |
1611 o 5:76840d832e98 B
1611 o 5:76840d832e98 B
1612 |
1612 |
1613 o 4:50e41c1f3950 Z
1613 o 4:50e41c1f3950 Z
1614 |
1614 |
1615 o 2:96cc3511f894 C
1615 o 2:96cc3511f894 C
1616
1616
1617 $ hg files -r tip
1617 $ hg files -r tip
1618 B
1618 B
1619 C
1619 C
1620 D
1620 D
1621 Z
1621 Z
1622
1622
1623 $ cd ..
1623 $ cd ..
1624
1624
1625 $ hg init p1-move-p2-succ
1625 $ hg init p1-move-p2-succ
1626 $ cd p1-move-p2-succ
1626 $ cd p1-move-p2-succ
1627 $ hg debugdrawdag <<'EOS'
1627 $ hg debugdrawdag <<'EOS'
1628 > D Z
1628 > D Z
1629 > /| | # replace: B -> C
1629 > /| | # replace: B -> C
1630 > A B C # D/D = D
1630 > A B C # D/D = D
1631 > EOS
1631 > EOS
1632 1 new orphan changesets
1632 1 new orphan changesets
1633 $ hg rebase -r B+A+D -d Z
1633 $ hg rebase -r B+A+D -d Z
1634 rebasing 0:426bada5c675 "A" (A)
1634 rebasing 0:426bada5c675 "A" (A)
1635 note: not rebasing 1:fc2b737bb2e5 "B" (B), already in destination as 2:96cc3511f894 "C" (C)
1635 note: not rebasing 1:fc2b737bb2e5 "B" (B), already in destination as 2:96cc3511f894 "C" (C)
1636 rebasing 3:b8ed089c80ad "D" (D)
1636 rebasing 3:b8ed089c80ad "D" (D)
1637
1637
1638 $ rm .hg/localtags
1638 $ rm .hg/localtags
1639 $ hg log -G
1639 $ hg log -G
1640 o 6:1b355ed94d82 D
1640 o 6:1b355ed94d82 D
1641 |
1641 |
1642 o 5:a81a74d764a6 A
1642 o 5:a81a74d764a6 A
1643 |
1643 |
1644 o 4:50e41c1f3950 Z
1644 o 4:50e41c1f3950 Z
1645 |
1645 |
1646 o 2:96cc3511f894 C
1646 o 2:96cc3511f894 C
1647
1647
1648 $ hg files -r tip
1648 $ hg files -r tip
1649 A
1649 A
1650 C
1650 C
1651 D
1651 D
1652 Z
1652 Z
1653
1653
1654 $ cd ..
1654 $ cd ..
1655
1655
1656 Test that bookmark is moved and working dir is updated when all changesets have
1656 Test that bookmark is moved and working dir is updated when all changesets have
1657 equivalents in destination
1657 equivalents in destination
1658 $ hg init rbsrepo && cd rbsrepo
1658 $ hg init rbsrepo && cd rbsrepo
1659 $ echo "[experimental]" > .hg/hgrc
1659 $ echo "[experimental]" > .hg/hgrc
1660 $ echo "evolution=true" >> .hg/hgrc
1660 $ echo "evolution=true" >> .hg/hgrc
1661 $ echo "rebaseskipobsolete=on" >> .hg/hgrc
1661 $ echo "rebaseskipobsolete=on" >> .hg/hgrc
1662 $ echo root > root && hg ci -Am root
1662 $ echo root > root && hg ci -Am root
1663 adding root
1663 adding root
1664 $ echo a > a && hg ci -Am a
1664 $ echo a > a && hg ci -Am a
1665 adding a
1665 adding a
1666 $ hg up 0
1666 $ hg up 0
1667 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1667 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1668 $ echo b > b && hg ci -Am b
1668 $ echo b > b && hg ci -Am b
1669 adding b
1669 adding b
1670 created new head
1670 created new head
1671 $ hg rebase -r 2 -d 1
1671 $ hg rebase -r 2 -d 1
1672 rebasing 2:1e9a3c00cbe9 "b" (tip)
1672 rebasing 2:1e9a3c00cbe9 "b" (tip)
1673 $ hg log -r . # working dir is at rev 3 (successor of 2)
1673 $ hg log -r . # working dir is at rev 3 (successor of 2)
1674 3:be1832deae9a b (no-eol)
1674 3:be1832deae9a b (no-eol)
1675 $ hg book -r 2 mybook --hidden # rev 2 has a bookmark on it now
1675 $ hg book -r 2 mybook --hidden # rev 2 has a bookmark on it now
1676 bookmarking hidden changeset 1e9a3c00cbe9
1676 bookmarking hidden changeset 1e9a3c00cbe9
1677 (hidden revision '1e9a3c00cbe9' was rewritten as: be1832deae9a)
1677 (hidden revision '1e9a3c00cbe9' was rewritten as: be1832deae9a)
1678 $ hg up 2 && hg log -r . # working dir is at rev 2 again
1678 $ hg up 2 && hg log -r . # working dir is at rev 2 again
1679 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1679 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1680 2:1e9a3c00cbe9 b (rewritten using rebase as 3:be1832deae9a) (no-eol)
1680 2:1e9a3c00cbe9 b (rewritten using rebase as 3:be1832deae9a) (no-eol)
1681 $ hg rebase -r 2 -d 3 --config experimental.evolution.track-operation=1
1681 $ hg rebase -r 2 -d 3 --config experimental.evolution.track-operation=1
1682 note: not rebasing 2:1e9a3c00cbe9 "b" (mybook), already in destination as 3:be1832deae9a "b" (tip)
1682 note: not rebasing 2:1e9a3c00cbe9 "b" (mybook), already in destination as 3:be1832deae9a "b" (tip)
1683 Check that working directory and bookmark was updated to rev 3 although rev 2
1683 Check that working directory and bookmark was updated to rev 3 although rev 2
1684 was skipped
1684 was skipped
1685 $ hg log -r .
1685 $ hg log -r .
1686 3:be1832deae9a b (no-eol)
1686 3:be1832deae9a b (no-eol)
1687 $ hg bookmarks
1687 $ hg bookmarks
1688 mybook 3:be1832deae9a
1688 mybook 3:be1832deae9a
1689 $ hg debugobsolete --rev tip
1689 $ hg debugobsolete --rev tip
1690 1e9a3c00cbe90d236ac05ef61efcc5e40b7412bc be1832deae9ac531caa7438b8dcf6055a122cd8e 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
1690 1e9a3c00cbe90d236ac05ef61efcc5e40b7412bc be1832deae9ac531caa7438b8dcf6055a122cd8e 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
1691
1691
1692 Obsoleted working parent and bookmark could be moved if an ancestor of working
1692 Obsoleted working parent and bookmark could be moved if an ancestor of working
1693 parent gets moved:
1693 parent gets moved:
1694
1694
1695 $ hg init $TESTTMP/ancestor-wd-move
1695 $ hg init $TESTTMP/ancestor-wd-move
1696 $ cd $TESTTMP/ancestor-wd-move
1696 $ cd $TESTTMP/ancestor-wd-move
1697 $ hg debugdrawdag <<'EOS'
1697 $ hg debugdrawdag <<'EOS'
1698 > E D1 # rebase: D1 -> D2
1698 > E D1 # rebase: D1 -> D2
1699 > | |
1699 > | |
1700 > | C
1700 > | C
1701 > D2 |
1701 > D2 |
1702 > | B
1702 > | B
1703 > |/
1703 > |/
1704 > A
1704 > A
1705 > EOS
1705 > EOS
1706 $ hg update D1 -q
1706 $ hg update D1 -q
1707 $ hg bookmark book -i
1707 $ hg bookmark book -i
1708 $ hg rebase -r B+D1 -d E
1708 $ hg rebase -r B+D1 -d E
1709 rebasing 1:112478962961 "B" (B)
1709 rebasing 1:112478962961 "B" (B)
1710 note: not rebasing 5:15ecf15e0114 "D1" (book D1 tip), already in destination as 2:0807738e0be9 "D2" (D2)
1710 note: not rebasing 5:15ecf15e0114 "D1" (book D1 tip), already in destination as 2:0807738e0be9 "D2" (D2)
1711 1 new orphan changesets
1711 1 new orphan changesets
1712 $ hg log -G -T '{desc} {bookmarks}'
1712 $ hg log -G -T '{desc} {bookmarks}'
1713 @ B book
1713 @ B book
1714 |
1714 |
1715 | x D1
1715 | x D1
1716 | |
1716 | |
1717 o | E
1717 o | E
1718 | |
1718 | |
1719 | * C
1719 | * C
1720 | |
1720 | |
1721 o | D2
1721 o | D2
1722 | |
1722 | |
1723 | x B
1723 | x B
1724 |/
1724 |/
1725 o A
1725 o A
1726
1726
1727 Rebasing a merge with one of its parent having a hidden successor
1727 Rebasing a merge with one of its parent having a hidden successor
1728
1728
1729 $ hg init $TESTTMP/merge-p1-hidden-successor
1729 $ hg init $TESTTMP/merge-p1-hidden-successor
1730 $ cd $TESTTMP/merge-p1-hidden-successor
1730 $ cd $TESTTMP/merge-p1-hidden-successor
1731
1731
1732 $ hg debugdrawdag <<'EOS'
1732 $ hg debugdrawdag <<'EOS'
1733 > E
1733 > E
1734 > |
1734 > |
1735 > B3 B2 # amend: B1 -> B2 -> B3
1735 > B3 B2 # amend: B1 -> B2 -> B3
1736 > |/ # B2 is hidden
1736 > |/ # B2 is hidden
1737 > | D
1737 > | D
1738 > | |\
1738 > | |\
1739 > | B1 C
1739 > | B1 C
1740 > |/
1740 > |/
1741 > A
1741 > A
1742 > EOS
1742 > EOS
1743 1 new orphan changesets
1743 1 new orphan changesets
1744
1744
1745 $ eval `hg tags -T '{tag}={node}\n'`
1745 $ eval `hg tags -T '{tag}={node}\n'`
1746 $ rm .hg/localtags
1746 $ rm .hg/localtags
1747
1747
1748 $ hg rebase -r $D -d $E
1748 $ hg rebase -r $D -d $E
1749 rebasing 5:9e62094e4d94 "D"
1749 rebasing 5:9e62094e4d94 "D"
1750
1750
1751 $ hg log -G
1751 $ hg log -G
1752 o 7:a699d059adcf D
1752 o 7:a699d059adcf D
1753 |\
1753 |\
1754 | o 6:ecc93090a95c E
1754 | o 6:ecc93090a95c E
1755 | |
1755 | |
1756 | o 4:0dc878468a23 B3
1756 | o 4:0dc878468a23 B3
1757 | |
1757 | |
1758 o | 1:96cc3511f894 C
1758 o | 1:96cc3511f894 C
1759 /
1759 /
1760 o 0:426bada5c675 A
1760 o 0:426bada5c675 A
1761
1761
1762 For some reasons (--hidden, rebaseskipobsolete=0, directaccess, etc.),
1762 For some reasons (--hidden, rebaseskipobsolete=0, directaccess, etc.),
1763 rebasestate may contain hidden hashes. "rebase --abort" should work regardless.
1763 rebasestate may contain hidden hashes. "rebase --abort" should work regardless.
1764
1764
1765 $ hg init $TESTTMP/hidden-state1
1765 $ hg init $TESTTMP/hidden-state1
1766 $ cd $TESTTMP/hidden-state1
1766 $ cd $TESTTMP/hidden-state1
1767 $ cat >> .hg/hgrc <<EOF
1767 $ cat >> .hg/hgrc <<EOF
1768 > [experimental]
1768 > [experimental]
1769 > rebaseskipobsolete=0
1769 > rebaseskipobsolete=0
1770 > EOF
1770 > EOF
1771
1771
1772 $ hg debugdrawdag <<'EOS'
1772 $ hg debugdrawdag <<'EOS'
1773 > C
1773 > C
1774 > |
1774 > |
1775 > D B # prune: B, C
1775 > D B # prune: B, C
1776 > |/ # B/D=B
1776 > |/ # B/D=B
1777 > A
1777 > A
1778 > EOS
1778 > EOS
1779
1779
1780 $ eval `hg tags -T '{tag}={node}\n'`
1780 $ eval `hg tags -T '{tag}={node}\n'`
1781 $ rm .hg/localtags
1781 $ rm .hg/localtags
1782
1782
1783 $ hg update -q $C --hidden
1783 $ hg update -q $C --hidden
1784 updated to hidden changeset 7829726be4dc
1784 updated to hidden changeset 7829726be4dc
1785 (hidden revision '7829726be4dc' is pruned)
1785 (hidden revision '7829726be4dc' is pruned)
1786 $ hg rebase -s $B -d $D
1786 $ hg rebase -s $B -d $D
1787 rebasing 1:2ec65233581b "B"
1787 rebasing 1:2ec65233581b "B"
1788 merging D
1788 merging D
1789 warning: conflicts while merging D! (edit, then use 'hg resolve --mark')
1789 warning: conflicts while merging D! (edit, then use 'hg resolve --mark')
1790 unresolved conflicts (see hg resolve, then hg rebase --continue)
1790 unresolved conflicts (see hg resolve, then hg rebase --continue)
1791 [1]
1791 [1]
1792
1792
1793 $ cp -R . $TESTTMP/hidden-state2
1793 $ cp -R . $TESTTMP/hidden-state2
1794
1794
1795 $ hg log -G
1795 $ hg log -G
1796 @ 2:b18e25de2cf5 D
1796 @ 2:b18e25de2cf5 D
1797 |
1797 |
1798 | @ 1:2ec65233581b B (pruned using prune)
1798 | @ 1:2ec65233581b B (pruned using prune)
1799 |/
1799 |/
1800 o 0:426bada5c675 A
1800 o 0:426bada5c675 A
1801
1801
1802 $ hg summary
1802 $ hg summary
1803 parent: 2:b18e25de2cf5 tip
1803 parent: 2:b18e25de2cf5 tip
1804 D
1804 D
1805 parent: 1:2ec65233581b (obsolete)
1805 parent: 1:2ec65233581b (obsolete)
1806 B
1806 B
1807 branch: default
1807 branch: default
1808 commit: 2 modified, 1 unknown, 1 unresolved (merge)
1808 commit: 2 modified, 1 unknown, 1 unresolved (merge)
1809 update: (current)
1809 update: (current)
1810 phases: 3 draft
1810 phases: 3 draft
1811 rebase: 0 rebased, 2 remaining (rebase --continue)
1811 rebase: 0 rebased, 2 remaining (rebase --continue)
1812
1812
1813 $ hg rebase --abort
1813 $ hg rebase --abort
1814 rebase aborted
1814 rebase aborted
1815
1815
1816 Also test --continue for the above case
1816 Also test --continue for the above case
1817
1817
1818 $ cd $TESTTMP/hidden-state2
1818 $ cd $TESTTMP/hidden-state2
1819 $ hg resolve -m
1819 $ hg resolve -m
1820 (no more unresolved files)
1820 (no more unresolved files)
1821 continue: hg rebase --continue
1821 continue: hg rebase --continue
1822 $ hg rebase --continue
1822 $ hg rebase --continue
1823 rebasing 1:2ec65233581b "B"
1823 rebasing 1:2ec65233581b "B"
1824 rebasing 3:7829726be4dc "C" (tip)
1824 rebasing 3:7829726be4dc "C" (tip)
1825 $ hg log -G
1825 $ hg log -G
1826 @ 5:1964d5d5b547 C
1826 @ 5:1964d5d5b547 C
1827 |
1827 |
1828 o 4:68deb90c12a2 B
1828 o 4:68deb90c12a2 B
1829 |
1829 |
1830 o 2:b18e25de2cf5 D
1830 o 2:b18e25de2cf5 D
1831 |
1831 |
1832 o 0:426bada5c675 A
1832 o 0:426bada5c675 A
1833
1833
1834 ====================
1834 ====================
1835 Test --stop option |
1835 Test --stop option |
1836 ====================
1836 ====================
1837 $ cd ..
1837 $ cd ..
1838 $ hg init rbstop
1838 $ hg init rbstop
1839 $ cd rbstop
1839 $ cd rbstop
1840 $ echo a>a
1840 $ echo a>a
1841 $ hg ci -Aqma
1841 $ hg ci -Aqma
1842 $ echo b>b
1842 $ echo b>b
1843 $ hg ci -Aqmb
1843 $ hg ci -Aqmb
1844 $ echo c>c
1844 $ echo c>c
1845 $ hg ci -Aqmc
1845 $ hg ci -Aqmc
1846 $ echo d>d
1846 $ echo d>d
1847 $ hg ci -Aqmd
1847 $ hg ci -Aqmd
1848 $ hg up 0 -q
1848 $ hg up 0 -q
1849 $ echo f>f
1849 $ echo f>f
1850 $ hg ci -Aqmf
1850 $ hg ci -Aqmf
1851 $ echo D>d
1851 $ echo D>d
1852 $ hg ci -Aqm "conflict with d"
1852 $ hg ci -Aqm "conflict with d"
1853 $ hg up 3 -q
1853 $ hg up 3 -q
1854 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1854 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1855 o 5:00bfc9898aeb test
1855 o 5:00bfc9898aeb test
1856 | conflict with d
1856 | conflict with d
1857 |
1857 |
1858 o 4:dafd40200f93 test
1858 o 4:dafd40200f93 test
1859 | f
1859 | f
1860 |
1860 |
1861 | @ 3:055a42cdd887 test
1861 | @ 3:055a42cdd887 test
1862 | | d
1862 | | d
1863 | |
1863 | |
1864 | o 2:177f92b77385 test
1864 | o 2:177f92b77385 test
1865 | | c
1865 | | c
1866 | |
1866 | |
1867 | o 1:d2ae7f538514 test
1867 | o 1:d2ae7f538514 test
1868 |/ b
1868 |/ b
1869 |
1869 |
1870 o 0:cb9a9f314b8b test
1870 o 0:cb9a9f314b8b test
1871 a
1871 a
1872
1872
1873 $ hg rebase -s 1 -d 5
1873 $ hg rebase -s 1 -d 5
1874 rebasing 1:d2ae7f538514 "b"
1874 rebasing 1:d2ae7f538514 "b"
1875 rebasing 2:177f92b77385 "c"
1875 rebasing 2:177f92b77385 "c"
1876 rebasing 3:055a42cdd887 "d"
1876 rebasing 3:055a42cdd887 "d"
1877 merging d
1877 merging d
1878 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
1878 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
1879 unresolved conflicts (see hg resolve, then hg rebase --continue)
1879 unresolved conflicts (see hg resolve, then hg rebase --continue)
1880 [1]
1880 [1]
1881 $ hg rebase --stop
1881 $ hg rebase --stop
1882 1 new orphan changesets
1882 1 new orphan changesets
1883 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1883 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1884 o 7:7fffad344617 test
1884 o 7:7fffad344617 test
1885 | c
1885 | c
1886 |
1886 |
1887 o 6:b15528633407 test
1887 o 6:b15528633407 test
1888 | b
1888 | b
1889 |
1889 |
1890 o 5:00bfc9898aeb test
1890 o 5:00bfc9898aeb test
1891 | conflict with d
1891 | conflict with d
1892 |
1892 |
1893 o 4:dafd40200f93 test
1893 o 4:dafd40200f93 test
1894 | f
1894 | f
1895 |
1895 |
1896 | @ 3:055a42cdd887 test
1896 | @ 3:055a42cdd887 test
1897 | | d
1897 | | d
1898 | |
1898 | |
1899 | x 2:177f92b77385 test
1899 | x 2:177f92b77385 test
1900 | | c
1900 | | c
1901 | |
1901 | |
1902 | x 1:d2ae7f538514 test
1902 | x 1:d2ae7f538514 test
1903 |/ b
1903 |/ b
1904 |
1904 |
1905 o 0:cb9a9f314b8b test
1905 o 0:cb9a9f314b8b test
1906 a
1906 a
1907
1907
1908 Test it aborts if unstable csets is not allowed:
1908 Test it aborts if unstable csets is not allowed:
1909 ===============================================
1909 ===============================================
1910 $ cat >> $HGRCPATH << EOF
1910 $ cat >> $HGRCPATH << EOF
1911 > [experimental]
1911 > [experimental]
1912 > evolution.allowunstable=False
1912 > evolution.allowunstable=False
1913 > EOF
1913 > EOF
1914
1914
1915 $ hg strip 6 --no-backup -q
1915 $ hg strip 6 --no-backup -q
1916 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1916 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1917 o 5:00bfc9898aeb test
1917 o 5:00bfc9898aeb test
1918 | conflict with d
1918 | conflict with d
1919 |
1919 |
1920 o 4:dafd40200f93 test
1920 o 4:dafd40200f93 test
1921 | f
1921 | f
1922 |
1922 |
1923 | @ 3:055a42cdd887 test
1923 | @ 3:055a42cdd887 test
1924 | | d
1924 | | d
1925 | |
1925 | |
1926 | o 2:177f92b77385 test
1926 | o 2:177f92b77385 test
1927 | | c
1927 | | c
1928 | |
1928 | |
1929 | o 1:d2ae7f538514 test
1929 | o 1:d2ae7f538514 test
1930 |/ b
1930 |/ b
1931 |
1931 |
1932 o 0:cb9a9f314b8b test
1932 o 0:cb9a9f314b8b test
1933 a
1933 a
1934
1934
1935 $ hg rebase -s 1 -d 5
1935 $ hg rebase -s 1 -d 5
1936 rebasing 1:d2ae7f538514 "b"
1936 rebasing 1:d2ae7f538514 "b"
1937 rebasing 2:177f92b77385 "c"
1937 rebasing 2:177f92b77385 "c"
1938 rebasing 3:055a42cdd887 "d"
1938 rebasing 3:055a42cdd887 "d"
1939 merging d
1939 merging d
1940 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
1940 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
1941 unresolved conflicts (see hg resolve, then hg rebase --continue)
1941 unresolved conflicts (see hg resolve, then hg rebase --continue)
1942 [1]
1942 [1]
1943 $ hg rebase --stop
1943 $ hg rebase --stop
1944 abort: cannot remove original changesets with unrebased descendants
1944 abort: cannot remove original changesets with unrebased descendants
1945 (either enable obsmarkers to allow unstable revisions or use --keep to keep original changesets)
1945 (either enable obsmarkers to allow unstable revisions or use --keep to keep original changesets)
1946 [255]
1946 [255]
1947 $ hg rebase --abort
1947 $ hg rebase --abort
1948 saved backup bundle to $TESTTMP/rbstop/.hg/strip-backup/b15528633407-6eb72b6f-backup.hg
1948 saved backup bundle to $TESTTMP/rbstop/.hg/strip-backup/b15528633407-6eb72b6f-backup.hg
1949 rebase aborted
1949 rebase aborted
1950
1950
1951 Test --stop when --keep is passed:
1951 Test --stop when --keep is passed:
1952 ==================================
1952 ==================================
1953 $ hg rebase -s 1 -d 5 --keep
1953 $ hg rebase -s 1 -d 5 --keep
1954 rebasing 1:d2ae7f538514 "b"
1954 rebasing 1:d2ae7f538514 "b"
1955 rebasing 2:177f92b77385 "c"
1955 rebasing 2:177f92b77385 "c"
1956 rebasing 3:055a42cdd887 "d"
1956 rebasing 3:055a42cdd887 "d"
1957 merging d
1957 merging d
1958 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
1958 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
1959 unresolved conflicts (see hg resolve, then hg rebase --continue)
1959 unresolved conflicts (see hg resolve, then hg rebase --continue)
1960 [1]
1960 [1]
1961 $ hg rebase --stop
1961 $ hg rebase --stop
1962 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1962 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1963 o 7:7fffad344617 test
1963 o 7:7fffad344617 test
1964 | c
1964 | c
1965 |
1965 |
1966 o 6:b15528633407 test
1966 o 6:b15528633407 test
1967 | b
1967 | b
1968 |
1968 |
1969 o 5:00bfc9898aeb test
1969 o 5:00bfc9898aeb test
1970 | conflict with d
1970 | conflict with d
1971 |
1971 |
1972 o 4:dafd40200f93 test
1972 o 4:dafd40200f93 test
1973 | f
1973 | f
1974 |
1974 |
1975 | @ 3:055a42cdd887 test
1975 | @ 3:055a42cdd887 test
1976 | | d
1976 | | d
1977 | |
1977 | |
1978 | o 2:177f92b77385 test
1978 | o 2:177f92b77385 test
1979 | | c
1979 | | c
1980 | |
1980 | |
1981 | o 1:d2ae7f538514 test
1981 | o 1:d2ae7f538514 test
1982 |/ b
1982 |/ b
1983 |
1983 |
1984 o 0:cb9a9f314b8b test
1984 o 0:cb9a9f314b8b test
1985 a
1985 a
1986
1986
1987 Test --stop aborts when --collapse was passed:
1987 Test --stop aborts when --collapse was passed:
1988 =============================================
1988 =============================================
1989 $ cat >> $HGRCPATH << EOF
1989 $ cat >> $HGRCPATH << EOF
1990 > [experimental]
1990 > [experimental]
1991 > evolution.allowunstable=True
1991 > evolution.allowunstable=True
1992 > EOF
1992 > EOF
1993
1993
1994 $ hg strip 6
1994 $ hg strip 6
1995 saved backup bundle to $TESTTMP/rbstop/.hg/strip-backup/b15528633407-6eb72b6f-backup.hg
1995 saved backup bundle to $TESTTMP/rbstop/.hg/strip-backup/b15528633407-6eb72b6f-backup.hg
1996 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1996 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
1997 o 5:00bfc9898aeb test
1997 o 5:00bfc9898aeb test
1998 | conflict with d
1998 | conflict with d
1999 |
1999 |
2000 o 4:dafd40200f93 test
2000 o 4:dafd40200f93 test
2001 | f
2001 | f
2002 |
2002 |
2003 | @ 3:055a42cdd887 test
2003 | @ 3:055a42cdd887 test
2004 | | d
2004 | | d
2005 | |
2005 | |
2006 | o 2:177f92b77385 test
2006 | o 2:177f92b77385 test
2007 | | c
2007 | | c
2008 | |
2008 | |
2009 | o 1:d2ae7f538514 test
2009 | o 1:d2ae7f538514 test
2010 |/ b
2010 |/ b
2011 |
2011 |
2012 o 0:cb9a9f314b8b test
2012 o 0:cb9a9f314b8b test
2013 a
2013 a
2014
2014
2015 $ hg rebase -s 1 -d 5 --collapse -m "collapsed b c d"
2015 $ hg rebase -s 1 -d 5 --collapse -m "collapsed b c d"
2016 rebasing 1:d2ae7f538514 "b"
2016 rebasing 1:d2ae7f538514 "b"
2017 rebasing 2:177f92b77385 "c"
2017 rebasing 2:177f92b77385 "c"
2018 rebasing 3:055a42cdd887 "d"
2018 rebasing 3:055a42cdd887 "d"
2019 merging d
2019 merging d
2020 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2020 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2021 unresolved conflicts (see hg resolve, then hg rebase --continue)
2021 unresolved conflicts (see hg resolve, then hg rebase --continue)
2022 [1]
2022 [1]
2023 $ hg rebase --stop
2023 $ hg rebase --stop
2024 abort: cannot stop in --collapse session
2024 abort: cannot stop in --collapse session
2025 [255]
2025 [255]
2026 $ hg rebase --abort
2026 $ hg rebase --abort
2027 rebase aborted
2027 rebase aborted
2028 $ hg diff
2028 $ hg diff
2029 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
2029 $ hg log -G --template "{rev}:{short(node)} {person(author)}\n{firstline(desc)} {topic}\n\n"
2030 o 5:00bfc9898aeb test
2030 o 5:00bfc9898aeb test
2031 | conflict with d
2031 | conflict with d
2032 |
2032 |
2033 o 4:dafd40200f93 test
2033 o 4:dafd40200f93 test
2034 | f
2034 | f
2035 |
2035 |
2036 | @ 3:055a42cdd887 test
2036 | @ 3:055a42cdd887 test
2037 | | d
2037 | | d
2038 | |
2038 | |
2039 | o 2:177f92b77385 test
2039 | o 2:177f92b77385 test
2040 | | c
2040 | | c
2041 | |
2041 | |
2042 | o 1:d2ae7f538514 test
2042 | o 1:d2ae7f538514 test
2043 |/ b
2043 |/ b
2044 |
2044 |
2045 o 0:cb9a9f314b8b test
2045 o 0:cb9a9f314b8b test
2046 a
2046 a
2047
2047
2048 Test --stop raise errors with conflicting options:
2048 Test --stop raise errors with conflicting options:
2049 =================================================
2049 =================================================
2050 $ hg rebase -s 3 -d 5
2050 $ hg rebase -s 3 -d 5
2051 rebasing 3:055a42cdd887 "d"
2051 rebasing 3:055a42cdd887 "d"
2052 merging d
2052 merging d
2053 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2053 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2054 unresolved conflicts (see hg resolve, then hg rebase --continue)
2054 unresolved conflicts (see hg resolve, then hg rebase --continue)
2055 [1]
2055 [1]
2056 $ hg rebase --stop --dry-run
2056 $ hg rebase --stop --dry-run
2057 abort: cannot specify both --dry-run and --stop
2057 abort: cannot specify both --stop and --dry-run
2058 [255]
2058 [255]
2059
2059
2060 $ hg rebase -s 3 -d 5
2060 $ hg rebase -s 3 -d 5
2061 abort: rebase in progress
2061 abort: rebase in progress
2062 (use 'hg rebase --continue' or 'hg rebase --abort')
2062 (use 'hg rebase --continue' or 'hg rebase --abort')
2063 [255]
2063 [255]
2064 $ hg rebase --stop --continue
2064 $ hg rebase --stop --continue
2065 abort: cannot specify both --stop and --continue
2065 abort: cannot specify both --stop and --continue
2066 [255]
2066 [255]
2067
2067
2068 Test --stop moves bookmarks of original revisions to new rebased nodes:
2068 Test --stop moves bookmarks of original revisions to new rebased nodes:
2069 ======================================================================
2069 ======================================================================
2070 $ cd ..
2070 $ cd ..
2071 $ hg init repo
2071 $ hg init repo
2072 $ cd repo
2072 $ cd repo
2073
2073
2074 $ echo a > a
2074 $ echo a > a
2075 $ hg ci -Am A
2075 $ hg ci -Am A
2076 adding a
2076 adding a
2077
2077
2078 $ echo b > b
2078 $ echo b > b
2079 $ hg ci -Am B
2079 $ hg ci -Am B
2080 adding b
2080 adding b
2081 $ hg book X
2081 $ hg book X
2082 $ hg book Y
2082 $ hg book Y
2083
2083
2084 $ echo c > c
2084 $ echo c > c
2085 $ hg ci -Am C
2085 $ hg ci -Am C
2086 adding c
2086 adding c
2087 $ hg book Z
2087 $ hg book Z
2088
2088
2089 $ echo d > d
2089 $ echo d > d
2090 $ hg ci -Am D
2090 $ hg ci -Am D
2091 adding d
2091 adding d
2092
2092
2093 $ hg up 0 -q
2093 $ hg up 0 -q
2094 $ echo e > e
2094 $ echo e > e
2095 $ hg ci -Am E
2095 $ hg ci -Am E
2096 adding e
2096 adding e
2097 created new head
2097 created new head
2098
2098
2099 $ echo doubt > d
2099 $ echo doubt > d
2100 $ hg ci -Am "conflict with d"
2100 $ hg ci -Am "conflict with d"
2101 adding d
2101 adding d
2102
2102
2103 $ hg log -GT "{rev}: {node|short} '{desc}' bookmarks: {bookmarks}\n"
2103 $ hg log -GT "{rev}: {node|short} '{desc}' bookmarks: {bookmarks}\n"
2104 @ 5: 39adf30bc1be 'conflict with d' bookmarks:
2104 @ 5: 39adf30bc1be 'conflict with d' bookmarks:
2105 |
2105 |
2106 o 4: 9c1e55f411b6 'E' bookmarks:
2106 o 4: 9c1e55f411b6 'E' bookmarks:
2107 |
2107 |
2108 | o 3: 67a385d4e6f2 'D' bookmarks: Z
2108 | o 3: 67a385d4e6f2 'D' bookmarks: Z
2109 | |
2109 | |
2110 | o 2: 49cb3485fa0c 'C' bookmarks: Y
2110 | o 2: 49cb3485fa0c 'C' bookmarks: Y
2111 | |
2111 | |
2112 | o 1: 6c81ed0049f8 'B' bookmarks: X
2112 | o 1: 6c81ed0049f8 'B' bookmarks: X
2113 |/
2113 |/
2114 o 0: 1994f17a630e 'A' bookmarks:
2114 o 0: 1994f17a630e 'A' bookmarks:
2115
2115
2116 $ hg rebase -s 1 -d 5
2116 $ hg rebase -s 1 -d 5
2117 rebasing 1:6c81ed0049f8 "B" (X)
2117 rebasing 1:6c81ed0049f8 "B" (X)
2118 rebasing 2:49cb3485fa0c "C" (Y)
2118 rebasing 2:49cb3485fa0c "C" (Y)
2119 rebasing 3:67a385d4e6f2 "D" (Z)
2119 rebasing 3:67a385d4e6f2 "D" (Z)
2120 merging d
2120 merging d
2121 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2121 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2122 unresolved conflicts (see hg resolve, then hg rebase --continue)
2122 unresolved conflicts (see hg resolve, then hg rebase --continue)
2123 [1]
2123 [1]
2124 $ hg rebase --stop
2124 $ hg rebase --stop
2125 1 new orphan changesets
2125 1 new orphan changesets
2126 $ hg log -GT "{rev}: {node|short} '{desc}' bookmarks: {bookmarks}\n"
2126 $ hg log -GT "{rev}: {node|short} '{desc}' bookmarks: {bookmarks}\n"
2127 o 7: 9c86c650b686 'C' bookmarks: Y
2127 o 7: 9c86c650b686 'C' bookmarks: Y
2128 |
2128 |
2129 o 6: 9b87b54e5fd8 'B' bookmarks: X
2129 o 6: 9b87b54e5fd8 'B' bookmarks: X
2130 |
2130 |
2131 @ 5: 39adf30bc1be 'conflict with d' bookmarks:
2131 @ 5: 39adf30bc1be 'conflict with d' bookmarks:
2132 |
2132 |
2133 o 4: 9c1e55f411b6 'E' bookmarks:
2133 o 4: 9c1e55f411b6 'E' bookmarks:
2134 |
2134 |
2135 | * 3: 67a385d4e6f2 'D' bookmarks: Z
2135 | * 3: 67a385d4e6f2 'D' bookmarks: Z
2136 | |
2136 | |
2137 | x 2: 49cb3485fa0c 'C' bookmarks:
2137 | x 2: 49cb3485fa0c 'C' bookmarks:
2138 | |
2138 | |
2139 | x 1: 6c81ed0049f8 'B' bookmarks:
2139 | x 1: 6c81ed0049f8 'B' bookmarks:
2140 |/
2140 |/
2141 o 0: 1994f17a630e 'A' bookmarks:
2141 o 0: 1994f17a630e 'A' bookmarks:
2142
2142
General Comments 0
You need to be logged in to leave comments. Login now