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