##// END OF EJS Templates
rebase: raise error for options conflicting with --stop...
Sushil khanchi -
r39129:2cf0b8b8 default
parent child Browse files
Show More
@@ -1,1940 +1,1945
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 or aborted with --abort/-a.
736 continued with --continue/-c or aborted with --abort/-a.
737
737
738 .. container:: verbose
738 .. container:: verbose
739
739
740 Examples:
740 Examples:
741
741
742 - move "local changes" (current commit back to branching point)
742 - move "local changes" (current commit back to branching point)
743 to the current branch tip after a pull::
743 to the current branch tip after a pull::
744
744
745 hg rebase
745 hg rebase
746
746
747 - move a single changeset to the stable branch::
747 - move a single changeset to the stable branch::
748
748
749 hg rebase -r 5f493448 -d stable
749 hg rebase -r 5f493448 -d stable
750
750
751 - splice a commit and all its descendants onto another part of history::
751 - splice a commit and all its descendants onto another part of history::
752
752
753 hg rebase --source c0c3 --dest 4cf9
753 hg rebase --source c0c3 --dest 4cf9
754
754
755 - rebase everything on a branch marked by a bookmark onto the
755 - rebase everything on a branch marked by a bookmark onto the
756 default branch::
756 default branch::
757
757
758 hg rebase --base myfeature --dest default
758 hg rebase --base myfeature --dest default
759
759
760 - collapse a sequence of changes into a single commit::
760 - collapse a sequence of changes into a single commit::
761
761
762 hg rebase --collapse -r 1520:1525 -d .
762 hg rebase --collapse -r 1520:1525 -d .
763
763
764 - move a named branch while preserving its name::
764 - move a named branch while preserving its name::
765
765
766 hg rebase -r "branch(featureX)" -d 1.3 --keepbranches
766 hg rebase -r "branch(featureX)" -d 1.3 --keepbranches
767
767
768 - stabilize orphaned changesets so history looks linear::
768 - stabilize orphaned changesets so history looks linear::
769
769
770 hg rebase -r 'orphan()-obsolete()'\
770 hg rebase -r 'orphan()-obsolete()'\
771 -d 'first(max((successors(max(roots(ALLSRC) & ::SRC)^)-obsolete())::) +\
771 -d 'first(max((successors(max(roots(ALLSRC) & ::SRC)^)-obsolete())::) +\
772 max(::((roots(ALLSRC) & ::SRC)^)-obsolete()))'
772 max(::((roots(ALLSRC) & ::SRC)^)-obsolete()))'
773
773
774 Configuration Options:
774 Configuration Options:
775
775
776 You can make rebase require a destination if you set the following config
776 You can make rebase require a destination if you set the following config
777 option::
777 option::
778
778
779 [commands]
779 [commands]
780 rebase.requiredest = True
780 rebase.requiredest = True
781
781
782 By default, rebase will close the transaction after each commit. For
782 By default, rebase will close the transaction after each commit. For
783 performance purposes, you can configure rebase to use a single transaction
783 performance purposes, you can configure rebase to use a single transaction
784 across the entire rebase. WARNING: This setting introduces a significant
784 across the entire rebase. WARNING: This setting introduces a significant
785 risk of losing the work you've done in a rebase if the rebase aborts
785 risk of losing the work you've done in a rebase if the rebase aborts
786 unexpectedly::
786 unexpectedly::
787
787
788 [rebase]
788 [rebase]
789 singletransaction = True
789 singletransaction = True
790
790
791 By default, rebase writes to the working copy, but you can configure it to
791 By default, rebase writes to the working copy, but you can configure it to
792 run in-memory for for better performance, and to allow it to run if the
792 run in-memory for for better performance, and to allow it to run if the
793 working copy is dirty::
793 working copy is dirty::
794
794
795 [rebase]
795 [rebase]
796 experimental.inmemory = True
796 experimental.inmemory = True
797
797
798 Return Values:
798 Return Values:
799
799
800 Returns 0 on success, 1 if nothing to rebase or there are
800 Returns 0 on success, 1 if nothing to rebase or there are
801 unresolved conflicts.
801 unresolved conflicts.
802
802
803 """
803 """
804 opts = pycompat.byteskwargs(opts)
804 opts = pycompat.byteskwargs(opts)
805 inmemory = ui.configbool('rebase', 'experimental.inmemory')
805 inmemory = ui.configbool('rebase', 'experimental.inmemory')
806 dryrun = opts.get('dry_run')
806 dryrun = opts.get('dry_run')
807 stop = opts.get('stop')
807 stop = opts.get('stop')
808 if stop:
809 if opts.get('dry_run') or opts.get('confirm'):
810 raise error.Abort(_('cannot use --stop with --dry-run '
811 'or --confirm'))
812 if opts.get('abort') or opts.get('continue'):
813 raise error.Abort(_('cannot use --stop with --abort or --continue'))
808 if dryrun:
814 if dryrun:
809 if opts.get('abort'):
815 if opts.get('abort'):
810 raise error.Abort(_('cannot specify both --dry-run and --abort'))
816 raise error.Abort(_('cannot specify both --dry-run and --abort'))
811 if opts.get('continue'):
817 if opts.get('continue'):
812 raise error.Abort(_('cannot specify both --dry-run and --continue'))
818 raise error.Abort(_('cannot specify both --dry-run and --continue'))
813 if opts.get('confirm'):
819 if opts.get('confirm'):
814 dryrun = True
820 dryrun = True
815 if opts.get('dry_run'):
821 if opts.get('dry_run'):
816 raise error.Abort(_('cannot specify both --confirm and --dry-run'))
822 raise error.Abort(_('cannot specify both --confirm and --dry-run'))
817 if opts.get('abort'):
823 if opts.get('abort'):
818 raise error.Abort(_('cannot specify both --confirm and --abort'))
824 raise error.Abort(_('cannot specify both --confirm and --abort'))
819 if opts.get('continue'):
825 if opts.get('continue'):
820 raise error.Abort(_('cannot specify both --confirm and --continue'))
826 raise error.Abort(_('cannot specify both --confirm and --continue'))
821
827
822 if (opts.get('continue') or opts.get('abort') or
828 if (opts.get('continue') or opts.get('abort') or
823 repo.currenttransaction() is not None):
829 repo.currenttransaction() is not None):
824 # in-memory rebase is not compatible with resuming rebases.
830 # in-memory rebase is not compatible with resuming rebases.
825 # (Or if it is run within a transaction, since the restart logic can
831 # (Or if it is run within a transaction, since the restart logic can
826 # fail the entire transaction.)
832 # fail the entire transaction.)
827 inmemory = False
833 inmemory = False
828
834
829 if opts.get('auto_orphans'):
835 if opts.get('auto_orphans'):
830 for key in opts:
836 for key in opts:
831 if key != 'auto_orphans' and opts.get(key):
837 if key != 'auto_orphans' and opts.get(key):
832 raise error.Abort(_('--auto-orphans is incompatible with %s') %
838 raise error.Abort(_('--auto-orphans is incompatible with %s') %
833 ('--' + key))
839 ('--' + key))
834 userrevs = list(repo.revs(opts.get('auto_orphans')))
840 userrevs = list(repo.revs(opts.get('auto_orphans')))
835 opts['rev'] = [revsetlang.formatspec('%ld and orphan()', userrevs)]
841 opts['rev'] = [revsetlang.formatspec('%ld and orphan()', userrevs)]
836 opts['dest'] = '_destautoorphanrebase(SRC)'
842 opts['dest'] = '_destautoorphanrebase(SRC)'
837
843
838 if dryrun:
844 if dryrun:
839 return _dryrunrebase(ui, repo, opts)
845 return _dryrunrebase(ui, repo, opts)
840 elif stop:
846 elif stop:
841 rbsrt = rebaseruntime(repo, ui)
847 rbsrt = rebaseruntime(repo, ui)
842 rbsrt.restorestatus()
848 rbsrt.restorestatus()
843
849
844 #todo: raise error for conflicting options
845 if rbsrt.collapsef:
850 if rbsrt.collapsef:
846 raise error.Abort(_("cannot stop in --collapse session"))
851 raise error.Abort(_("cannot stop in --collapse session"))
847 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
852 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
848 if not (rbsrt.keepf or allowunstable):
853 if not (rbsrt.keepf or allowunstable):
849 raise error.Abort(_("cannot remove original changesets with"
854 raise error.Abort(_("cannot remove original changesets with"
850 " unrebased descendants"),
855 " unrebased descendants"),
851 hint=_('either enable obsmarkers to allow unstable '
856 hint=_('either enable obsmarkers to allow unstable '
852 'revisions or use --keep to keep original '
857 'revisions or use --keep to keep original '
853 'changesets'))
858 'changesets'))
854 with repo.wlock(), repo.lock():
859 with repo.wlock(), repo.lock():
855 if needupdate(repo, rbsrt.state):
860 if needupdate(repo, rbsrt.state):
856 # update to the current working revision
861 # update to the current working revision
857 # to clear interrupted merge
862 # to clear interrupted merge
858 hg.updaterepo(repo, rbsrt.originalwd, overwrite=True)
863 hg.updaterepo(repo, rbsrt.originalwd, overwrite=True)
859 rbsrt._finishrebase()
864 rbsrt._finishrebase()
860 return 0
865 return 0
861 elif inmemory:
866 elif inmemory:
862 try:
867 try:
863 # in-memory merge doesn't support conflicts, so if we hit any, abort
868 # in-memory merge doesn't support conflicts, so if we hit any, abort
864 # and re-run as an on-disk merge.
869 # and re-run as an on-disk merge.
865 overrides = {('rebase', 'singletransaction'): True}
870 overrides = {('rebase', 'singletransaction'): True}
866 with ui.configoverride(overrides, 'rebase'):
871 with ui.configoverride(overrides, 'rebase'):
867 return _dorebase(ui, repo, opts, inmemory=inmemory)
872 return _dorebase(ui, repo, opts, inmemory=inmemory)
868 except error.InMemoryMergeConflictsError:
873 except error.InMemoryMergeConflictsError:
869 ui.warn(_('hit merge conflicts; re-running rebase without in-memory'
874 ui.warn(_('hit merge conflicts; re-running rebase without in-memory'
870 ' merge\n'))
875 ' merge\n'))
871 _dorebase(ui, repo, {'abort': True})
876 _dorebase(ui, repo, {'abort': True})
872 return _dorebase(ui, repo, opts, inmemory=False)
877 return _dorebase(ui, repo, opts, inmemory=False)
873 else:
878 else:
874 return _dorebase(ui, repo, opts)
879 return _dorebase(ui, repo, opts)
875
880
876 def _dryrunrebase(ui, repo, opts):
881 def _dryrunrebase(ui, repo, opts):
877 rbsrt = rebaseruntime(repo, ui, inmemory=True, opts=opts)
882 rbsrt = rebaseruntime(repo, ui, inmemory=True, opts=opts)
878 confirm = opts.get('confirm')
883 confirm = opts.get('confirm')
879 if confirm:
884 if confirm:
880 ui.status(_('starting in-memory rebase\n'))
885 ui.status(_('starting in-memory rebase\n'))
881 else:
886 else:
882 ui.status(_('starting dry-run rebase; repository will not be '
887 ui.status(_('starting dry-run rebase; repository will not be '
883 'changed\n'))
888 'changed\n'))
884 with repo.wlock(), repo.lock():
889 with repo.wlock(), repo.lock():
885 needsabort = True
890 needsabort = True
886 try:
891 try:
887 overrides = {('rebase', 'singletransaction'): True}
892 overrides = {('rebase', 'singletransaction'): True}
888 with ui.configoverride(overrides, 'rebase'):
893 with ui.configoverride(overrides, 'rebase'):
889 _origrebase(ui, repo, opts, rbsrt, inmemory=True,
894 _origrebase(ui, repo, opts, rbsrt, inmemory=True,
890 leaveunfinished=True)
895 leaveunfinished=True)
891 except error.InMemoryMergeConflictsError:
896 except error.InMemoryMergeConflictsError:
892 ui.status(_('hit a merge conflict\n'))
897 ui.status(_('hit a merge conflict\n'))
893 return 1
898 return 1
894 else:
899 else:
895 if confirm:
900 if confirm:
896 ui.status(_('rebase completed successfully\n'))
901 ui.status(_('rebase completed successfully\n'))
897 if not ui.promptchoice(_(b'apply changes (yn)?'
902 if not ui.promptchoice(_(b'apply changes (yn)?'
898 b'$$ &Yes $$ &No')):
903 b'$$ &Yes $$ &No')):
899 # finish unfinished rebase
904 # finish unfinished rebase
900 rbsrt._finishrebase()
905 rbsrt._finishrebase()
901 else:
906 else:
902 rbsrt._prepareabortorcontinue(isabort=True, backup=False,
907 rbsrt._prepareabortorcontinue(isabort=True, backup=False,
903 suppwarns=True)
908 suppwarns=True)
904 needsabort = False
909 needsabort = False
905 else:
910 else:
906 ui.status(_('dry-run rebase completed successfully; run without'
911 ui.status(_('dry-run rebase completed successfully; run without'
907 ' -n/--dry-run to perform this rebase\n'))
912 ' -n/--dry-run to perform this rebase\n'))
908 return 0
913 return 0
909 finally:
914 finally:
910 if needsabort:
915 if needsabort:
911 # no need to store backup in case of dryrun
916 # no need to store backup in case of dryrun
912 rbsrt._prepareabortorcontinue(isabort=True, backup=False,
917 rbsrt._prepareabortorcontinue(isabort=True, backup=False,
913 suppwarns=True)
918 suppwarns=True)
914
919
915 def _dorebase(ui, repo, opts, inmemory=False):
920 def _dorebase(ui, repo, opts, inmemory=False):
916 rbsrt = rebaseruntime(repo, ui, inmemory, opts)
921 rbsrt = rebaseruntime(repo, ui, inmemory, opts)
917 return _origrebase(ui, repo, opts, rbsrt, inmemory=inmemory)
922 return _origrebase(ui, repo, opts, rbsrt, inmemory=inmemory)
918
923
919 def _origrebase(ui, repo, opts, rbsrt, inmemory=False, leaveunfinished=False):
924 def _origrebase(ui, repo, opts, rbsrt, inmemory=False, leaveunfinished=False):
920 with repo.wlock(), repo.lock():
925 with repo.wlock(), repo.lock():
921 # Validate input and define rebasing points
926 # Validate input and define rebasing points
922 destf = opts.get('dest', None)
927 destf = opts.get('dest', None)
923 srcf = opts.get('source', None)
928 srcf = opts.get('source', None)
924 basef = opts.get('base', None)
929 basef = opts.get('base', None)
925 revf = opts.get('rev', [])
930 revf = opts.get('rev', [])
926 # search default destination in this space
931 # search default destination in this space
927 # used in the 'hg pull --rebase' case, see issue 5214.
932 # used in the 'hg pull --rebase' case, see issue 5214.
928 destspace = opts.get('_destspace')
933 destspace = opts.get('_destspace')
929 contf = opts.get('continue')
934 contf = opts.get('continue')
930 abortf = opts.get('abort')
935 abortf = opts.get('abort')
931 if opts.get('interactive'):
936 if opts.get('interactive'):
932 try:
937 try:
933 if extensions.find('histedit'):
938 if extensions.find('histedit'):
934 enablehistedit = ''
939 enablehistedit = ''
935 except KeyError:
940 except KeyError:
936 enablehistedit = " --config extensions.histedit="
941 enablehistedit = " --config extensions.histedit="
937 help = "hg%s help -e histedit" % enablehistedit
942 help = "hg%s help -e histedit" % enablehistedit
938 msg = _("interactive history editing is supported by the "
943 msg = _("interactive history editing is supported by the "
939 "'histedit' extension (see \"%s\")") % help
944 "'histedit' extension (see \"%s\")") % help
940 raise error.Abort(msg)
945 raise error.Abort(msg)
941
946
942 if rbsrt.collapsemsg and not rbsrt.collapsef:
947 if rbsrt.collapsemsg and not rbsrt.collapsef:
943 raise error.Abort(
948 raise error.Abort(
944 _('message can only be specified with collapse'))
949 _('message can only be specified with collapse'))
945
950
946 if contf or abortf:
951 if contf or abortf:
947 if contf and abortf:
952 if contf and abortf:
948 raise error.Abort(_('cannot use both abort and continue'))
953 raise error.Abort(_('cannot use both abort and continue'))
949 if rbsrt.collapsef:
954 if rbsrt.collapsef:
950 raise error.Abort(
955 raise error.Abort(
951 _('cannot use collapse with continue or abort'))
956 _('cannot use collapse with continue or abort'))
952 if srcf or basef or destf:
957 if srcf or basef or destf:
953 raise error.Abort(
958 raise error.Abort(
954 _('abort and continue do not allow specifying revisions'))
959 _('abort and continue do not allow specifying revisions'))
955 if abortf and opts.get('tool', False):
960 if abortf and opts.get('tool', False):
956 ui.warn(_('tool option will be ignored\n'))
961 ui.warn(_('tool option will be ignored\n'))
957 if contf:
962 if contf:
958 ms = mergemod.mergestate.read(repo)
963 ms = mergemod.mergestate.read(repo)
959 mergeutil.checkunresolved(ms)
964 mergeutil.checkunresolved(ms)
960
965
961 retcode = rbsrt._prepareabortorcontinue(abortf)
966 retcode = rbsrt._prepareabortorcontinue(abortf)
962 if retcode is not None:
967 if retcode is not None:
963 return retcode
968 return retcode
964 else:
969 else:
965 destmap = _definedestmap(ui, repo, inmemory, destf, srcf, basef,
970 destmap = _definedestmap(ui, repo, inmemory, destf, srcf, basef,
966 revf, destspace=destspace)
971 revf, destspace=destspace)
967 retcode = rbsrt._preparenewrebase(destmap)
972 retcode = rbsrt._preparenewrebase(destmap)
968 if retcode is not None:
973 if retcode is not None:
969 return retcode
974 return retcode
970 storecollapsemsg(repo, rbsrt.collapsemsg)
975 storecollapsemsg(repo, rbsrt.collapsemsg)
971
976
972 tr = None
977 tr = None
973
978
974 singletr = ui.configbool('rebase', 'singletransaction')
979 singletr = ui.configbool('rebase', 'singletransaction')
975 if singletr:
980 if singletr:
976 tr = repo.transaction('rebase')
981 tr = repo.transaction('rebase')
977
982
978 # If `rebase.singletransaction` is enabled, wrap the entire operation in
983 # If `rebase.singletransaction` is enabled, wrap the entire operation in
979 # one transaction here. Otherwise, transactions are obtained when
984 # one transaction here. Otherwise, transactions are obtained when
980 # committing each node, which is slower but allows partial success.
985 # committing each node, which is slower but allows partial success.
981 with util.acceptintervention(tr):
986 with util.acceptintervention(tr):
982 # Same logic for the dirstate guard, except we don't create one when
987 # Same logic for the dirstate guard, except we don't create one when
983 # rebasing in-memory (it's not needed).
988 # rebasing in-memory (it's not needed).
984 dsguard = None
989 dsguard = None
985 if singletr and not inmemory:
990 if singletr and not inmemory:
986 dsguard = dirstateguard.dirstateguard(repo, 'rebase')
991 dsguard = dirstateguard.dirstateguard(repo, 'rebase')
987 with util.acceptintervention(dsguard):
992 with util.acceptintervention(dsguard):
988 rbsrt._performrebase(tr)
993 rbsrt._performrebase(tr)
989 if not leaveunfinished:
994 if not leaveunfinished:
990 rbsrt._finishrebase()
995 rbsrt._finishrebase()
991
996
992 def _definedestmap(ui, repo, inmemory, destf=None, srcf=None, basef=None,
997 def _definedestmap(ui, repo, inmemory, destf=None, srcf=None, basef=None,
993 revf=None, destspace=None):
998 revf=None, destspace=None):
994 """use revisions argument to define destmap {srcrev: destrev}"""
999 """use revisions argument to define destmap {srcrev: destrev}"""
995 if revf is None:
1000 if revf is None:
996 revf = []
1001 revf = []
997
1002
998 # destspace is here to work around issues with `hg pull --rebase` see
1003 # destspace is here to work around issues with `hg pull --rebase` see
999 # issue5214 for details
1004 # issue5214 for details
1000 if srcf and basef:
1005 if srcf and basef:
1001 raise error.Abort(_('cannot specify both a source and a base'))
1006 raise error.Abort(_('cannot specify both a source and a base'))
1002 if revf and basef:
1007 if revf and basef:
1003 raise error.Abort(_('cannot specify both a revision and a base'))
1008 raise error.Abort(_('cannot specify both a revision and a base'))
1004 if revf and srcf:
1009 if revf and srcf:
1005 raise error.Abort(_('cannot specify both a revision and a source'))
1010 raise error.Abort(_('cannot specify both a revision and a source'))
1006
1011
1007 if not inmemory:
1012 if not inmemory:
1008 cmdutil.checkunfinished(repo)
1013 cmdutil.checkunfinished(repo)
1009 cmdutil.bailifchanged(repo)
1014 cmdutil.bailifchanged(repo)
1010
1015
1011 if ui.configbool('commands', 'rebase.requiredest') and not destf:
1016 if ui.configbool('commands', 'rebase.requiredest') and not destf:
1012 raise error.Abort(_('you must specify a destination'),
1017 raise error.Abort(_('you must specify a destination'),
1013 hint=_('use: hg rebase -d REV'))
1018 hint=_('use: hg rebase -d REV'))
1014
1019
1015 dest = None
1020 dest = None
1016
1021
1017 if revf:
1022 if revf:
1018 rebaseset = scmutil.revrange(repo, revf)
1023 rebaseset = scmutil.revrange(repo, revf)
1019 if not rebaseset:
1024 if not rebaseset:
1020 ui.status(_('empty "rev" revision set - nothing to rebase\n'))
1025 ui.status(_('empty "rev" revision set - nothing to rebase\n'))
1021 return None
1026 return None
1022 elif srcf:
1027 elif srcf:
1023 src = scmutil.revrange(repo, [srcf])
1028 src = scmutil.revrange(repo, [srcf])
1024 if not src:
1029 if not src:
1025 ui.status(_('empty "source" revision set - nothing to rebase\n'))
1030 ui.status(_('empty "source" revision set - nothing to rebase\n'))
1026 return None
1031 return None
1027 rebaseset = repo.revs('(%ld)::', src)
1032 rebaseset = repo.revs('(%ld)::', src)
1028 assert rebaseset
1033 assert rebaseset
1029 else:
1034 else:
1030 base = scmutil.revrange(repo, [basef or '.'])
1035 base = scmutil.revrange(repo, [basef or '.'])
1031 if not base:
1036 if not base:
1032 ui.status(_('empty "base" revision set - '
1037 ui.status(_('empty "base" revision set - '
1033 "can't compute rebase set\n"))
1038 "can't compute rebase set\n"))
1034 return None
1039 return None
1035 if destf:
1040 if destf:
1036 # --base does not support multiple destinations
1041 # --base does not support multiple destinations
1037 dest = scmutil.revsingle(repo, destf)
1042 dest = scmutil.revsingle(repo, destf)
1038 else:
1043 else:
1039 dest = repo[_destrebase(repo, base, destspace=destspace)]
1044 dest = repo[_destrebase(repo, base, destspace=destspace)]
1040 destf = bytes(dest)
1045 destf = bytes(dest)
1041
1046
1042 roots = [] # selected children of branching points
1047 roots = [] # selected children of branching points
1043 bpbase = {} # {branchingpoint: [origbase]}
1048 bpbase = {} # {branchingpoint: [origbase]}
1044 for b in base: # group bases by branching points
1049 for b in base: # group bases by branching points
1045 bp = repo.revs('ancestor(%d, %d)', b, dest.rev()).first()
1050 bp = repo.revs('ancestor(%d, %d)', b, dest.rev()).first()
1046 bpbase[bp] = bpbase.get(bp, []) + [b]
1051 bpbase[bp] = bpbase.get(bp, []) + [b]
1047 if None in bpbase:
1052 if None in bpbase:
1048 # emulate the old behavior, showing "nothing to rebase" (a better
1053 # emulate the old behavior, showing "nothing to rebase" (a better
1049 # behavior may be abort with "cannot find branching point" error)
1054 # behavior may be abort with "cannot find branching point" error)
1050 bpbase.clear()
1055 bpbase.clear()
1051 for bp, bs in bpbase.iteritems(): # calculate roots
1056 for bp, bs in bpbase.iteritems(): # calculate roots
1052 roots += list(repo.revs('children(%d) & ancestors(%ld)', bp, bs))
1057 roots += list(repo.revs('children(%d) & ancestors(%ld)', bp, bs))
1053
1058
1054 rebaseset = repo.revs('%ld::', roots)
1059 rebaseset = repo.revs('%ld::', roots)
1055
1060
1056 if not rebaseset:
1061 if not rebaseset:
1057 # transform to list because smartsets are not comparable to
1062 # transform to list because smartsets are not comparable to
1058 # lists. This should be improved to honor laziness of
1063 # lists. This should be improved to honor laziness of
1059 # smartset.
1064 # smartset.
1060 if list(base) == [dest.rev()]:
1065 if list(base) == [dest.rev()]:
1061 if basef:
1066 if basef:
1062 ui.status(_('nothing to rebase - %s is both "base"'
1067 ui.status(_('nothing to rebase - %s is both "base"'
1063 ' and destination\n') % dest)
1068 ' and destination\n') % dest)
1064 else:
1069 else:
1065 ui.status(_('nothing to rebase - working directory '
1070 ui.status(_('nothing to rebase - working directory '
1066 'parent is also destination\n'))
1071 'parent is also destination\n'))
1067 elif not repo.revs('%ld - ::%d', base, dest.rev()):
1072 elif not repo.revs('%ld - ::%d', base, dest.rev()):
1068 if basef:
1073 if basef:
1069 ui.status(_('nothing to rebase - "base" %s is '
1074 ui.status(_('nothing to rebase - "base" %s is '
1070 'already an ancestor of destination '
1075 'already an ancestor of destination '
1071 '%s\n') %
1076 '%s\n') %
1072 ('+'.join(bytes(repo[r]) for r in base),
1077 ('+'.join(bytes(repo[r]) for r in base),
1073 dest))
1078 dest))
1074 else:
1079 else:
1075 ui.status(_('nothing to rebase - working '
1080 ui.status(_('nothing to rebase - working '
1076 'directory parent is already an '
1081 'directory parent is already an '
1077 'ancestor of destination %s\n') % dest)
1082 'ancestor of destination %s\n') % dest)
1078 else: # can it happen?
1083 else: # can it happen?
1079 ui.status(_('nothing to rebase from %s to %s\n') %
1084 ui.status(_('nothing to rebase from %s to %s\n') %
1080 ('+'.join(bytes(repo[r]) for r in base), dest))
1085 ('+'.join(bytes(repo[r]) for r in base), dest))
1081 return None
1086 return None
1082
1087
1083 rebasingwcp = repo['.'].rev() in rebaseset
1088 rebasingwcp = repo['.'].rev() in rebaseset
1084 ui.log("rebase", "", rebase_rebasing_wcp=rebasingwcp)
1089 ui.log("rebase", "", rebase_rebasing_wcp=rebasingwcp)
1085 if inmemory and rebasingwcp:
1090 if inmemory and rebasingwcp:
1086 # Check these since we did not before.
1091 # Check these since we did not before.
1087 cmdutil.checkunfinished(repo)
1092 cmdutil.checkunfinished(repo)
1088 cmdutil.bailifchanged(repo)
1093 cmdutil.bailifchanged(repo)
1089
1094
1090 if not destf:
1095 if not destf:
1091 dest = repo[_destrebase(repo, rebaseset, destspace=destspace)]
1096 dest = repo[_destrebase(repo, rebaseset, destspace=destspace)]
1092 destf = bytes(dest)
1097 destf = bytes(dest)
1093
1098
1094 allsrc = revsetlang.formatspec('%ld', rebaseset)
1099 allsrc = revsetlang.formatspec('%ld', rebaseset)
1095 alias = {'ALLSRC': allsrc}
1100 alias = {'ALLSRC': allsrc}
1096
1101
1097 if dest is None:
1102 if dest is None:
1098 try:
1103 try:
1099 # fast path: try to resolve dest without SRC alias
1104 # fast path: try to resolve dest without SRC alias
1100 dest = scmutil.revsingle(repo, destf, localalias=alias)
1105 dest = scmutil.revsingle(repo, destf, localalias=alias)
1101 except error.RepoLookupError:
1106 except error.RepoLookupError:
1102 # multi-dest path: resolve dest for each SRC separately
1107 # multi-dest path: resolve dest for each SRC separately
1103 destmap = {}
1108 destmap = {}
1104 for r in rebaseset:
1109 for r in rebaseset:
1105 alias['SRC'] = revsetlang.formatspec('%d', r)
1110 alias['SRC'] = revsetlang.formatspec('%d', r)
1106 # use repo.anyrevs instead of scmutil.revsingle because we
1111 # use repo.anyrevs instead of scmutil.revsingle because we
1107 # don't want to abort if destset is empty.
1112 # don't want to abort if destset is empty.
1108 destset = repo.anyrevs([destf], user=True, localalias=alias)
1113 destset = repo.anyrevs([destf], user=True, localalias=alias)
1109 size = len(destset)
1114 size = len(destset)
1110 if size == 1:
1115 if size == 1:
1111 destmap[r] = destset.first()
1116 destmap[r] = destset.first()
1112 elif size == 0:
1117 elif size == 0:
1113 ui.note(_('skipping %s - empty destination\n') % repo[r])
1118 ui.note(_('skipping %s - empty destination\n') % repo[r])
1114 else:
1119 else:
1115 raise error.Abort(_('rebase destination for %s is not '
1120 raise error.Abort(_('rebase destination for %s is not '
1116 'unique') % repo[r])
1121 'unique') % repo[r])
1117
1122
1118 if dest is not None:
1123 if dest is not None:
1119 # single-dest case: assign dest to each rev in rebaseset
1124 # single-dest case: assign dest to each rev in rebaseset
1120 destrev = dest.rev()
1125 destrev = dest.rev()
1121 destmap = {r: destrev for r in rebaseset} # {srcrev: destrev}
1126 destmap = {r: destrev for r in rebaseset} # {srcrev: destrev}
1122
1127
1123 if not destmap:
1128 if not destmap:
1124 ui.status(_('nothing to rebase - empty destination\n'))
1129 ui.status(_('nothing to rebase - empty destination\n'))
1125 return None
1130 return None
1126
1131
1127 return destmap
1132 return destmap
1128
1133
1129 def externalparent(repo, state, destancestors):
1134 def externalparent(repo, state, destancestors):
1130 """Return the revision that should be used as the second parent
1135 """Return the revision that should be used as the second parent
1131 when the revisions in state is collapsed on top of destancestors.
1136 when the revisions in state is collapsed on top of destancestors.
1132 Abort if there is more than one parent.
1137 Abort if there is more than one parent.
1133 """
1138 """
1134 parents = set()
1139 parents = set()
1135 source = min(state)
1140 source = min(state)
1136 for rev in state:
1141 for rev in state:
1137 if rev == source:
1142 if rev == source:
1138 continue
1143 continue
1139 for p in repo[rev].parents():
1144 for p in repo[rev].parents():
1140 if (p.rev() not in state
1145 if (p.rev() not in state
1141 and p.rev() not in destancestors):
1146 and p.rev() not in destancestors):
1142 parents.add(p.rev())
1147 parents.add(p.rev())
1143 if not parents:
1148 if not parents:
1144 return nullrev
1149 return nullrev
1145 if len(parents) == 1:
1150 if len(parents) == 1:
1146 return parents.pop()
1151 return parents.pop()
1147 raise error.Abort(_('unable to collapse on top of %d, there is more '
1152 raise error.Abort(_('unable to collapse on top of %d, there is more '
1148 'than one external parent: %s') %
1153 'than one external parent: %s') %
1149 (max(destancestors),
1154 (max(destancestors),
1150 ', '.join("%d" % p for p in sorted(parents))))
1155 ', '.join("%d" % p for p in sorted(parents))))
1151
1156
1152 def commitmemorynode(repo, p1, p2, wctx, editor, extra, user, date, commitmsg):
1157 def commitmemorynode(repo, p1, p2, wctx, editor, extra, user, date, commitmsg):
1153 '''Commit the memory changes with parents p1 and p2.
1158 '''Commit the memory changes with parents p1 and p2.
1154 Return node of committed revision.'''
1159 Return node of committed revision.'''
1155 # Replicates the empty check in ``repo.commit``.
1160 # Replicates the empty check in ``repo.commit``.
1156 if wctx.isempty() and not repo.ui.configbool('ui', 'allowemptycommit'):
1161 if wctx.isempty() and not repo.ui.configbool('ui', 'allowemptycommit'):
1157 return None
1162 return None
1158
1163
1159 # By convention, ``extra['branch']`` (set by extrafn) clobbers
1164 # By convention, ``extra['branch']`` (set by extrafn) clobbers
1160 # ``branch`` (used when passing ``--keepbranches``).
1165 # ``branch`` (used when passing ``--keepbranches``).
1161 branch = repo[p1].branch()
1166 branch = repo[p1].branch()
1162 if 'branch' in extra:
1167 if 'branch' in extra:
1163 branch = extra['branch']
1168 branch = extra['branch']
1164
1169
1165 memctx = wctx.tomemctx(commitmsg, parents=(p1, p2), date=date,
1170 memctx = wctx.tomemctx(commitmsg, parents=(p1, p2), date=date,
1166 extra=extra, user=user, branch=branch, editor=editor)
1171 extra=extra, user=user, branch=branch, editor=editor)
1167 commitres = repo.commitctx(memctx)
1172 commitres = repo.commitctx(memctx)
1168 wctx.clean() # Might be reused
1173 wctx.clean() # Might be reused
1169 return commitres
1174 return commitres
1170
1175
1171 def commitnode(repo, p1, p2, editor, extra, user, date, commitmsg):
1176 def commitnode(repo, p1, p2, editor, extra, user, date, commitmsg):
1172 '''Commit the wd changes with parents p1 and p2.
1177 '''Commit the wd changes with parents p1 and p2.
1173 Return node of committed revision.'''
1178 Return node of committed revision.'''
1174 dsguard = util.nullcontextmanager()
1179 dsguard = util.nullcontextmanager()
1175 if not repo.ui.configbool('rebase', 'singletransaction'):
1180 if not repo.ui.configbool('rebase', 'singletransaction'):
1176 dsguard = dirstateguard.dirstateguard(repo, 'rebase')
1181 dsguard = dirstateguard.dirstateguard(repo, 'rebase')
1177 with dsguard:
1182 with dsguard:
1178 repo.setparents(repo[p1].node(), repo[p2].node())
1183 repo.setparents(repo[p1].node(), repo[p2].node())
1179
1184
1180 # Commit might fail if unresolved files exist
1185 # Commit might fail if unresolved files exist
1181 newnode = repo.commit(text=commitmsg, user=user, date=date,
1186 newnode = repo.commit(text=commitmsg, user=user, date=date,
1182 extra=extra, editor=editor)
1187 extra=extra, editor=editor)
1183
1188
1184 repo.dirstate.setbranch(repo[newnode].branch())
1189 repo.dirstate.setbranch(repo[newnode].branch())
1185 return newnode
1190 return newnode
1186
1191
1187 def rebasenode(repo, rev, p1, base, collapse, dest, wctx):
1192 def rebasenode(repo, rev, p1, base, collapse, dest, wctx):
1188 'Rebase a single revision rev on top of p1 using base as merge ancestor'
1193 'Rebase a single revision rev on top of p1 using base as merge ancestor'
1189 # Merge phase
1194 # Merge phase
1190 # Update to destination and merge it with local
1195 # Update to destination and merge it with local
1191 if wctx.isinmemory():
1196 if wctx.isinmemory():
1192 wctx.setbase(repo[p1])
1197 wctx.setbase(repo[p1])
1193 else:
1198 else:
1194 if repo['.'].rev() != p1:
1199 if repo['.'].rev() != p1:
1195 repo.ui.debug(" update to %d:%s\n" % (p1, repo[p1]))
1200 repo.ui.debug(" update to %d:%s\n" % (p1, repo[p1]))
1196 mergemod.update(repo, p1, False, True)
1201 mergemod.update(repo, p1, False, True)
1197 else:
1202 else:
1198 repo.ui.debug(" already in destination\n")
1203 repo.ui.debug(" already in destination\n")
1199 # This is, alas, necessary to invalidate workingctx's manifest cache,
1204 # This is, alas, necessary to invalidate workingctx's manifest cache,
1200 # as well as other data we litter on it in other places.
1205 # as well as other data we litter on it in other places.
1201 wctx = repo[None]
1206 wctx = repo[None]
1202 repo.dirstate.write(repo.currenttransaction())
1207 repo.dirstate.write(repo.currenttransaction())
1203 repo.ui.debug(" merge against %d:%s\n" % (rev, repo[rev]))
1208 repo.ui.debug(" merge against %d:%s\n" % (rev, repo[rev]))
1204 if base is not None:
1209 if base is not None:
1205 repo.ui.debug(" detach base %d:%s\n" % (base, repo[base]))
1210 repo.ui.debug(" detach base %d:%s\n" % (base, repo[base]))
1206 # When collapsing in-place, the parent is the common ancestor, we
1211 # When collapsing in-place, the parent is the common ancestor, we
1207 # have to allow merging with it.
1212 # have to allow merging with it.
1208 stats = mergemod.update(repo, rev, True, True, base, collapse,
1213 stats = mergemod.update(repo, rev, True, True, base, collapse,
1209 labels=['dest', 'source'], wc=wctx)
1214 labels=['dest', 'source'], wc=wctx)
1210 if collapse:
1215 if collapse:
1211 copies.duplicatecopies(repo, wctx, rev, dest)
1216 copies.duplicatecopies(repo, wctx, rev, dest)
1212 else:
1217 else:
1213 # If we're not using --collapse, we need to
1218 # If we're not using --collapse, we need to
1214 # duplicate copies between the revision we're
1219 # duplicate copies between the revision we're
1215 # rebasing and its first parent, but *not*
1220 # rebasing and its first parent, but *not*
1216 # duplicate any copies that have already been
1221 # duplicate any copies that have already been
1217 # performed in the destination.
1222 # performed in the destination.
1218 p1rev = repo[rev].p1().rev()
1223 p1rev = repo[rev].p1().rev()
1219 copies.duplicatecopies(repo, wctx, rev, p1rev, skiprev=dest)
1224 copies.duplicatecopies(repo, wctx, rev, p1rev, skiprev=dest)
1220 return stats
1225 return stats
1221
1226
1222 def adjustdest(repo, rev, destmap, state, skipped):
1227 def adjustdest(repo, rev, destmap, state, skipped):
1223 """adjust rebase destination given the current rebase state
1228 """adjust rebase destination given the current rebase state
1224
1229
1225 rev is what is being rebased. Return a list of two revs, which are the
1230 rev is what is being rebased. Return a list of two revs, which are the
1226 adjusted destinations for rev's p1 and p2, respectively. If a parent is
1231 adjusted destinations for rev's p1 and p2, respectively. If a parent is
1227 nullrev, return dest without adjustment for it.
1232 nullrev, return dest without adjustment for it.
1228
1233
1229 For example, when doing rebasing B+E to F, C to G, rebase will first move B
1234 For example, when doing rebasing B+E to F, C to G, rebase will first move B
1230 to B1, and E's destination will be adjusted from F to B1.
1235 to B1, and E's destination will be adjusted from F to B1.
1231
1236
1232 B1 <- written during rebasing B
1237 B1 <- written during rebasing B
1233 |
1238 |
1234 F <- original destination of B, E
1239 F <- original destination of B, E
1235 |
1240 |
1236 | E <- rev, which is being rebased
1241 | E <- rev, which is being rebased
1237 | |
1242 | |
1238 | D <- prev, one parent of rev being checked
1243 | D <- prev, one parent of rev being checked
1239 | |
1244 | |
1240 | x <- skipped, ex. no successor or successor in (::dest)
1245 | x <- skipped, ex. no successor or successor in (::dest)
1241 | |
1246 | |
1242 | C <- rebased as C', different destination
1247 | C <- rebased as C', different destination
1243 | |
1248 | |
1244 | B <- rebased as B1 C'
1249 | B <- rebased as B1 C'
1245 |/ |
1250 |/ |
1246 A G <- destination of C, different
1251 A G <- destination of C, different
1247
1252
1248 Another example about merge changeset, rebase -r C+G+H -d K, rebase will
1253 Another example about merge changeset, rebase -r C+G+H -d K, rebase will
1249 first move C to C1, G to G1, and when it's checking H, the adjusted
1254 first move C to C1, G to G1, and when it's checking H, the adjusted
1250 destinations will be [C1, G1].
1255 destinations will be [C1, G1].
1251
1256
1252 H C1 G1
1257 H C1 G1
1253 /| | /
1258 /| | /
1254 F G |/
1259 F G |/
1255 K | | -> K
1260 K | | -> K
1256 | C D |
1261 | C D |
1257 | |/ |
1262 | |/ |
1258 | B | ...
1263 | B | ...
1259 |/ |/
1264 |/ |/
1260 A A
1265 A A
1261
1266
1262 Besides, adjust dest according to existing rebase information. For example,
1267 Besides, adjust dest according to existing rebase information. For example,
1263
1268
1264 B C D B needs to be rebased on top of C, C needs to be rebased on top
1269 B C D B needs to be rebased on top of C, C needs to be rebased on top
1265 \|/ of D. We will rebase C first.
1270 \|/ of D. We will rebase C first.
1266 A
1271 A
1267
1272
1268 C' After rebasing C, when considering B's destination, use C'
1273 C' After rebasing C, when considering B's destination, use C'
1269 | instead of the original C.
1274 | instead of the original C.
1270 B D
1275 B D
1271 \ /
1276 \ /
1272 A
1277 A
1273 """
1278 """
1274 # pick already rebased revs with same dest from state as interesting source
1279 # pick already rebased revs with same dest from state as interesting source
1275 dest = destmap[rev]
1280 dest = destmap[rev]
1276 source = [s for s, d in state.items()
1281 source = [s for s, d in state.items()
1277 if d > 0 and destmap[s] == dest and s not in skipped]
1282 if d > 0 and destmap[s] == dest and s not in skipped]
1278
1283
1279 result = []
1284 result = []
1280 for prev in repo.changelog.parentrevs(rev):
1285 for prev in repo.changelog.parentrevs(rev):
1281 adjusted = dest
1286 adjusted = dest
1282 if prev != nullrev:
1287 if prev != nullrev:
1283 candidate = repo.revs('max(%ld and (::%d))', source, prev).first()
1288 candidate = repo.revs('max(%ld and (::%d))', source, prev).first()
1284 if candidate is not None:
1289 if candidate is not None:
1285 adjusted = state[candidate]
1290 adjusted = state[candidate]
1286 if adjusted == dest and dest in state:
1291 if adjusted == dest and dest in state:
1287 adjusted = state[dest]
1292 adjusted = state[dest]
1288 if adjusted == revtodo:
1293 if adjusted == revtodo:
1289 # sortsource should produce an order that makes this impossible
1294 # sortsource should produce an order that makes this impossible
1290 raise error.ProgrammingError(
1295 raise error.ProgrammingError(
1291 'rev %d should be rebased already at this time' % dest)
1296 'rev %d should be rebased already at this time' % dest)
1292 result.append(adjusted)
1297 result.append(adjusted)
1293 return result
1298 return result
1294
1299
1295 def _checkobsrebase(repo, ui, rebaseobsrevs, rebaseobsskipped):
1300 def _checkobsrebase(repo, ui, rebaseobsrevs, rebaseobsskipped):
1296 """
1301 """
1297 Abort if rebase will create divergence or rebase is noop because of markers
1302 Abort if rebase will create divergence or rebase is noop because of markers
1298
1303
1299 `rebaseobsrevs`: set of obsolete revision in source
1304 `rebaseobsrevs`: set of obsolete revision in source
1300 `rebaseobsskipped`: set of revisions from source skipped because they have
1305 `rebaseobsskipped`: set of revisions from source skipped because they have
1301 successors in destination or no non-obsolete successor.
1306 successors in destination or no non-obsolete successor.
1302 """
1307 """
1303 # Obsolete node with successors not in dest leads to divergence
1308 # Obsolete node with successors not in dest leads to divergence
1304 divergenceok = ui.configbool('experimental',
1309 divergenceok = ui.configbool('experimental',
1305 'evolution.allowdivergence')
1310 'evolution.allowdivergence')
1306 divergencebasecandidates = rebaseobsrevs - rebaseobsskipped
1311 divergencebasecandidates = rebaseobsrevs - rebaseobsskipped
1307
1312
1308 if divergencebasecandidates and not divergenceok:
1313 if divergencebasecandidates and not divergenceok:
1309 divhashes = (bytes(repo[r])
1314 divhashes = (bytes(repo[r])
1310 for r in divergencebasecandidates)
1315 for r in divergencebasecandidates)
1311 msg = _("this rebase will cause "
1316 msg = _("this rebase will cause "
1312 "divergences from: %s")
1317 "divergences from: %s")
1313 h = _("to force the rebase please set "
1318 h = _("to force the rebase please set "
1314 "experimental.evolution.allowdivergence=True")
1319 "experimental.evolution.allowdivergence=True")
1315 raise error.Abort(msg % (",".join(divhashes),), hint=h)
1320 raise error.Abort(msg % (",".join(divhashes),), hint=h)
1316
1321
1317 def successorrevs(unfi, rev):
1322 def successorrevs(unfi, rev):
1318 """yield revision numbers for successors of rev"""
1323 """yield revision numbers for successors of rev"""
1319 assert unfi.filtername is None
1324 assert unfi.filtername is None
1320 nodemap = unfi.changelog.nodemap
1325 nodemap = unfi.changelog.nodemap
1321 for s in obsutil.allsuccessors(unfi.obsstore, [unfi[rev].node()]):
1326 for s in obsutil.allsuccessors(unfi.obsstore, [unfi[rev].node()]):
1322 if s in nodemap:
1327 if s in nodemap:
1323 yield nodemap[s]
1328 yield nodemap[s]
1324
1329
1325 def defineparents(repo, rev, destmap, state, skipped, obsskipped):
1330 def defineparents(repo, rev, destmap, state, skipped, obsskipped):
1326 """Return new parents and optionally a merge base for rev being rebased
1331 """Return new parents and optionally a merge base for rev being rebased
1327
1332
1328 The destination specified by "dest" cannot always be used directly because
1333 The destination specified by "dest" cannot always be used directly because
1329 previously rebase result could affect destination. For example,
1334 previously rebase result could affect destination. For example,
1330
1335
1331 D E rebase -r C+D+E -d B
1336 D E rebase -r C+D+E -d B
1332 |/ C will be rebased to C'
1337 |/ C will be rebased to C'
1333 B C D's new destination will be C' instead of B
1338 B C D's new destination will be C' instead of B
1334 |/ E's new destination will be C' instead of B
1339 |/ E's new destination will be C' instead of B
1335 A
1340 A
1336
1341
1337 The new parents of a merge is slightly more complicated. See the comment
1342 The new parents of a merge is slightly more complicated. See the comment
1338 block below.
1343 block below.
1339 """
1344 """
1340 # use unfiltered changelog since successorrevs may return filtered nodes
1345 # use unfiltered changelog since successorrevs may return filtered nodes
1341 assert repo.filtername is None
1346 assert repo.filtername is None
1342 cl = repo.changelog
1347 cl = repo.changelog
1343 isancestor = cl.isancestorrev
1348 isancestor = cl.isancestorrev
1344
1349
1345 dest = destmap[rev]
1350 dest = destmap[rev]
1346 oldps = repo.changelog.parentrevs(rev) # old parents
1351 oldps = repo.changelog.parentrevs(rev) # old parents
1347 newps = [nullrev, nullrev] # new parents
1352 newps = [nullrev, nullrev] # new parents
1348 dests = adjustdest(repo, rev, destmap, state, skipped)
1353 dests = adjustdest(repo, rev, destmap, state, skipped)
1349 bases = list(oldps) # merge base candidates, initially just old parents
1354 bases = list(oldps) # merge base candidates, initially just old parents
1350
1355
1351 if all(r == nullrev for r in oldps[1:]):
1356 if all(r == nullrev for r in oldps[1:]):
1352 # For non-merge changeset, just move p to adjusted dest as requested.
1357 # For non-merge changeset, just move p to adjusted dest as requested.
1353 newps[0] = dests[0]
1358 newps[0] = dests[0]
1354 else:
1359 else:
1355 # For merge changeset, if we move p to dests[i] unconditionally, both
1360 # For merge changeset, if we move p to dests[i] unconditionally, both
1356 # parents may change and the end result looks like "the merge loses a
1361 # parents may change and the end result looks like "the merge loses a
1357 # parent", which is a surprise. This is a limit because "--dest" only
1362 # parent", which is a surprise. This is a limit because "--dest" only
1358 # accepts one dest per src.
1363 # accepts one dest per src.
1359 #
1364 #
1360 # Therefore, only move p with reasonable conditions (in this order):
1365 # Therefore, only move p with reasonable conditions (in this order):
1361 # 1. use dest, if dest is a descendent of (p or one of p's successors)
1366 # 1. use dest, if dest is a descendent of (p or one of p's successors)
1362 # 2. use p's rebased result, if p is rebased (state[p] > 0)
1367 # 2. use p's rebased result, if p is rebased (state[p] > 0)
1363 #
1368 #
1364 # Comparing with adjustdest, the logic here does some additional work:
1369 # Comparing with adjustdest, the logic here does some additional work:
1365 # 1. decide which parents will not be moved towards dest
1370 # 1. decide which parents will not be moved towards dest
1366 # 2. if the above decision is "no", should a parent still be moved
1371 # 2. if the above decision is "no", should a parent still be moved
1367 # because it was rebased?
1372 # because it was rebased?
1368 #
1373 #
1369 # For example:
1374 # For example:
1370 #
1375 #
1371 # C # "rebase -r C -d D" is an error since none of the parents
1376 # C # "rebase -r C -d D" is an error since none of the parents
1372 # /| # can be moved. "rebase -r B+C -d D" will move C's parent
1377 # /| # can be moved. "rebase -r B+C -d D" will move C's parent
1373 # A B D # B (using rule "2."), since B will be rebased.
1378 # A B D # B (using rule "2."), since B will be rebased.
1374 #
1379 #
1375 # The loop tries to be not rely on the fact that a Mercurial node has
1380 # The loop tries to be not rely on the fact that a Mercurial node has
1376 # at most 2 parents.
1381 # at most 2 parents.
1377 for i, p in enumerate(oldps):
1382 for i, p in enumerate(oldps):
1378 np = p # new parent
1383 np = p # new parent
1379 if any(isancestor(x, dests[i]) for x in successorrevs(repo, p)):
1384 if any(isancestor(x, dests[i]) for x in successorrevs(repo, p)):
1380 np = dests[i]
1385 np = dests[i]
1381 elif p in state and state[p] > 0:
1386 elif p in state and state[p] > 0:
1382 np = state[p]
1387 np = state[p]
1383
1388
1384 # "bases" only record "special" merge bases that cannot be
1389 # "bases" only record "special" merge bases that cannot be
1385 # calculated from changelog DAG (i.e. isancestor(p, np) is False).
1390 # calculated from changelog DAG (i.e. isancestor(p, np) is False).
1386 # For example:
1391 # For example:
1387 #
1392 #
1388 # B' # rebase -s B -d D, when B was rebased to B'. dest for C
1393 # B' # rebase -s B -d D, when B was rebased to B'. dest for C
1389 # | C # is B', but merge base for C is B, instead of
1394 # | C # is B', but merge base for C is B, instead of
1390 # D | # changelog.ancestor(C, B') == A. If changelog DAG and
1395 # D | # changelog.ancestor(C, B') == A. If changelog DAG and
1391 # | B # "state" edges are merged (so there will be an edge from
1396 # | B # "state" edges are merged (so there will be an edge from
1392 # |/ # B to B'), the merge base is still ancestor(C, B') in
1397 # |/ # B to B'), the merge base is still ancestor(C, B') in
1393 # A # the merged graph.
1398 # A # the merged graph.
1394 #
1399 #
1395 # Also see https://bz.mercurial-scm.org/show_bug.cgi?id=1950#c8
1400 # Also see https://bz.mercurial-scm.org/show_bug.cgi?id=1950#c8
1396 # which uses "virtual null merge" to explain this situation.
1401 # which uses "virtual null merge" to explain this situation.
1397 if isancestor(p, np):
1402 if isancestor(p, np):
1398 bases[i] = nullrev
1403 bases[i] = nullrev
1399
1404
1400 # If one parent becomes an ancestor of the other, drop the ancestor
1405 # If one parent becomes an ancestor of the other, drop the ancestor
1401 for j, x in enumerate(newps[:i]):
1406 for j, x in enumerate(newps[:i]):
1402 if x == nullrev:
1407 if x == nullrev:
1403 continue
1408 continue
1404 if isancestor(np, x): # CASE-1
1409 if isancestor(np, x): # CASE-1
1405 np = nullrev
1410 np = nullrev
1406 elif isancestor(x, np): # CASE-2
1411 elif isancestor(x, np): # CASE-2
1407 newps[j] = np
1412 newps[j] = np
1408 np = nullrev
1413 np = nullrev
1409 # New parents forming an ancestor relationship does not
1414 # New parents forming an ancestor relationship does not
1410 # mean the old parents have a similar relationship. Do not
1415 # mean the old parents have a similar relationship. Do not
1411 # set bases[x] to nullrev.
1416 # set bases[x] to nullrev.
1412 bases[j], bases[i] = bases[i], bases[j]
1417 bases[j], bases[i] = bases[i], bases[j]
1413
1418
1414 newps[i] = np
1419 newps[i] = np
1415
1420
1416 # "rebasenode" updates to new p1, and the old p1 will be used as merge
1421 # "rebasenode" updates to new p1, and the old p1 will be used as merge
1417 # base. If only p2 changes, merging using unchanged p1 as merge base is
1422 # base. If only p2 changes, merging using unchanged p1 as merge base is
1418 # suboptimal. Therefore swap parents to make the merge sane.
1423 # suboptimal. Therefore swap parents to make the merge sane.
1419 if newps[1] != nullrev and oldps[0] == newps[0]:
1424 if newps[1] != nullrev and oldps[0] == newps[0]:
1420 assert len(newps) == 2 and len(oldps) == 2
1425 assert len(newps) == 2 and len(oldps) == 2
1421 newps.reverse()
1426 newps.reverse()
1422 bases.reverse()
1427 bases.reverse()
1423
1428
1424 # No parent change might be an error because we fail to make rev a
1429 # No parent change might be an error because we fail to make rev a
1425 # descendent of requested dest. This can happen, for example:
1430 # descendent of requested dest. This can happen, for example:
1426 #
1431 #
1427 # C # rebase -r C -d D
1432 # C # rebase -r C -d D
1428 # /| # None of A and B will be changed to D and rebase fails.
1433 # /| # None of A and B will be changed to D and rebase fails.
1429 # A B D
1434 # A B D
1430 if set(newps) == set(oldps) and dest not in newps:
1435 if set(newps) == set(oldps) and dest not in newps:
1431 raise error.Abort(_('cannot rebase %d:%s without '
1436 raise error.Abort(_('cannot rebase %d:%s without '
1432 'moving at least one of its parents')
1437 'moving at least one of its parents')
1433 % (rev, repo[rev]))
1438 % (rev, repo[rev]))
1434
1439
1435 # Source should not be ancestor of dest. The check here guarantees it's
1440 # Source should not be ancestor of dest. The check here guarantees it's
1436 # impossible. With multi-dest, the initial check does not cover complex
1441 # impossible. With multi-dest, the initial check does not cover complex
1437 # cases since we don't have abstractions to dry-run rebase cheaply.
1442 # cases since we don't have abstractions to dry-run rebase cheaply.
1438 if any(p != nullrev and isancestor(rev, p) for p in newps):
1443 if any(p != nullrev and isancestor(rev, p) for p in newps):
1439 raise error.Abort(_('source is ancestor of destination'))
1444 raise error.Abort(_('source is ancestor of destination'))
1440
1445
1441 # "rebasenode" updates to new p1, use the corresponding merge base.
1446 # "rebasenode" updates to new p1, use the corresponding merge base.
1442 if bases[0] != nullrev:
1447 if bases[0] != nullrev:
1443 base = bases[0]
1448 base = bases[0]
1444 else:
1449 else:
1445 base = None
1450 base = None
1446
1451
1447 # Check if the merge will contain unwanted changes. That may happen if
1452 # Check if the merge will contain unwanted changes. That may happen if
1448 # there are multiple special (non-changelog ancestor) merge bases, which
1453 # there are multiple special (non-changelog ancestor) merge bases, which
1449 # cannot be handled well by the 3-way merge algorithm. For example:
1454 # cannot be handled well by the 3-way merge algorithm. For example:
1450 #
1455 #
1451 # F
1456 # F
1452 # /|
1457 # /|
1453 # D E # "rebase -r D+E+F -d Z", when rebasing F, if "D" was chosen
1458 # D E # "rebase -r D+E+F -d Z", when rebasing F, if "D" was chosen
1454 # | | # as merge base, the difference between D and F will include
1459 # | | # as merge base, the difference between D and F will include
1455 # B C # C, so the rebased F will contain C surprisingly. If "E" was
1460 # B C # C, so the rebased F will contain C surprisingly. If "E" was
1456 # |/ # chosen, the rebased F will contain B.
1461 # |/ # chosen, the rebased F will contain B.
1457 # A Z
1462 # A Z
1458 #
1463 #
1459 # But our merge base candidates (D and E in above case) could still be
1464 # But our merge base candidates (D and E in above case) could still be
1460 # better than the default (ancestor(F, Z) == null). Therefore still
1465 # better than the default (ancestor(F, Z) == null). Therefore still
1461 # pick one (so choose p1 above).
1466 # pick one (so choose p1 above).
1462 if sum(1 for b in bases if b != nullrev) > 1:
1467 if sum(1 for b in bases if b != nullrev) > 1:
1463 unwanted = [None, None] # unwanted[i]: unwanted revs if choose bases[i]
1468 unwanted = [None, None] # unwanted[i]: unwanted revs if choose bases[i]
1464 for i, base in enumerate(bases):
1469 for i, base in enumerate(bases):
1465 if base == nullrev:
1470 if base == nullrev:
1466 continue
1471 continue
1467 # Revisions in the side (not chosen as merge base) branch that
1472 # Revisions in the side (not chosen as merge base) branch that
1468 # might contain "surprising" contents
1473 # might contain "surprising" contents
1469 siderevs = list(repo.revs('((%ld-%d) %% (%d+%d))',
1474 siderevs = list(repo.revs('((%ld-%d) %% (%d+%d))',
1470 bases, base, base, dest))
1475 bases, base, base, dest))
1471
1476
1472 # If those revisions are covered by rebaseset, the result is good.
1477 # If those revisions are covered by rebaseset, the result is good.
1473 # A merge in rebaseset would be considered to cover its ancestors.
1478 # A merge in rebaseset would be considered to cover its ancestors.
1474 if siderevs:
1479 if siderevs:
1475 rebaseset = [r for r, d in state.items()
1480 rebaseset = [r for r, d in state.items()
1476 if d > 0 and r not in obsskipped]
1481 if d > 0 and r not in obsskipped]
1477 merges = [r for r in rebaseset
1482 merges = [r for r in rebaseset
1478 if cl.parentrevs(r)[1] != nullrev]
1483 if cl.parentrevs(r)[1] != nullrev]
1479 unwanted[i] = list(repo.revs('%ld - (::%ld) - %ld',
1484 unwanted[i] = list(repo.revs('%ld - (::%ld) - %ld',
1480 siderevs, merges, rebaseset))
1485 siderevs, merges, rebaseset))
1481
1486
1482 # Choose a merge base that has a minimal number of unwanted revs.
1487 # Choose a merge base that has a minimal number of unwanted revs.
1483 l, i = min((len(revs), i)
1488 l, i = min((len(revs), i)
1484 for i, revs in enumerate(unwanted) if revs is not None)
1489 for i, revs in enumerate(unwanted) if revs is not None)
1485 base = bases[i]
1490 base = bases[i]
1486
1491
1487 # newps[0] should match merge base if possible. Currently, if newps[i]
1492 # newps[0] should match merge base if possible. Currently, if newps[i]
1488 # is nullrev, the only case is newps[i] and newps[j] (j < i), one is
1493 # is nullrev, the only case is newps[i] and newps[j] (j < i), one is
1489 # the other's ancestor. In that case, it's fine to not swap newps here.
1494 # the other's ancestor. In that case, it's fine to not swap newps here.
1490 # (see CASE-1 and CASE-2 above)
1495 # (see CASE-1 and CASE-2 above)
1491 if i != 0 and newps[i] != nullrev:
1496 if i != 0 and newps[i] != nullrev:
1492 newps[0], newps[i] = newps[i], newps[0]
1497 newps[0], newps[i] = newps[i], newps[0]
1493
1498
1494 # The merge will include unwanted revisions. Abort now. Revisit this if
1499 # The merge will include unwanted revisions. Abort now. Revisit this if
1495 # we have a more advanced merge algorithm that handles multiple bases.
1500 # we have a more advanced merge algorithm that handles multiple bases.
1496 if l > 0:
1501 if l > 0:
1497 unwanteddesc = _(' or ').join(
1502 unwanteddesc = _(' or ').join(
1498 (', '.join('%d:%s' % (r, repo[r]) for r in revs)
1503 (', '.join('%d:%s' % (r, repo[r]) for r in revs)
1499 for revs in unwanted if revs is not None))
1504 for revs in unwanted if revs is not None))
1500 raise error.Abort(
1505 raise error.Abort(
1501 _('rebasing %d:%s will include unwanted changes from %s')
1506 _('rebasing %d:%s will include unwanted changes from %s')
1502 % (rev, repo[rev], unwanteddesc))
1507 % (rev, repo[rev], unwanteddesc))
1503
1508
1504 repo.ui.debug(" future parents are %d and %d\n" % tuple(newps))
1509 repo.ui.debug(" future parents are %d and %d\n" % tuple(newps))
1505
1510
1506 return newps[0], newps[1], base
1511 return newps[0], newps[1], base
1507
1512
1508 def isagitpatch(repo, patchname):
1513 def isagitpatch(repo, patchname):
1509 'Return true if the given patch is in git format'
1514 'Return true if the given patch is in git format'
1510 mqpatch = os.path.join(repo.mq.path, patchname)
1515 mqpatch = os.path.join(repo.mq.path, patchname)
1511 for line in patch.linereader(open(mqpatch, 'rb')):
1516 for line in patch.linereader(open(mqpatch, 'rb')):
1512 if line.startswith('diff --git'):
1517 if line.startswith('diff --git'):
1513 return True
1518 return True
1514 return False
1519 return False
1515
1520
1516 def updatemq(repo, state, skipped, **opts):
1521 def updatemq(repo, state, skipped, **opts):
1517 'Update rebased mq patches - finalize and then import them'
1522 'Update rebased mq patches - finalize and then import them'
1518 mqrebase = {}
1523 mqrebase = {}
1519 mq = repo.mq
1524 mq = repo.mq
1520 original_series = mq.fullseries[:]
1525 original_series = mq.fullseries[:]
1521 skippedpatches = set()
1526 skippedpatches = set()
1522
1527
1523 for p in mq.applied:
1528 for p in mq.applied:
1524 rev = repo[p.node].rev()
1529 rev = repo[p.node].rev()
1525 if rev in state:
1530 if rev in state:
1526 repo.ui.debug('revision %d is an mq patch (%s), finalize it.\n' %
1531 repo.ui.debug('revision %d is an mq patch (%s), finalize it.\n' %
1527 (rev, p.name))
1532 (rev, p.name))
1528 mqrebase[rev] = (p.name, isagitpatch(repo, p.name))
1533 mqrebase[rev] = (p.name, isagitpatch(repo, p.name))
1529 else:
1534 else:
1530 # Applied but not rebased, not sure this should happen
1535 # Applied but not rebased, not sure this should happen
1531 skippedpatches.add(p.name)
1536 skippedpatches.add(p.name)
1532
1537
1533 if mqrebase:
1538 if mqrebase:
1534 mq.finish(repo, mqrebase.keys())
1539 mq.finish(repo, mqrebase.keys())
1535
1540
1536 # We must start import from the newest revision
1541 # We must start import from the newest revision
1537 for rev in sorted(mqrebase, reverse=True):
1542 for rev in sorted(mqrebase, reverse=True):
1538 if rev not in skipped:
1543 if rev not in skipped:
1539 name, isgit = mqrebase[rev]
1544 name, isgit = mqrebase[rev]
1540 repo.ui.note(_('updating mq patch %s to %d:%s\n') %
1545 repo.ui.note(_('updating mq patch %s to %d:%s\n') %
1541 (name, state[rev], repo[state[rev]]))
1546 (name, state[rev], repo[state[rev]]))
1542 mq.qimport(repo, (), patchname=name, git=isgit,
1547 mq.qimport(repo, (), patchname=name, git=isgit,
1543 rev=["%d" % state[rev]])
1548 rev=["%d" % state[rev]])
1544 else:
1549 else:
1545 # Rebased and skipped
1550 # Rebased and skipped
1546 skippedpatches.add(mqrebase[rev][0])
1551 skippedpatches.add(mqrebase[rev][0])
1547
1552
1548 # Patches were either applied and rebased and imported in
1553 # Patches were either applied and rebased and imported in
1549 # order, applied and removed or unapplied. Discard the removed
1554 # order, applied and removed or unapplied. Discard the removed
1550 # ones while preserving the original series order and guards.
1555 # ones while preserving the original series order and guards.
1551 newseries = [s for s in original_series
1556 newseries = [s for s in original_series
1552 if mq.guard_re.split(s, 1)[0] not in skippedpatches]
1557 if mq.guard_re.split(s, 1)[0] not in skippedpatches]
1553 mq.fullseries[:] = newseries
1558 mq.fullseries[:] = newseries
1554 mq.seriesdirty = True
1559 mq.seriesdirty = True
1555 mq.savedirty()
1560 mq.savedirty()
1556
1561
1557 def storecollapsemsg(repo, collapsemsg):
1562 def storecollapsemsg(repo, collapsemsg):
1558 'Store the collapse message to allow recovery'
1563 'Store the collapse message to allow recovery'
1559 collapsemsg = collapsemsg or ''
1564 collapsemsg = collapsemsg or ''
1560 f = repo.vfs("last-message.txt", "w")
1565 f = repo.vfs("last-message.txt", "w")
1561 f.write("%s\n" % collapsemsg)
1566 f.write("%s\n" % collapsemsg)
1562 f.close()
1567 f.close()
1563
1568
1564 def clearcollapsemsg(repo):
1569 def clearcollapsemsg(repo):
1565 'Remove collapse message file'
1570 'Remove collapse message file'
1566 repo.vfs.unlinkpath("last-message.txt", ignoremissing=True)
1571 repo.vfs.unlinkpath("last-message.txt", ignoremissing=True)
1567
1572
1568 def restorecollapsemsg(repo, isabort):
1573 def restorecollapsemsg(repo, isabort):
1569 'Restore previously stored collapse message'
1574 'Restore previously stored collapse message'
1570 try:
1575 try:
1571 f = repo.vfs("last-message.txt")
1576 f = repo.vfs("last-message.txt")
1572 collapsemsg = f.readline().strip()
1577 collapsemsg = f.readline().strip()
1573 f.close()
1578 f.close()
1574 except IOError as err:
1579 except IOError as err:
1575 if err.errno != errno.ENOENT:
1580 if err.errno != errno.ENOENT:
1576 raise
1581 raise
1577 if isabort:
1582 if isabort:
1578 # Oh well, just abort like normal
1583 # Oh well, just abort like normal
1579 collapsemsg = ''
1584 collapsemsg = ''
1580 else:
1585 else:
1581 raise error.Abort(_('missing .hg/last-message.txt for rebase'))
1586 raise error.Abort(_('missing .hg/last-message.txt for rebase'))
1582 return collapsemsg
1587 return collapsemsg
1583
1588
1584 def clearstatus(repo):
1589 def clearstatus(repo):
1585 'Remove the status files'
1590 'Remove the status files'
1586 # Make sure the active transaction won't write the state file
1591 # Make sure the active transaction won't write the state file
1587 tr = repo.currenttransaction()
1592 tr = repo.currenttransaction()
1588 if tr:
1593 if tr:
1589 tr.removefilegenerator('rebasestate')
1594 tr.removefilegenerator('rebasestate')
1590 repo.vfs.unlinkpath("rebasestate", ignoremissing=True)
1595 repo.vfs.unlinkpath("rebasestate", ignoremissing=True)
1591
1596
1592 def needupdate(repo, state):
1597 def needupdate(repo, state):
1593 '''check whether we should `update --clean` away from a merge, or if
1598 '''check whether we should `update --clean` away from a merge, or if
1594 somehow the working dir got forcibly updated, e.g. by older hg'''
1599 somehow the working dir got forcibly updated, e.g. by older hg'''
1595 parents = [p.rev() for p in repo[None].parents()]
1600 parents = [p.rev() for p in repo[None].parents()]
1596
1601
1597 # Are we in a merge state at all?
1602 # Are we in a merge state at all?
1598 if len(parents) < 2:
1603 if len(parents) < 2:
1599 return False
1604 return False
1600
1605
1601 # We should be standing on the first as-of-yet unrebased commit.
1606 # We should be standing on the first as-of-yet unrebased commit.
1602 firstunrebased = min([old for old, new in state.iteritems()
1607 firstunrebased = min([old for old, new in state.iteritems()
1603 if new == nullrev])
1608 if new == nullrev])
1604 if firstunrebased in parents:
1609 if firstunrebased in parents:
1605 return True
1610 return True
1606
1611
1607 return False
1612 return False
1608
1613
1609 def abort(repo, originalwd, destmap, state, activebookmark=None, backup=True,
1614 def abort(repo, originalwd, destmap, state, activebookmark=None, backup=True,
1610 suppwarns=False):
1615 suppwarns=False):
1611 '''Restore the repository to its original state. Additional args:
1616 '''Restore the repository to its original state. Additional args:
1612
1617
1613 activebookmark: the name of the bookmark that should be active after the
1618 activebookmark: the name of the bookmark that should be active after the
1614 restore'''
1619 restore'''
1615
1620
1616 try:
1621 try:
1617 # If the first commits in the rebased set get skipped during the rebase,
1622 # If the first commits in the rebased set get skipped during the rebase,
1618 # their values within the state mapping will be the dest rev id. The
1623 # their values within the state mapping will be the dest rev id. The
1619 # rebased list must must not contain the dest rev (issue4896)
1624 # rebased list must must not contain the dest rev (issue4896)
1620 rebased = [s for r, s in state.items()
1625 rebased = [s for r, s in state.items()
1621 if s >= 0 and s != r and s != destmap[r]]
1626 if s >= 0 and s != r and s != destmap[r]]
1622 immutable = [d for d in rebased if not repo[d].mutable()]
1627 immutable = [d for d in rebased if not repo[d].mutable()]
1623 cleanup = True
1628 cleanup = True
1624 if immutable:
1629 if immutable:
1625 repo.ui.warn(_("warning: can't clean up public changesets %s\n")
1630 repo.ui.warn(_("warning: can't clean up public changesets %s\n")
1626 % ', '.join(bytes(repo[r]) for r in immutable),
1631 % ', '.join(bytes(repo[r]) for r in immutable),
1627 hint=_("see 'hg help phases' for details"))
1632 hint=_("see 'hg help phases' for details"))
1628 cleanup = False
1633 cleanup = False
1629
1634
1630 descendants = set()
1635 descendants = set()
1631 if rebased:
1636 if rebased:
1632 descendants = set(repo.changelog.descendants(rebased))
1637 descendants = set(repo.changelog.descendants(rebased))
1633 if descendants - set(rebased):
1638 if descendants - set(rebased):
1634 repo.ui.warn(_("warning: new changesets detected on destination "
1639 repo.ui.warn(_("warning: new changesets detected on destination "
1635 "branch, can't strip\n"))
1640 "branch, can't strip\n"))
1636 cleanup = False
1641 cleanup = False
1637
1642
1638 if cleanup:
1643 if cleanup:
1639 shouldupdate = False
1644 shouldupdate = False
1640 if rebased:
1645 if rebased:
1641 strippoints = [
1646 strippoints = [
1642 c.node() for c in repo.set('roots(%ld)', rebased)]
1647 c.node() for c in repo.set('roots(%ld)', rebased)]
1643
1648
1644 updateifonnodes = set(rebased)
1649 updateifonnodes = set(rebased)
1645 updateifonnodes.update(destmap.values())
1650 updateifonnodes.update(destmap.values())
1646 updateifonnodes.add(originalwd)
1651 updateifonnodes.add(originalwd)
1647 shouldupdate = repo['.'].rev() in updateifonnodes
1652 shouldupdate = repo['.'].rev() in updateifonnodes
1648
1653
1649 # Update away from the rebase if necessary
1654 # Update away from the rebase if necessary
1650 if shouldupdate or needupdate(repo, state):
1655 if shouldupdate or needupdate(repo, state):
1651 mergemod.update(repo, originalwd, False, True)
1656 mergemod.update(repo, originalwd, False, True)
1652
1657
1653 # Strip from the first rebased revision
1658 # Strip from the first rebased revision
1654 if rebased:
1659 if rebased:
1655 repair.strip(repo.ui, repo, strippoints, backup=backup)
1660 repair.strip(repo.ui, repo, strippoints, backup=backup)
1656
1661
1657 if activebookmark and activebookmark in repo._bookmarks:
1662 if activebookmark and activebookmark in repo._bookmarks:
1658 bookmarks.activate(repo, activebookmark)
1663 bookmarks.activate(repo, activebookmark)
1659
1664
1660 finally:
1665 finally:
1661 clearstatus(repo)
1666 clearstatus(repo)
1662 clearcollapsemsg(repo)
1667 clearcollapsemsg(repo)
1663 if not suppwarns:
1668 if not suppwarns:
1664 repo.ui.warn(_('rebase aborted\n'))
1669 repo.ui.warn(_('rebase aborted\n'))
1665 return 0
1670 return 0
1666
1671
1667 def sortsource(destmap):
1672 def sortsource(destmap):
1668 """yield source revisions in an order that we only rebase things once
1673 """yield source revisions in an order that we only rebase things once
1669
1674
1670 If source and destination overlaps, we should filter out revisions
1675 If source and destination overlaps, we should filter out revisions
1671 depending on other revisions which hasn't been rebased yet.
1676 depending on other revisions which hasn't been rebased yet.
1672
1677
1673 Yield a sorted list of revisions each time.
1678 Yield a sorted list of revisions each time.
1674
1679
1675 For example, when rebasing A to B, B to C. This function yields [B], then
1680 For example, when rebasing A to B, B to C. This function yields [B], then
1676 [A], indicating B needs to be rebased first.
1681 [A], indicating B needs to be rebased first.
1677
1682
1678 Raise if there is a cycle so the rebase is impossible.
1683 Raise if there is a cycle so the rebase is impossible.
1679 """
1684 """
1680 srcset = set(destmap)
1685 srcset = set(destmap)
1681 while srcset:
1686 while srcset:
1682 srclist = sorted(srcset)
1687 srclist = sorted(srcset)
1683 result = []
1688 result = []
1684 for r in srclist:
1689 for r in srclist:
1685 if destmap[r] not in srcset:
1690 if destmap[r] not in srcset:
1686 result.append(r)
1691 result.append(r)
1687 if not result:
1692 if not result:
1688 raise error.Abort(_('source and destination form a cycle'))
1693 raise error.Abort(_('source and destination form a cycle'))
1689 srcset -= set(result)
1694 srcset -= set(result)
1690 yield result
1695 yield result
1691
1696
1692 def buildstate(repo, destmap, collapse):
1697 def buildstate(repo, destmap, collapse):
1693 '''Define which revisions are going to be rebased and where
1698 '''Define which revisions are going to be rebased and where
1694
1699
1695 repo: repo
1700 repo: repo
1696 destmap: {srcrev: destrev}
1701 destmap: {srcrev: destrev}
1697 '''
1702 '''
1698 rebaseset = destmap.keys()
1703 rebaseset = destmap.keys()
1699 originalwd = repo['.'].rev()
1704 originalwd = repo['.'].rev()
1700
1705
1701 # This check isn't strictly necessary, since mq detects commits over an
1706 # This check isn't strictly necessary, since mq detects commits over an
1702 # applied patch. But it prevents messing up the working directory when
1707 # applied patch. But it prevents messing up the working directory when
1703 # a partially completed rebase is blocked by mq.
1708 # a partially completed rebase is blocked by mq.
1704 if 'qtip' in repo.tags():
1709 if 'qtip' in repo.tags():
1705 mqapplied = set(repo[s.node].rev() for s in repo.mq.applied)
1710 mqapplied = set(repo[s.node].rev() for s in repo.mq.applied)
1706 if set(destmap.values()) & mqapplied:
1711 if set(destmap.values()) & mqapplied:
1707 raise error.Abort(_('cannot rebase onto an applied mq patch'))
1712 raise error.Abort(_('cannot rebase onto an applied mq patch'))
1708
1713
1709 # Get "cycle" error early by exhausting the generator.
1714 # Get "cycle" error early by exhausting the generator.
1710 sortedsrc = list(sortsource(destmap)) # a list of sorted revs
1715 sortedsrc = list(sortsource(destmap)) # a list of sorted revs
1711 if not sortedsrc:
1716 if not sortedsrc:
1712 raise error.Abort(_('no matching revisions'))
1717 raise error.Abort(_('no matching revisions'))
1713
1718
1714 # Only check the first batch of revisions to rebase not depending on other
1719 # Only check the first batch of revisions to rebase not depending on other
1715 # rebaseset. This means "source is ancestor of destination" for the second
1720 # rebaseset. This means "source is ancestor of destination" for the second
1716 # (and following) batches of revisions are not checked here. We rely on
1721 # (and following) batches of revisions are not checked here. We rely on
1717 # "defineparents" to do that check.
1722 # "defineparents" to do that check.
1718 roots = list(repo.set('roots(%ld)', sortedsrc[0]))
1723 roots = list(repo.set('roots(%ld)', sortedsrc[0]))
1719 if not roots:
1724 if not roots:
1720 raise error.Abort(_('no matching revisions'))
1725 raise error.Abort(_('no matching revisions'))
1721 def revof(r):
1726 def revof(r):
1722 return r.rev()
1727 return r.rev()
1723 roots = sorted(roots, key=revof)
1728 roots = sorted(roots, key=revof)
1724 state = dict.fromkeys(rebaseset, revtodo)
1729 state = dict.fromkeys(rebaseset, revtodo)
1725 emptyrebase = (len(sortedsrc) == 1)
1730 emptyrebase = (len(sortedsrc) == 1)
1726 for root in roots:
1731 for root in roots:
1727 dest = repo[destmap[root.rev()]]
1732 dest = repo[destmap[root.rev()]]
1728 commonbase = root.ancestor(dest)
1733 commonbase = root.ancestor(dest)
1729 if commonbase == root:
1734 if commonbase == root:
1730 raise error.Abort(_('source is ancestor of destination'))
1735 raise error.Abort(_('source is ancestor of destination'))
1731 if commonbase == dest:
1736 if commonbase == dest:
1732 wctx = repo[None]
1737 wctx = repo[None]
1733 if dest == wctx.p1():
1738 if dest == wctx.p1():
1734 # when rebasing to '.', it will use the current wd branch name
1739 # when rebasing to '.', it will use the current wd branch name
1735 samebranch = root.branch() == wctx.branch()
1740 samebranch = root.branch() == wctx.branch()
1736 else:
1741 else:
1737 samebranch = root.branch() == dest.branch()
1742 samebranch = root.branch() == dest.branch()
1738 if not collapse and samebranch and dest in root.parents():
1743 if not collapse and samebranch and dest in root.parents():
1739 # mark the revision as done by setting its new revision
1744 # mark the revision as done by setting its new revision
1740 # equal to its old (current) revisions
1745 # equal to its old (current) revisions
1741 state[root.rev()] = root.rev()
1746 state[root.rev()] = root.rev()
1742 repo.ui.debug('source is a child of destination\n')
1747 repo.ui.debug('source is a child of destination\n')
1743 continue
1748 continue
1744
1749
1745 emptyrebase = False
1750 emptyrebase = False
1746 repo.ui.debug('rebase onto %s starting from %s\n' % (dest, root))
1751 repo.ui.debug('rebase onto %s starting from %s\n' % (dest, root))
1747 if emptyrebase:
1752 if emptyrebase:
1748 return None
1753 return None
1749 for rev in sorted(state):
1754 for rev in sorted(state):
1750 parents = [p for p in repo.changelog.parentrevs(rev) if p != nullrev]
1755 parents = [p for p in repo.changelog.parentrevs(rev) if p != nullrev]
1751 # if all parents of this revision are done, then so is this revision
1756 # if all parents of this revision are done, then so is this revision
1752 if parents and all((state.get(p) == p for p in parents)):
1757 if parents and all((state.get(p) == p for p in parents)):
1753 state[rev] = rev
1758 state[rev] = rev
1754 return originalwd, destmap, state
1759 return originalwd, destmap, state
1755
1760
1756 def clearrebased(ui, repo, destmap, state, skipped, collapsedas=None,
1761 def clearrebased(ui, repo, destmap, state, skipped, collapsedas=None,
1757 keepf=False, fm=None, backup=True):
1762 keepf=False, fm=None, backup=True):
1758 """dispose of rebased revision at the end of the rebase
1763 """dispose of rebased revision at the end of the rebase
1759
1764
1760 If `collapsedas` is not None, the rebase was a collapse whose result if the
1765 If `collapsedas` is not None, the rebase was a collapse whose result if the
1761 `collapsedas` node.
1766 `collapsedas` node.
1762
1767
1763 If `keepf` is not True, the rebase has --keep set and no nodes should be
1768 If `keepf` is not True, the rebase has --keep set and no nodes should be
1764 removed (but bookmarks still need to be moved).
1769 removed (but bookmarks still need to be moved).
1765
1770
1766 If `backup` is False, no backup will be stored when stripping rebased
1771 If `backup` is False, no backup will be stored when stripping rebased
1767 revisions.
1772 revisions.
1768 """
1773 """
1769 tonode = repo.changelog.node
1774 tonode = repo.changelog.node
1770 replacements = {}
1775 replacements = {}
1771 moves = {}
1776 moves = {}
1772 for rev, newrev in sorted(state.items()):
1777 for rev, newrev in sorted(state.items()):
1773 if newrev >= 0 and newrev != rev:
1778 if newrev >= 0 and newrev != rev:
1774 oldnode = tonode(rev)
1779 oldnode = tonode(rev)
1775 newnode = collapsedas or tonode(newrev)
1780 newnode = collapsedas or tonode(newrev)
1776 moves[oldnode] = newnode
1781 moves[oldnode] = newnode
1777 if not keepf:
1782 if not keepf:
1778 if rev in skipped:
1783 if rev in skipped:
1779 succs = ()
1784 succs = ()
1780 else:
1785 else:
1781 succs = (newnode,)
1786 succs = (newnode,)
1782 replacements[oldnode] = succs
1787 replacements[oldnode] = succs
1783 scmutil.cleanupnodes(repo, replacements, 'rebase', moves, backup=backup)
1788 scmutil.cleanupnodes(repo, replacements, 'rebase', moves, backup=backup)
1784 if fm:
1789 if fm:
1785 hf = fm.hexfunc
1790 hf = fm.hexfunc
1786 fl = fm.formatlist
1791 fl = fm.formatlist
1787 fd = fm.formatdict
1792 fd = fm.formatdict
1788 nodechanges = fd({hf(oldn): fl([hf(n) for n in newn], name='node')
1793 nodechanges = fd({hf(oldn): fl([hf(n) for n in newn], name='node')
1789 for oldn, newn in replacements.iteritems()},
1794 for oldn, newn in replacements.iteritems()},
1790 key="oldnode", value="newnodes")
1795 key="oldnode", value="newnodes")
1791 fm.data(nodechanges=nodechanges)
1796 fm.data(nodechanges=nodechanges)
1792
1797
1793 def pullrebase(orig, ui, repo, *args, **opts):
1798 def pullrebase(orig, ui, repo, *args, **opts):
1794 'Call rebase after pull if the latter has been invoked with --rebase'
1799 'Call rebase after pull if the latter has been invoked with --rebase'
1795 ret = None
1800 ret = None
1796 if opts.get(r'rebase'):
1801 if opts.get(r'rebase'):
1797 if ui.configbool('commands', 'rebase.requiredest'):
1802 if ui.configbool('commands', 'rebase.requiredest'):
1798 msg = _('rebase destination required by configuration')
1803 msg = _('rebase destination required by configuration')
1799 hint = _('use hg pull followed by hg rebase -d DEST')
1804 hint = _('use hg pull followed by hg rebase -d DEST')
1800 raise error.Abort(msg, hint=hint)
1805 raise error.Abort(msg, hint=hint)
1801
1806
1802 with repo.wlock(), repo.lock():
1807 with repo.wlock(), repo.lock():
1803 if opts.get(r'update'):
1808 if opts.get(r'update'):
1804 del opts[r'update']
1809 del opts[r'update']
1805 ui.debug('--update and --rebase are not compatible, ignoring '
1810 ui.debug('--update and --rebase are not compatible, ignoring '
1806 'the update flag\n')
1811 'the update flag\n')
1807
1812
1808 cmdutil.checkunfinished(repo)
1813 cmdutil.checkunfinished(repo)
1809 cmdutil.bailifchanged(repo, hint=_('cannot pull with rebase: '
1814 cmdutil.bailifchanged(repo, hint=_('cannot pull with rebase: '
1810 'please commit or shelve your changes first'))
1815 'please commit or shelve your changes first'))
1811
1816
1812 revsprepull = len(repo)
1817 revsprepull = len(repo)
1813 origpostincoming = commands.postincoming
1818 origpostincoming = commands.postincoming
1814 def _dummy(*args, **kwargs):
1819 def _dummy(*args, **kwargs):
1815 pass
1820 pass
1816 commands.postincoming = _dummy
1821 commands.postincoming = _dummy
1817 try:
1822 try:
1818 ret = orig(ui, repo, *args, **opts)
1823 ret = orig(ui, repo, *args, **opts)
1819 finally:
1824 finally:
1820 commands.postincoming = origpostincoming
1825 commands.postincoming = origpostincoming
1821 revspostpull = len(repo)
1826 revspostpull = len(repo)
1822 if revspostpull > revsprepull:
1827 if revspostpull > revsprepull:
1823 # --rev option from pull conflict with rebase own --rev
1828 # --rev option from pull conflict with rebase own --rev
1824 # dropping it
1829 # dropping it
1825 if r'rev' in opts:
1830 if r'rev' in opts:
1826 del opts[r'rev']
1831 del opts[r'rev']
1827 # positional argument from pull conflicts with rebase's own
1832 # positional argument from pull conflicts with rebase's own
1828 # --source.
1833 # --source.
1829 if r'source' in opts:
1834 if r'source' in opts:
1830 del opts[r'source']
1835 del opts[r'source']
1831 # revsprepull is the len of the repo, not revnum of tip.
1836 # revsprepull is the len of the repo, not revnum of tip.
1832 destspace = list(repo.changelog.revs(start=revsprepull))
1837 destspace = list(repo.changelog.revs(start=revsprepull))
1833 opts[r'_destspace'] = destspace
1838 opts[r'_destspace'] = destspace
1834 try:
1839 try:
1835 rebase(ui, repo, **opts)
1840 rebase(ui, repo, **opts)
1836 except error.NoMergeDestAbort:
1841 except error.NoMergeDestAbort:
1837 # we can maybe update instead
1842 # we can maybe update instead
1838 rev, _a, _b = destutil.destupdate(repo)
1843 rev, _a, _b = destutil.destupdate(repo)
1839 if rev == repo['.'].rev():
1844 if rev == repo['.'].rev():
1840 ui.status(_('nothing to rebase\n'))
1845 ui.status(_('nothing to rebase\n'))
1841 else:
1846 else:
1842 ui.status(_('nothing to rebase - updating instead\n'))
1847 ui.status(_('nothing to rebase - updating instead\n'))
1843 # not passing argument to get the bare update behavior
1848 # not passing argument to get the bare update behavior
1844 # with warning and trumpets
1849 # with warning and trumpets
1845 commands.update(ui, repo)
1850 commands.update(ui, repo)
1846 else:
1851 else:
1847 if opts.get(r'tool'):
1852 if opts.get(r'tool'):
1848 raise error.Abort(_('--tool can only be used with --rebase'))
1853 raise error.Abort(_('--tool can only be used with --rebase'))
1849 ret = orig(ui, repo, *args, **opts)
1854 ret = orig(ui, repo, *args, **opts)
1850
1855
1851 return ret
1856 return ret
1852
1857
1853 def _filterobsoleterevs(repo, revs):
1858 def _filterobsoleterevs(repo, revs):
1854 """returns a set of the obsolete revisions in revs"""
1859 """returns a set of the obsolete revisions in revs"""
1855 return set(r for r in revs if repo[r].obsolete())
1860 return set(r for r in revs if repo[r].obsolete())
1856
1861
1857 def _computeobsoletenotrebased(repo, rebaseobsrevs, destmap):
1862 def _computeobsoletenotrebased(repo, rebaseobsrevs, destmap):
1858 """Return (obsoletenotrebased, obsoletewithoutsuccessorindestination).
1863 """Return (obsoletenotrebased, obsoletewithoutsuccessorindestination).
1859
1864
1860 `obsoletenotrebased` is a mapping mapping obsolete => successor for all
1865 `obsoletenotrebased` is a mapping mapping obsolete => successor for all
1861 obsolete nodes to be rebased given in `rebaseobsrevs`.
1866 obsolete nodes to be rebased given in `rebaseobsrevs`.
1862
1867
1863 `obsoletewithoutsuccessorindestination` is a set with obsolete revisions
1868 `obsoletewithoutsuccessorindestination` is a set with obsolete revisions
1864 without a successor in destination.
1869 without a successor in destination.
1865
1870
1866 `obsoleteextinctsuccessors` is a set of obsolete revisions with only
1871 `obsoleteextinctsuccessors` is a set of obsolete revisions with only
1867 obsolete successors.
1872 obsolete successors.
1868 """
1873 """
1869 obsoletenotrebased = {}
1874 obsoletenotrebased = {}
1870 obsoletewithoutsuccessorindestination = set([])
1875 obsoletewithoutsuccessorindestination = set([])
1871 obsoleteextinctsuccessors = set([])
1876 obsoleteextinctsuccessors = set([])
1872
1877
1873 assert repo.filtername is None
1878 assert repo.filtername is None
1874 cl = repo.changelog
1879 cl = repo.changelog
1875 nodemap = cl.nodemap
1880 nodemap = cl.nodemap
1876 extinctrevs = set(repo.revs('extinct()'))
1881 extinctrevs = set(repo.revs('extinct()'))
1877 for srcrev in rebaseobsrevs:
1882 for srcrev in rebaseobsrevs:
1878 srcnode = cl.node(srcrev)
1883 srcnode = cl.node(srcrev)
1879 # XXX: more advanced APIs are required to handle split correctly
1884 # XXX: more advanced APIs are required to handle split correctly
1880 successors = set(obsutil.allsuccessors(repo.obsstore, [srcnode]))
1885 successors = set(obsutil.allsuccessors(repo.obsstore, [srcnode]))
1881 # obsutil.allsuccessors includes node itself
1886 # obsutil.allsuccessors includes node itself
1882 successors.remove(srcnode)
1887 successors.remove(srcnode)
1883 succrevs = {nodemap[s] for s in successors if s in nodemap}
1888 succrevs = {nodemap[s] for s in successors if s in nodemap}
1884 if succrevs.issubset(extinctrevs):
1889 if succrevs.issubset(extinctrevs):
1885 # all successors are extinct
1890 # all successors are extinct
1886 obsoleteextinctsuccessors.add(srcrev)
1891 obsoleteextinctsuccessors.add(srcrev)
1887 if not successors:
1892 if not successors:
1888 # no successor
1893 # no successor
1889 obsoletenotrebased[srcrev] = None
1894 obsoletenotrebased[srcrev] = None
1890 else:
1895 else:
1891 dstrev = destmap[srcrev]
1896 dstrev = destmap[srcrev]
1892 for succrev in succrevs:
1897 for succrev in succrevs:
1893 if cl.isancestorrev(succrev, dstrev):
1898 if cl.isancestorrev(succrev, dstrev):
1894 obsoletenotrebased[srcrev] = succrev
1899 obsoletenotrebased[srcrev] = succrev
1895 break
1900 break
1896 else:
1901 else:
1897 # If 'srcrev' has a successor in rebase set but none in
1902 # If 'srcrev' has a successor in rebase set but none in
1898 # destination (which would be catched above), we shall skip it
1903 # destination (which would be catched above), we shall skip it
1899 # and its descendants to avoid divergence.
1904 # and its descendants to avoid divergence.
1900 if any(s in destmap for s in succrevs):
1905 if any(s in destmap for s in succrevs):
1901 obsoletewithoutsuccessorindestination.add(srcrev)
1906 obsoletewithoutsuccessorindestination.add(srcrev)
1902
1907
1903 return (
1908 return (
1904 obsoletenotrebased,
1909 obsoletenotrebased,
1905 obsoletewithoutsuccessorindestination,
1910 obsoletewithoutsuccessorindestination,
1906 obsoleteextinctsuccessors,
1911 obsoleteextinctsuccessors,
1907 )
1912 )
1908
1913
1909 def summaryhook(ui, repo):
1914 def summaryhook(ui, repo):
1910 if not repo.vfs.exists('rebasestate'):
1915 if not repo.vfs.exists('rebasestate'):
1911 return
1916 return
1912 try:
1917 try:
1913 rbsrt = rebaseruntime(repo, ui, {})
1918 rbsrt = rebaseruntime(repo, ui, {})
1914 rbsrt.restorestatus()
1919 rbsrt.restorestatus()
1915 state = rbsrt.state
1920 state = rbsrt.state
1916 except error.RepoLookupError:
1921 except error.RepoLookupError:
1917 # i18n: column positioning for "hg summary"
1922 # i18n: column positioning for "hg summary"
1918 msg = _('rebase: (use "hg rebase --abort" to clear broken state)\n')
1923 msg = _('rebase: (use "hg rebase --abort" to clear broken state)\n')
1919 ui.write(msg)
1924 ui.write(msg)
1920 return
1925 return
1921 numrebased = len([i for i in state.itervalues() if i >= 0])
1926 numrebased = len([i for i in state.itervalues() if i >= 0])
1922 # i18n: column positioning for "hg summary"
1927 # i18n: column positioning for "hg summary"
1923 ui.write(_('rebase: %s, %s (rebase --continue)\n') %
1928 ui.write(_('rebase: %s, %s (rebase --continue)\n') %
1924 (ui.label(_('%d rebased'), 'rebase.rebased') % numrebased,
1929 (ui.label(_('%d rebased'), 'rebase.rebased') % numrebased,
1925 ui.label(_('%d remaining'), 'rebase.remaining') %
1930 ui.label(_('%d remaining'), 'rebase.remaining') %
1926 (len(state) - numrebased)))
1931 (len(state) - numrebased)))
1927
1932
1928 def uisetup(ui):
1933 def uisetup(ui):
1929 #Replace pull with a decorator to provide --rebase option
1934 #Replace pull with a decorator to provide --rebase option
1930 entry = extensions.wrapcommand(commands.table, 'pull', pullrebase)
1935 entry = extensions.wrapcommand(commands.table, 'pull', pullrebase)
1931 entry[1].append(('', 'rebase', None,
1936 entry[1].append(('', 'rebase', None,
1932 _("rebase working directory to branch head")))
1937 _("rebase working directory to branch head")))
1933 entry[1].append(('t', 'tool', '',
1938 entry[1].append(('t', 'tool', '',
1934 _("specify merge tool for rebase")))
1939 _("specify merge tool for rebase")))
1935 cmdutil.summaryhooks.add('rebase', summaryhook)
1940 cmdutil.summaryhooks.add('rebase', summaryhook)
1936 cmdutil.unfinishedstates.append(
1941 cmdutil.unfinishedstates.append(
1937 ['rebasestate', False, False, _('rebase in progress'),
1942 ['rebasestate', False, False, _('rebase in progress'),
1938 _("use 'hg rebase --continue' or 'hg rebase --abort'")])
1943 _("use 'hg rebase --continue' or 'hg rebase --abort'")])
1939 cmdutil.afterresolvedstates.append(
1944 cmdutil.afterresolvedstates.append(
1940 ['rebasestate', _('hg rebase --continue')])
1945 ['rebasestate', _('hg rebase --continue')])
@@ -1,2005 +1,2024
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:
2007 =================================================
2008 $ hg rebase -s 3 -d 5
2009 rebasing 3:055a42cdd887 "d"
2010 merging d
2011 warning: conflicts while merging d! (edit, then use 'hg resolve --mark')
2012 unresolved conflicts (see hg resolve, then hg rebase --continue)
2013 [1]
2014 $ hg rebase --stop --dry-run
2015 abort: cannot use --stop with --dry-run or --confirm
2016 [255]
2017
2018 $ hg rebase -s 3 -d 5
2019 abort: rebase in progress
2020 (use 'hg rebase --continue' or 'hg rebase --abort')
2021 [255]
2022 $ hg rebase --stop --continue
2023 abort: cannot use --stop with --abort or --continue
2024 [255]
General Comments 0
You need to be logged in to leave comments. Login now