##// END OF EJS Templates
rebase: improve resolve failure message
Steve Borho -
r12896:b19b4c1d stable
parent child Browse files
Show More
@@ -1,577 +1,577 b''
1 # rebase.py - rebasing feature for mercurial
1 # rebase.py - rebasing feature for mercurial
2 #
2 #
3 # Copyright 2008 Stefano Tortarolo <stefano.tortarolo at gmail dot com>
3 # Copyright 2008 Stefano Tortarolo <stefano.tortarolo at gmail dot com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 '''command to move sets of revisions to a different ancestor
8 '''command to move sets of revisions to a different ancestor
9
9
10 This extension lets you rebase changesets in an existing Mercurial
10 This extension lets you rebase changesets in an existing Mercurial
11 repository.
11 repository.
12
12
13 For more information:
13 For more information:
14 http://mercurial.selenic.com/wiki/RebaseExtension
14 http://mercurial.selenic.com/wiki/RebaseExtension
15 '''
15 '''
16
16
17 from mercurial import hg, util, repair, merge, cmdutil, commands
17 from mercurial import hg, util, repair, merge, cmdutil, commands
18 from mercurial import extensions, ancestor, copies, patch
18 from mercurial import extensions, ancestor, copies, patch
19 from mercurial.commands import templateopts
19 from mercurial.commands import templateopts
20 from mercurial.node import nullrev
20 from mercurial.node import nullrev
21 from mercurial.lock import release
21 from mercurial.lock import release
22 from mercurial.i18n import _
22 from mercurial.i18n import _
23 import os, errno
23 import os, errno
24
24
25 nullmerge = -2
25 nullmerge = -2
26
26
27 def rebase(ui, repo, **opts):
27 def rebase(ui, repo, **opts):
28 """move changeset (and descendants) to a different branch
28 """move changeset (and descendants) to a different branch
29
29
30 Rebase uses repeated merging to graft changesets from one part of
30 Rebase uses repeated merging to graft changesets from one part of
31 history (the source) onto another (the destination). This can be
31 history (the source) onto another (the destination). This can be
32 useful for linearizing *local* changes relative to a master
32 useful for linearizing *local* changes relative to a master
33 development tree.
33 development tree.
34
34
35 You should not rebase changesets that have already been shared
35 You should not rebase changesets that have already been shared
36 with others. Doing so will force everybody else to perform the
36 with others. Doing so will force everybody else to perform the
37 same rebase or they will end up with duplicated changesets after
37 same rebase or they will end up with duplicated changesets after
38 pulling in your rebased changesets.
38 pulling in your rebased changesets.
39
39
40 If you don't specify a destination changeset (``-d/--dest``),
40 If you don't specify a destination changeset (``-d/--dest``),
41 rebase uses the tipmost head of the current named branch as the
41 rebase uses the tipmost head of the current named branch as the
42 destination. (The destination changeset is not modified by
42 destination. (The destination changeset is not modified by
43 rebasing, but new changesets are added as its descendants.)
43 rebasing, but new changesets are added as its descendants.)
44
44
45 You can specify which changesets to rebase in two ways: as a
45 You can specify which changesets to rebase in two ways: as a
46 "source" changeset or as a "base" changeset. Both are shorthand
46 "source" changeset or as a "base" changeset. Both are shorthand
47 for a topologically related set of changesets (the "source
47 for a topologically related set of changesets (the "source
48 branch"). If you specify source (``-s/--source``), rebase will
48 branch"). If you specify source (``-s/--source``), rebase will
49 rebase that changeset and all of its descendants onto dest. If you
49 rebase that changeset and all of its descendants onto dest. If you
50 specify base (``-b/--base``), rebase will select ancestors of base
50 specify base (``-b/--base``), rebase will select ancestors of base
51 back to but not including the common ancestor with dest. Thus,
51 back to but not including the common ancestor with dest. Thus,
52 ``-b`` is less precise but more convenient than ``-s``: you can
52 ``-b`` is less precise but more convenient than ``-s``: you can
53 specify any changeset in the source branch, and rebase will select
53 specify any changeset in the source branch, and rebase will select
54 the whole branch. If you specify neither ``-s`` nor ``-b``, rebase
54 the whole branch. If you specify neither ``-s`` nor ``-b``, rebase
55 uses the parent of the working directory as the base.
55 uses the parent of the working directory as the base.
56
56
57 By default, rebase recreates the changesets in the source branch
57 By default, rebase recreates the changesets in the source branch
58 as descendants of dest and then destroys the originals. Use
58 as descendants of dest and then destroys the originals. Use
59 ``--keep`` to preserve the original source changesets. Some
59 ``--keep`` to preserve the original source changesets. Some
60 changesets in the source branch (e.g. merges from the destination
60 changesets in the source branch (e.g. merges from the destination
61 branch) may be dropped if they no longer contribute any change.
61 branch) may be dropped if they no longer contribute any change.
62
62
63 One result of the rules for selecting the destination changeset
63 One result of the rules for selecting the destination changeset
64 and source branch is that, unlike ``merge``, rebase will do
64 and source branch is that, unlike ``merge``, rebase will do
65 nothing if you are at the latest (tipmost) head of a named branch
65 nothing if you are at the latest (tipmost) head of a named branch
66 with two heads. You need to explicitly specify source and/or
66 with two heads. You need to explicitly specify source and/or
67 destination (or ``update`` to the other head, if it's the head of
67 destination (or ``update`` to the other head, if it's the head of
68 the intended source branch).
68 the intended source branch).
69
69
70 If a rebase is interrupted to manually resolve a merge, it can be
70 If a rebase is interrupted to manually resolve a merge, it can be
71 continued with --continue/-c or aborted with --abort/-a.
71 continued with --continue/-c or aborted with --abort/-a.
72
72
73 Returns 0 on success, 1 if nothing to rebase.
73 Returns 0 on success, 1 if nothing to rebase.
74 """
74 """
75 originalwd = target = None
75 originalwd = target = None
76 external = nullrev
76 external = nullrev
77 state = {}
77 state = {}
78 skipped = set()
78 skipped = set()
79 targetancestors = set()
79 targetancestors = set()
80
80
81 lock = wlock = None
81 lock = wlock = None
82 try:
82 try:
83 lock = repo.lock()
83 lock = repo.lock()
84 wlock = repo.wlock()
84 wlock = repo.wlock()
85
85
86 # Validate input and define rebasing points
86 # Validate input and define rebasing points
87 destf = opts.get('dest', None)
87 destf = opts.get('dest', None)
88 srcf = opts.get('source', None)
88 srcf = opts.get('source', None)
89 basef = opts.get('base', None)
89 basef = opts.get('base', None)
90 contf = opts.get('continue')
90 contf = opts.get('continue')
91 abortf = opts.get('abort')
91 abortf = opts.get('abort')
92 collapsef = opts.get('collapse', False)
92 collapsef = opts.get('collapse', False)
93 extrafn = opts.get('extrafn')
93 extrafn = opts.get('extrafn')
94 keepf = opts.get('keep', False)
94 keepf = opts.get('keep', False)
95 keepbranchesf = opts.get('keepbranches', False)
95 keepbranchesf = opts.get('keepbranches', False)
96 detachf = opts.get('detach', False)
96 detachf = opts.get('detach', False)
97 # keepopen is not meant for use on the command line, but by
97 # keepopen is not meant for use on the command line, but by
98 # other extensions
98 # other extensions
99 keepopen = opts.get('keepopen', False)
99 keepopen = opts.get('keepopen', False)
100
100
101 if contf or abortf:
101 if contf or abortf:
102 if contf and abortf:
102 if contf and abortf:
103 raise util.Abort(_('cannot use both abort and continue'))
103 raise util.Abort(_('cannot use both abort and continue'))
104 if collapsef:
104 if collapsef:
105 raise util.Abort(
105 raise util.Abort(
106 _('cannot use collapse with continue or abort'))
106 _('cannot use collapse with continue or abort'))
107 if detachf:
107 if detachf:
108 raise util.Abort(_('cannot use detach with continue or abort'))
108 raise util.Abort(_('cannot use detach with continue or abort'))
109 if srcf or basef or destf:
109 if srcf or basef or destf:
110 raise util.Abort(
110 raise util.Abort(
111 _('abort and continue do not allow specifying revisions'))
111 _('abort and continue do not allow specifying revisions'))
112
112
113 (originalwd, target, state, skipped, collapsef, keepf,
113 (originalwd, target, state, skipped, collapsef, keepf,
114 keepbranchesf, external) = restorestatus(repo)
114 keepbranchesf, external) = restorestatus(repo)
115 if abortf:
115 if abortf:
116 return abort(repo, originalwd, target, state)
116 return abort(repo, originalwd, target, state)
117 else:
117 else:
118 if srcf and basef:
118 if srcf and basef:
119 raise util.Abort(_('cannot specify both a '
119 raise util.Abort(_('cannot specify both a '
120 'revision and a base'))
120 'revision and a base'))
121 if detachf:
121 if detachf:
122 if not srcf:
122 if not srcf:
123 raise util.Abort(
123 raise util.Abort(
124 _('detach requires a revision to be specified'))
124 _('detach requires a revision to be specified'))
125 if basef:
125 if basef:
126 raise util.Abort(_('cannot specify a base with detach'))
126 raise util.Abort(_('cannot specify a base with detach'))
127
127
128 cmdutil.bail_if_changed(repo)
128 cmdutil.bail_if_changed(repo)
129 result = buildstate(repo, destf, srcf, basef, detachf)
129 result = buildstate(repo, destf, srcf, basef, detachf)
130 if not result:
130 if not result:
131 # Empty state built, nothing to rebase
131 # Empty state built, nothing to rebase
132 ui.status(_('nothing to rebase\n'))
132 ui.status(_('nothing to rebase\n'))
133 return 1
133 return 1
134 else:
134 else:
135 originalwd, target, state = result
135 originalwd, target, state = result
136 if collapsef:
136 if collapsef:
137 targetancestors = set(repo.changelog.ancestors(target))
137 targetancestors = set(repo.changelog.ancestors(target))
138 external = checkexternal(repo, state, targetancestors)
138 external = checkexternal(repo, state, targetancestors)
139
139
140 if keepbranchesf:
140 if keepbranchesf:
141 if extrafn:
141 if extrafn:
142 raise util.Abort(_('cannot use both keepbranches and extrafn'))
142 raise util.Abort(_('cannot use both keepbranches and extrafn'))
143 def extrafn(ctx, extra):
143 def extrafn(ctx, extra):
144 extra['branch'] = ctx.branch()
144 extra['branch'] = ctx.branch()
145
145
146 # Rebase
146 # Rebase
147 if not targetancestors:
147 if not targetancestors:
148 targetancestors = set(repo.changelog.ancestors(target))
148 targetancestors = set(repo.changelog.ancestors(target))
149 targetancestors.add(target)
149 targetancestors.add(target)
150
150
151 sortedstate = sorted(state)
151 sortedstate = sorted(state)
152 total = len(sortedstate)
152 total = len(sortedstate)
153 pos = 0
153 pos = 0
154 for rev in sortedstate:
154 for rev in sortedstate:
155 pos += 1
155 pos += 1
156 if state[rev] == -1:
156 if state[rev] == -1:
157 ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, repo[rev])),
157 ui.progress(_("rebasing"), pos, ("%d:%s" % (rev, repo[rev])),
158 _('changesets'), total)
158 _('changesets'), total)
159 storestatus(repo, originalwd, target, state, collapsef, keepf,
159 storestatus(repo, originalwd, target, state, collapsef, keepf,
160 keepbranchesf, external)
160 keepbranchesf, external)
161 p1, p2 = defineparents(repo, rev, target, state,
161 p1, p2 = defineparents(repo, rev, target, state,
162 targetancestors)
162 targetancestors)
163 if len(repo.parents()) == 2:
163 if len(repo.parents()) == 2:
164 repo.ui.debug('resuming interrupted rebase\n')
164 repo.ui.debug('resuming interrupted rebase\n')
165 else:
165 else:
166 stats = rebasenode(repo, rev, p1, p2, state)
166 stats = rebasenode(repo, rev, p1, p2, state)
167 if stats and stats[3] > 0:
167 if stats and stats[3] > 0:
168 raise util.Abort(_('fix unresolved conflicts with hg '
168 raise util.Abort(_('unresolved conflicts (see hg '
169 'resolve then run hg rebase --continue'))
169 'resolve, then hg rebase --continue)'))
170 updatedirstate(repo, rev, target, p2)
170 updatedirstate(repo, rev, target, p2)
171 if not collapsef:
171 if not collapsef:
172 newrev = concludenode(repo, rev, p1, p2, extrafn=extrafn)
172 newrev = concludenode(repo, rev, p1, p2, extrafn=extrafn)
173 else:
173 else:
174 # Skip commit if we are collapsing
174 # Skip commit if we are collapsing
175 repo.dirstate.setparents(repo[p1].node())
175 repo.dirstate.setparents(repo[p1].node())
176 newrev = None
176 newrev = None
177 # Update the state
177 # Update the state
178 if newrev is not None:
178 if newrev is not None:
179 state[rev] = repo[newrev].rev()
179 state[rev] = repo[newrev].rev()
180 else:
180 else:
181 if not collapsef:
181 if not collapsef:
182 ui.note(_('no changes, revision %d skipped\n') % rev)
182 ui.note(_('no changes, revision %d skipped\n') % rev)
183 ui.debug('next revision set to %s\n' % p1)
183 ui.debug('next revision set to %s\n' % p1)
184 skipped.add(rev)
184 skipped.add(rev)
185 state[rev] = p1
185 state[rev] = p1
186
186
187 ui.progress(_('rebasing'), None)
187 ui.progress(_('rebasing'), None)
188 ui.note(_('rebase merging completed\n'))
188 ui.note(_('rebase merging completed\n'))
189
189
190 if collapsef and not keepopen:
190 if collapsef and not keepopen:
191 p1, p2 = defineparents(repo, min(state), target,
191 p1, p2 = defineparents(repo, min(state), target,
192 state, targetancestors)
192 state, targetancestors)
193 commitmsg = 'Collapsed revision'
193 commitmsg = 'Collapsed revision'
194 for rebased in state:
194 for rebased in state:
195 if rebased not in skipped and state[rebased] != nullmerge:
195 if rebased not in skipped and state[rebased] != nullmerge:
196 commitmsg += '\n* %s' % repo[rebased].description()
196 commitmsg += '\n* %s' % repo[rebased].description()
197 commitmsg = ui.edit(commitmsg, repo.ui.username())
197 commitmsg = ui.edit(commitmsg, repo.ui.username())
198 newrev = concludenode(repo, rev, p1, external, commitmsg=commitmsg,
198 newrev = concludenode(repo, rev, p1, external, commitmsg=commitmsg,
199 extrafn=extrafn)
199 extrafn=extrafn)
200
200
201 if 'qtip' in repo.tags():
201 if 'qtip' in repo.tags():
202 updatemq(repo, state, skipped, **opts)
202 updatemq(repo, state, skipped, **opts)
203
203
204 if not keepf:
204 if not keepf:
205 # Remove no more useful revisions
205 # Remove no more useful revisions
206 rebased = [rev for rev in state if state[rev] != nullmerge]
206 rebased = [rev for rev in state if state[rev] != nullmerge]
207 if rebased:
207 if rebased:
208 if set(repo.changelog.descendants(min(rebased))) - set(state):
208 if set(repo.changelog.descendants(min(rebased))) - set(state):
209 ui.warn(_("warning: new changesets detected "
209 ui.warn(_("warning: new changesets detected "
210 "on source branch, not stripping\n"))
210 "on source branch, not stripping\n"))
211 else:
211 else:
212 # backup the old csets by default
212 # backup the old csets by default
213 repair.strip(ui, repo, repo[min(rebased)].node(), "all")
213 repair.strip(ui, repo, repo[min(rebased)].node(), "all")
214
214
215 clearstatus(repo)
215 clearstatus(repo)
216 ui.note(_("rebase completed\n"))
216 ui.note(_("rebase completed\n"))
217 if os.path.exists(repo.sjoin('undo')):
217 if os.path.exists(repo.sjoin('undo')):
218 util.unlink(repo.sjoin('undo'))
218 util.unlink(repo.sjoin('undo'))
219 if skipped:
219 if skipped:
220 ui.note(_("%d revisions have been skipped\n") % len(skipped))
220 ui.note(_("%d revisions have been skipped\n") % len(skipped))
221 finally:
221 finally:
222 release(lock, wlock)
222 release(lock, wlock)
223
223
224 def rebasemerge(repo, rev, first=False):
224 def rebasemerge(repo, rev, first=False):
225 'return the correct ancestor'
225 'return the correct ancestor'
226 oldancestor = ancestor.ancestor
226 oldancestor = ancestor.ancestor
227
227
228 def newancestor(a, b, pfunc):
228 def newancestor(a, b, pfunc):
229 if b == rev:
229 if b == rev:
230 return repo[rev].parents()[0].rev()
230 return repo[rev].parents()[0].rev()
231 return oldancestor(a, b, pfunc)
231 return oldancestor(a, b, pfunc)
232
232
233 if not first:
233 if not first:
234 ancestor.ancestor = newancestor
234 ancestor.ancestor = newancestor
235 else:
235 else:
236 repo.ui.debug("first revision, do not change ancestor\n")
236 repo.ui.debug("first revision, do not change ancestor\n")
237 try:
237 try:
238 stats = merge.update(repo, rev, True, True, False)
238 stats = merge.update(repo, rev, True, True, False)
239 return stats
239 return stats
240 finally:
240 finally:
241 ancestor.ancestor = oldancestor
241 ancestor.ancestor = oldancestor
242
242
243 def checkexternal(repo, state, targetancestors):
243 def checkexternal(repo, state, targetancestors):
244 """Check whether one or more external revisions need to be taken in
244 """Check whether one or more external revisions need to be taken in
245 consideration. In the latter case, abort.
245 consideration. In the latter case, abort.
246 """
246 """
247 external = nullrev
247 external = nullrev
248 source = min(state)
248 source = min(state)
249 for rev in state:
249 for rev in state:
250 if rev == source:
250 if rev == source:
251 continue
251 continue
252 # Check externals and fail if there are more than one
252 # Check externals and fail if there are more than one
253 for p in repo[rev].parents():
253 for p in repo[rev].parents():
254 if (p.rev() not in state
254 if (p.rev() not in state
255 and p.rev() not in targetancestors):
255 and p.rev() not in targetancestors):
256 if external != nullrev:
256 if external != nullrev:
257 raise util.Abort(_('unable to collapse, there is more '
257 raise util.Abort(_('unable to collapse, there is more '
258 'than one external parent'))
258 'than one external parent'))
259 external = p.rev()
259 external = p.rev()
260 return external
260 return external
261
261
262 def updatedirstate(repo, rev, p1, p2):
262 def updatedirstate(repo, rev, p1, p2):
263 """Keep track of renamed files in the revision that is going to be rebased
263 """Keep track of renamed files in the revision that is going to be rebased
264 """
264 """
265 # Here we simulate the copies and renames in the source changeset
265 # Here we simulate the copies and renames in the source changeset
266 cop, diver = copies.copies(repo, repo[rev], repo[p1], repo[p2], True)
266 cop, diver = copies.copies(repo, repo[rev], repo[p1], repo[p2], True)
267 m1 = repo[rev].manifest()
267 m1 = repo[rev].manifest()
268 m2 = repo[p1].manifest()
268 m2 = repo[p1].manifest()
269 for k, v in cop.iteritems():
269 for k, v in cop.iteritems():
270 if k in m1:
270 if k in m1:
271 if v in m1 or v in m2:
271 if v in m1 or v in m2:
272 repo.dirstate.copy(v, k)
272 repo.dirstate.copy(v, k)
273 if v in m2 and v not in m1:
273 if v in m2 and v not in m1:
274 repo.dirstate.remove(v)
274 repo.dirstate.remove(v)
275
275
276 def concludenode(repo, rev, p1, p2, commitmsg=None, extrafn=None):
276 def concludenode(repo, rev, p1, p2, commitmsg=None, extrafn=None):
277 'Commit the changes and store useful information in extra'
277 'Commit the changes and store useful information in extra'
278 try:
278 try:
279 repo.dirstate.setparents(repo[p1].node(), repo[p2].node())
279 repo.dirstate.setparents(repo[p1].node(), repo[p2].node())
280 ctx = repo[rev]
280 ctx = repo[rev]
281 if commitmsg is None:
281 if commitmsg is None:
282 commitmsg = ctx.description()
282 commitmsg = ctx.description()
283 extra = {'rebase_source': ctx.hex()}
283 extra = {'rebase_source': ctx.hex()}
284 if extrafn:
284 if extrafn:
285 extrafn(ctx, extra)
285 extrafn(ctx, extra)
286 # Commit might fail if unresolved files exist
286 # Commit might fail if unresolved files exist
287 newrev = repo.commit(text=commitmsg, user=ctx.user(),
287 newrev = repo.commit(text=commitmsg, user=ctx.user(),
288 date=ctx.date(), extra=extra)
288 date=ctx.date(), extra=extra)
289 repo.dirstate.setbranch(repo[newrev].branch())
289 repo.dirstate.setbranch(repo[newrev].branch())
290 return newrev
290 return newrev
291 except util.Abort:
291 except util.Abort:
292 # Invalidate the previous setparents
292 # Invalidate the previous setparents
293 repo.dirstate.invalidate()
293 repo.dirstate.invalidate()
294 raise
294 raise
295
295
296 def rebasenode(repo, rev, p1, p2, state):
296 def rebasenode(repo, rev, p1, p2, state):
297 'Rebase a single revision'
297 'Rebase a single revision'
298 # Merge phase
298 # Merge phase
299 # Update to target and merge it with local
299 # Update to target and merge it with local
300 if repo['.'].rev() != repo[p1].rev():
300 if repo['.'].rev() != repo[p1].rev():
301 repo.ui.debug(" update to %d:%s\n" % (repo[p1].rev(), repo[p1]))
301 repo.ui.debug(" update to %d:%s\n" % (repo[p1].rev(), repo[p1]))
302 merge.update(repo, p1, False, True, False)
302 merge.update(repo, p1, False, True, False)
303 else:
303 else:
304 repo.ui.debug(" already in target\n")
304 repo.ui.debug(" already in target\n")
305 repo.dirstate.write()
305 repo.dirstate.write()
306 repo.ui.debug(" merge against %d:%s\n" % (repo[rev].rev(), repo[rev]))
306 repo.ui.debug(" merge against %d:%s\n" % (repo[rev].rev(), repo[rev]))
307 first = repo[rev].rev() == repo[min(state)].rev()
307 first = repo[rev].rev() == repo[min(state)].rev()
308 stats = rebasemerge(repo, rev, first)
308 stats = rebasemerge(repo, rev, first)
309 return stats
309 return stats
310
310
311 def defineparents(repo, rev, target, state, targetancestors):
311 def defineparents(repo, rev, target, state, targetancestors):
312 'Return the new parent relationship of the revision that will be rebased'
312 'Return the new parent relationship of the revision that will be rebased'
313 parents = repo[rev].parents()
313 parents = repo[rev].parents()
314 p1 = p2 = nullrev
314 p1 = p2 = nullrev
315
315
316 P1n = parents[0].rev()
316 P1n = parents[0].rev()
317 if P1n in targetancestors:
317 if P1n in targetancestors:
318 p1 = target
318 p1 = target
319 elif P1n in state:
319 elif P1n in state:
320 if state[P1n] == nullmerge:
320 if state[P1n] == nullmerge:
321 p1 = target
321 p1 = target
322 else:
322 else:
323 p1 = state[P1n]
323 p1 = state[P1n]
324 else: # P1n external
324 else: # P1n external
325 p1 = target
325 p1 = target
326 p2 = P1n
326 p2 = P1n
327
327
328 if len(parents) == 2 and parents[1].rev() not in targetancestors:
328 if len(parents) == 2 and parents[1].rev() not in targetancestors:
329 P2n = parents[1].rev()
329 P2n = parents[1].rev()
330 # interesting second parent
330 # interesting second parent
331 if P2n in state:
331 if P2n in state:
332 if p1 == target: # P1n in targetancestors or external
332 if p1 == target: # P1n in targetancestors or external
333 p1 = state[P2n]
333 p1 = state[P2n]
334 else:
334 else:
335 p2 = state[P2n]
335 p2 = state[P2n]
336 else: # P2n external
336 else: # P2n external
337 if p2 != nullrev: # P1n external too => rev is a merged revision
337 if p2 != nullrev: # P1n external too => rev is a merged revision
338 raise util.Abort(_('cannot use revision %d as base, result '
338 raise util.Abort(_('cannot use revision %d as base, result '
339 'would have 3 parents') % rev)
339 'would have 3 parents') % rev)
340 p2 = P2n
340 p2 = P2n
341 repo.ui.debug(" future parents are %d and %d\n" %
341 repo.ui.debug(" future parents are %d and %d\n" %
342 (repo[p1].rev(), repo[p2].rev()))
342 (repo[p1].rev(), repo[p2].rev()))
343 return p1, p2
343 return p1, p2
344
344
345 def isagitpatch(repo, patchname):
345 def isagitpatch(repo, patchname):
346 'Return true if the given patch is in git format'
346 'Return true if the given patch is in git format'
347 mqpatch = os.path.join(repo.mq.path, patchname)
347 mqpatch = os.path.join(repo.mq.path, patchname)
348 for line in patch.linereader(file(mqpatch, 'rb')):
348 for line in patch.linereader(file(mqpatch, 'rb')):
349 if line.startswith('diff --git'):
349 if line.startswith('diff --git'):
350 return True
350 return True
351 return False
351 return False
352
352
353 def updatemq(repo, state, skipped, **opts):
353 def updatemq(repo, state, skipped, **opts):
354 'Update rebased mq patches - finalize and then import them'
354 'Update rebased mq patches - finalize and then import them'
355 mqrebase = {}
355 mqrebase = {}
356 mq = repo.mq
356 mq = repo.mq
357 for p in mq.applied:
357 for p in mq.applied:
358 rev = repo[p.node].rev()
358 rev = repo[p.node].rev()
359 if rev in state:
359 if rev in state:
360 repo.ui.debug('revision %d is an mq patch (%s), finalize it.\n' %
360 repo.ui.debug('revision %d is an mq patch (%s), finalize it.\n' %
361 (rev, p.name))
361 (rev, p.name))
362 mqrebase[rev] = (p.name, isagitpatch(repo, p.name))
362 mqrebase[rev] = (p.name, isagitpatch(repo, p.name))
363
363
364 if mqrebase:
364 if mqrebase:
365 mq.finish(repo, mqrebase.keys())
365 mq.finish(repo, mqrebase.keys())
366
366
367 # We must start import from the newest revision
367 # We must start import from the newest revision
368 for rev in sorted(mqrebase, reverse=True):
368 for rev in sorted(mqrebase, reverse=True):
369 if rev not in skipped:
369 if rev not in skipped:
370 name, isgit = mqrebase[rev]
370 name, isgit = mqrebase[rev]
371 repo.ui.debug('import mq patch %d (%s)\n' % (state[rev], name))
371 repo.ui.debug('import mq patch %d (%s)\n' % (state[rev], name))
372 mq.qimport(repo, (), patchname=name, git=isgit,
372 mq.qimport(repo, (), patchname=name, git=isgit,
373 rev=[str(state[rev])])
373 rev=[str(state[rev])])
374 mq.save_dirty()
374 mq.save_dirty()
375
375
376 def storestatus(repo, originalwd, target, state, collapse, keep, keepbranches,
376 def storestatus(repo, originalwd, target, state, collapse, keep, keepbranches,
377 external):
377 external):
378 'Store the current status to allow recovery'
378 'Store the current status to allow recovery'
379 f = repo.opener("rebasestate", "w")
379 f = repo.opener("rebasestate", "w")
380 f.write(repo[originalwd].hex() + '\n')
380 f.write(repo[originalwd].hex() + '\n')
381 f.write(repo[target].hex() + '\n')
381 f.write(repo[target].hex() + '\n')
382 f.write(repo[external].hex() + '\n')
382 f.write(repo[external].hex() + '\n')
383 f.write('%d\n' % int(collapse))
383 f.write('%d\n' % int(collapse))
384 f.write('%d\n' % int(keep))
384 f.write('%d\n' % int(keep))
385 f.write('%d\n' % int(keepbranches))
385 f.write('%d\n' % int(keepbranches))
386 for d, v in state.iteritems():
386 for d, v in state.iteritems():
387 oldrev = repo[d].hex()
387 oldrev = repo[d].hex()
388 newrev = repo[v].hex()
388 newrev = repo[v].hex()
389 f.write("%s:%s\n" % (oldrev, newrev))
389 f.write("%s:%s\n" % (oldrev, newrev))
390 f.close()
390 f.close()
391 repo.ui.debug('rebase status stored\n')
391 repo.ui.debug('rebase status stored\n')
392
392
393 def clearstatus(repo):
393 def clearstatus(repo):
394 'Remove the status files'
394 'Remove the status files'
395 if os.path.exists(repo.join("rebasestate")):
395 if os.path.exists(repo.join("rebasestate")):
396 util.unlink(repo.join("rebasestate"))
396 util.unlink(repo.join("rebasestate"))
397
397
398 def restorestatus(repo):
398 def restorestatus(repo):
399 'Restore a previously stored status'
399 'Restore a previously stored status'
400 try:
400 try:
401 target = None
401 target = None
402 collapse = False
402 collapse = False
403 external = nullrev
403 external = nullrev
404 state = {}
404 state = {}
405 f = repo.opener("rebasestate")
405 f = repo.opener("rebasestate")
406 for i, l in enumerate(f.read().splitlines()):
406 for i, l in enumerate(f.read().splitlines()):
407 if i == 0:
407 if i == 0:
408 originalwd = repo[l].rev()
408 originalwd = repo[l].rev()
409 elif i == 1:
409 elif i == 1:
410 target = repo[l].rev()
410 target = repo[l].rev()
411 elif i == 2:
411 elif i == 2:
412 external = repo[l].rev()
412 external = repo[l].rev()
413 elif i == 3:
413 elif i == 3:
414 collapse = bool(int(l))
414 collapse = bool(int(l))
415 elif i == 4:
415 elif i == 4:
416 keep = bool(int(l))
416 keep = bool(int(l))
417 elif i == 5:
417 elif i == 5:
418 keepbranches = bool(int(l))
418 keepbranches = bool(int(l))
419 else:
419 else:
420 oldrev, newrev = l.split(':')
420 oldrev, newrev = l.split(':')
421 state[repo[oldrev].rev()] = repo[newrev].rev()
421 state[repo[oldrev].rev()] = repo[newrev].rev()
422 skipped = set()
422 skipped = set()
423 # recompute the set of skipped revs
423 # recompute the set of skipped revs
424 if not collapse:
424 if not collapse:
425 seen = set([target])
425 seen = set([target])
426 for old, new in sorted(state.items()):
426 for old, new in sorted(state.items()):
427 if new != nullrev and new in seen:
427 if new != nullrev and new in seen:
428 skipped.add(old)
428 skipped.add(old)
429 seen.add(new)
429 seen.add(new)
430 repo.ui.debug('computed skipped revs: %s\n' % skipped)
430 repo.ui.debug('computed skipped revs: %s\n' % skipped)
431 repo.ui.debug('rebase status resumed\n')
431 repo.ui.debug('rebase status resumed\n')
432 return (originalwd, target, state, skipped,
432 return (originalwd, target, state, skipped,
433 collapse, keep, keepbranches, external)
433 collapse, keep, keepbranches, external)
434 except IOError, err:
434 except IOError, err:
435 if err.errno != errno.ENOENT:
435 if err.errno != errno.ENOENT:
436 raise
436 raise
437 raise util.Abort(_('no rebase in progress'))
437 raise util.Abort(_('no rebase in progress'))
438
438
439 def abort(repo, originalwd, target, state):
439 def abort(repo, originalwd, target, state):
440 'Restore the repository to its original state'
440 'Restore the repository to its original state'
441 if set(repo.changelog.descendants(target)) - set(state.values()):
441 if set(repo.changelog.descendants(target)) - set(state.values()):
442 repo.ui.warn(_("warning: new changesets detected on target branch, "
442 repo.ui.warn(_("warning: new changesets detected on target branch, "
443 "can't abort\n"))
443 "can't abort\n"))
444 return -1
444 return -1
445 else:
445 else:
446 # Strip from the first rebased revision
446 # Strip from the first rebased revision
447 merge.update(repo, repo[originalwd].rev(), False, True, False)
447 merge.update(repo, repo[originalwd].rev(), False, True, False)
448 rebased = filter(lambda x: x > -1 and x != target, state.values())
448 rebased = filter(lambda x: x > -1 and x != target, state.values())
449 if rebased:
449 if rebased:
450 strippoint = min(rebased)
450 strippoint = min(rebased)
451 # no backup of rebased cset versions needed
451 # no backup of rebased cset versions needed
452 repair.strip(repo.ui, repo, repo[strippoint].node())
452 repair.strip(repo.ui, repo, repo[strippoint].node())
453 clearstatus(repo)
453 clearstatus(repo)
454 repo.ui.warn(_('rebase aborted\n'))
454 repo.ui.warn(_('rebase aborted\n'))
455 return 0
455 return 0
456
456
457 def buildstate(repo, dest, src, base, detach):
457 def buildstate(repo, dest, src, base, detach):
458 'Define which revisions are going to be rebased and where'
458 'Define which revisions are going to be rebased and where'
459 targetancestors = set()
459 targetancestors = set()
460 detachset = set()
460 detachset = set()
461
461
462 if not dest:
462 if not dest:
463 # Destination defaults to the latest revision in the current branch
463 # Destination defaults to the latest revision in the current branch
464 branch = repo[None].branch()
464 branch = repo[None].branch()
465 dest = repo[branch].rev()
465 dest = repo[branch].rev()
466 else:
466 else:
467 dest = repo[dest].rev()
467 dest = repo[dest].rev()
468
468
469 # This check isn't strictly necessary, since mq detects commits over an
469 # This check isn't strictly necessary, since mq detects commits over an
470 # applied patch. But it prevents messing up the working directory when
470 # applied patch. But it prevents messing up the working directory when
471 # a partially completed rebase is blocked by mq.
471 # a partially completed rebase is blocked by mq.
472 if 'qtip' in repo.tags() and (repo[dest].node() in
472 if 'qtip' in repo.tags() and (repo[dest].node() in
473 [s.node for s in repo.mq.applied]):
473 [s.node for s in repo.mq.applied]):
474 raise util.Abort(_('cannot rebase onto an applied mq patch'))
474 raise util.Abort(_('cannot rebase onto an applied mq patch'))
475
475
476 if src:
476 if src:
477 commonbase = repo[src].ancestor(repo[dest])
477 commonbase = repo[src].ancestor(repo[dest])
478 if commonbase == repo[src]:
478 if commonbase == repo[src]:
479 raise util.Abort(_('source is ancestor of destination'))
479 raise util.Abort(_('source is ancestor of destination'))
480 if commonbase == repo[dest]:
480 if commonbase == repo[dest]:
481 raise util.Abort(_('source is descendant of destination'))
481 raise util.Abort(_('source is descendant of destination'))
482 source = repo[src].rev()
482 source = repo[src].rev()
483 if detach:
483 if detach:
484 # We need to keep track of source's ancestors up to the common base
484 # We need to keep track of source's ancestors up to the common base
485 srcancestors = set(repo.changelog.ancestors(source))
485 srcancestors = set(repo.changelog.ancestors(source))
486 baseancestors = set(repo.changelog.ancestors(commonbase.rev()))
486 baseancestors = set(repo.changelog.ancestors(commonbase.rev()))
487 detachset = srcancestors - baseancestors
487 detachset = srcancestors - baseancestors
488 detachset.remove(commonbase.rev())
488 detachset.remove(commonbase.rev())
489 else:
489 else:
490 if base:
490 if base:
491 cwd = repo[base].rev()
491 cwd = repo[base].rev()
492 else:
492 else:
493 cwd = repo['.'].rev()
493 cwd = repo['.'].rev()
494
494
495 if cwd == dest:
495 if cwd == dest:
496 repo.ui.debug('source and destination are the same\n')
496 repo.ui.debug('source and destination are the same\n')
497 return None
497 return None
498
498
499 targetancestors = set(repo.changelog.ancestors(dest))
499 targetancestors = set(repo.changelog.ancestors(dest))
500 if cwd in targetancestors:
500 if cwd in targetancestors:
501 repo.ui.debug('source is ancestor of destination\n')
501 repo.ui.debug('source is ancestor of destination\n')
502 return None
502 return None
503
503
504 cwdancestors = set(repo.changelog.ancestors(cwd))
504 cwdancestors = set(repo.changelog.ancestors(cwd))
505 if dest in cwdancestors:
505 if dest in cwdancestors:
506 repo.ui.debug('source is descendant of destination\n')
506 repo.ui.debug('source is descendant of destination\n')
507 return None
507 return None
508
508
509 cwdancestors.add(cwd)
509 cwdancestors.add(cwd)
510 rebasingbranch = cwdancestors - targetancestors
510 rebasingbranch = cwdancestors - targetancestors
511 source = min(rebasingbranch)
511 source = min(rebasingbranch)
512
512
513 repo.ui.debug('rebase onto %d starting from %d\n' % (dest, source))
513 repo.ui.debug('rebase onto %d starting from %d\n' % (dest, source))
514 state = dict.fromkeys(repo.changelog.descendants(source), nullrev)
514 state = dict.fromkeys(repo.changelog.descendants(source), nullrev)
515 state.update(dict.fromkeys(detachset, nullmerge))
515 state.update(dict.fromkeys(detachset, nullmerge))
516 state[source] = nullrev
516 state[source] = nullrev
517 return repo['.'].rev(), repo[dest].rev(), state
517 return repo['.'].rev(), repo[dest].rev(), state
518
518
519 def pullrebase(orig, ui, repo, *args, **opts):
519 def pullrebase(orig, ui, repo, *args, **opts):
520 'Call rebase after pull if the latter has been invoked with --rebase'
520 'Call rebase after pull if the latter has been invoked with --rebase'
521 if opts.get('rebase'):
521 if opts.get('rebase'):
522 if opts.get('update'):
522 if opts.get('update'):
523 del opts['update']
523 del opts['update']
524 ui.debug('--update and --rebase are not compatible, ignoring '
524 ui.debug('--update and --rebase are not compatible, ignoring '
525 'the update flag\n')
525 'the update flag\n')
526
526
527 cmdutil.bail_if_changed(repo)
527 cmdutil.bail_if_changed(repo)
528 revsprepull = len(repo)
528 revsprepull = len(repo)
529 origpostincoming = commands.postincoming
529 origpostincoming = commands.postincoming
530 def _dummy(*args, **kwargs):
530 def _dummy(*args, **kwargs):
531 pass
531 pass
532 commands.postincoming = _dummy
532 commands.postincoming = _dummy
533 try:
533 try:
534 orig(ui, repo, *args, **opts)
534 orig(ui, repo, *args, **opts)
535 finally:
535 finally:
536 commands.postincoming = origpostincoming
536 commands.postincoming = origpostincoming
537 revspostpull = len(repo)
537 revspostpull = len(repo)
538 if revspostpull > revsprepull:
538 if revspostpull > revsprepull:
539 rebase(ui, repo, **opts)
539 rebase(ui, repo, **opts)
540 branch = repo[None].branch()
540 branch = repo[None].branch()
541 dest = repo[branch].rev()
541 dest = repo[branch].rev()
542 if dest != repo['.'].rev():
542 if dest != repo['.'].rev():
543 # there was nothing to rebase we force an update
543 # there was nothing to rebase we force an update
544 hg.update(repo, dest)
544 hg.update(repo, dest)
545 else:
545 else:
546 orig(ui, repo, *args, **opts)
546 orig(ui, repo, *args, **opts)
547
547
548 def uisetup(ui):
548 def uisetup(ui):
549 'Replace pull with a decorator to provide --rebase option'
549 'Replace pull with a decorator to provide --rebase option'
550 entry = extensions.wrapcommand(commands.table, 'pull', pullrebase)
550 entry = extensions.wrapcommand(commands.table, 'pull', pullrebase)
551 entry[1].append(('', 'rebase', None,
551 entry[1].append(('', 'rebase', None,
552 _("rebase working directory to branch head"))
552 _("rebase working directory to branch head"))
553 )
553 )
554
554
555 cmdtable = {
555 cmdtable = {
556 "rebase":
556 "rebase":
557 (rebase,
557 (rebase,
558 [
558 [
559 ('s', 'source', '',
559 ('s', 'source', '',
560 _('rebase from the specified changeset'), _('REV')),
560 _('rebase from the specified changeset'), _('REV')),
561 ('b', 'base', '',
561 ('b', 'base', '',
562 _('rebase from the base of the specified changeset '
562 _('rebase from the base of the specified changeset '
563 '(up to greatest common ancestor of base and dest)'),
563 '(up to greatest common ancestor of base and dest)'),
564 _('REV')),
564 _('REV')),
565 ('d', 'dest', '',
565 ('d', 'dest', '',
566 _('rebase onto the specified changeset'), _('REV')),
566 _('rebase onto the specified changeset'), _('REV')),
567 ('', 'collapse', False, _('collapse the rebased changesets')),
567 ('', 'collapse', False, _('collapse the rebased changesets')),
568 ('', 'keep', False, _('keep original changesets')),
568 ('', 'keep', False, _('keep original changesets')),
569 ('', 'keepbranches', False, _('keep original branch names')),
569 ('', 'keepbranches', False, _('keep original branch names')),
570 ('', 'detach', False, _('force detaching of source from its original '
570 ('', 'detach', False, _('force detaching of source from its original '
571 'branch')),
571 'branch')),
572 ('c', 'continue', False, _('continue an interrupted rebase')),
572 ('c', 'continue', False, _('continue an interrupted rebase')),
573 ('a', 'abort', False, _('abort an interrupted rebase'))] +
573 ('a', 'abort', False, _('abort an interrupted rebase'))] +
574 templateopts,
574 templateopts,
575 _('hg rebase [-s REV | -b REV] [-d REV] [options]\n'
575 _('hg rebase [-s REV | -b REV] [-d REV] [options]\n'
576 'hg rebase {-a|-c}'))
576 'hg rebase {-a|-c}'))
577 }
577 }
@@ -1,148 +1,148 b''
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [extensions]
2 > [extensions]
3 > graphlog=
3 > graphlog=
4 > rebase=
4 > rebase=
5 >
5 >
6 > [alias]
6 > [alias]
7 > tglog = log -G --template "{rev}: '{desc}' {branches}\n"
7 > tglog = log -G --template "{rev}: '{desc}' {branches}\n"
8 > EOF
8 > EOF
9
9
10
10
11 $ hg init a
11 $ hg init a
12 $ cd a
12 $ cd a
13
13
14 $ echo c1 > common
14 $ echo c1 > common
15 $ hg add common
15 $ hg add common
16 $ hg ci -m C1
16 $ hg ci -m C1
17
17
18 $ echo c2 >> common
18 $ echo c2 >> common
19 $ hg ci -m C2
19 $ hg ci -m C2
20
20
21 $ echo c3 >> common
21 $ echo c3 >> common
22 $ hg ci -m C3
22 $ hg ci -m C3
23
23
24 $ hg up -q -C 1
24 $ hg up -q -C 1
25
25
26 $ echo l1 >> extra
26 $ echo l1 >> extra
27 $ hg add extra
27 $ hg add extra
28 $ hg ci -m L1
28 $ hg ci -m L1
29 created new head
29 created new head
30
30
31 $ sed -e 's/c2/l2/' common > common.new
31 $ sed -e 's/c2/l2/' common > common.new
32 $ mv common.new common
32 $ mv common.new common
33 $ hg ci -m L2
33 $ hg ci -m L2
34
34
35 $ hg tglog
35 $ hg tglog
36 @ 4: 'L2'
36 @ 4: 'L2'
37 |
37 |
38 o 3: 'L1'
38 o 3: 'L1'
39 |
39 |
40 | o 2: 'C3'
40 | o 2: 'C3'
41 |/
41 |/
42 o 1: 'C2'
42 o 1: 'C2'
43 |
43 |
44 o 0: 'C1'
44 o 0: 'C1'
45
45
46
46
47 Conflicting rebase:
47 Conflicting rebase:
48
48
49 $ hg rebase -s 3 -d 2
49 $ hg rebase -s 3 -d 2
50 merging common
50 merging common
51 warning: conflicts during merge.
51 warning: conflicts during merge.
52 merging common failed!
52 merging common failed!
53 abort: fix unresolved conflicts with hg resolve then run hg rebase --continue
53 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
54 [255]
54 [255]
55
55
56 Abort:
56 Abort:
57
57
58 $ hg rebase --abort
58 $ hg rebase --abort
59 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
59 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
60 rebase aborted
60 rebase aborted
61
61
62 $ hg tglog
62 $ hg tglog
63 @ 4: 'L2'
63 @ 4: 'L2'
64 |
64 |
65 o 3: 'L1'
65 o 3: 'L1'
66 |
66 |
67 | o 2: 'C3'
67 | o 2: 'C3'
68 |/
68 |/
69 o 1: 'C2'
69 o 1: 'C2'
70 |
70 |
71 o 0: 'C1'
71 o 0: 'C1'
72
72
73 $ cd ..
73 $ cd ..
74
74
75
75
76 Constrcut new repo:
76 Constrcut new repo:
77
77
78 $ hg init b
78 $ hg init b
79 $ cd b
79 $ cd b
80
80
81 $ echo a > a
81 $ echo a > a
82 $ hg ci -Am A
82 $ hg ci -Am A
83 adding a
83 adding a
84
84
85 $ echo b > b
85 $ echo b > b
86 $ hg ci -Am B
86 $ hg ci -Am B
87 adding b
87 adding b
88
88
89 $ echo c > c
89 $ echo c > c
90 $ hg ci -Am C
90 $ hg ci -Am C
91 adding c
91 adding c
92
92
93 $ hg up -q 0
93 $ hg up -q 0
94
94
95 $ echo b > b
95 $ echo b > b
96 $ hg ci -Am 'B bis'
96 $ hg ci -Am 'B bis'
97 adding b
97 adding b
98 created new head
98 created new head
99
99
100 $ echo c1 > c
100 $ echo c1 > c
101 $ hg ci -Am C1
101 $ hg ci -Am C1
102 adding c
102 adding c
103
103
104 Rebase and abort without generating new changesets:
104 Rebase and abort without generating new changesets:
105
105
106 $ hg tglog
106 $ hg tglog
107 @ 4: 'C1'
107 @ 4: 'C1'
108 |
108 |
109 o 3: 'B bis'
109 o 3: 'B bis'
110 |
110 |
111 | o 2: 'C'
111 | o 2: 'C'
112 | |
112 | |
113 | o 1: 'B'
113 | o 1: 'B'
114 |/
114 |/
115 o 0: 'A'
115 o 0: 'A'
116
116
117 $ hg rebase -b 4 -d 2
117 $ hg rebase -b 4 -d 2
118 merging c
118 merging c
119 warning: conflicts during merge.
119 warning: conflicts during merge.
120 merging c failed!
120 merging c failed!
121 abort: fix unresolved conflicts with hg resolve then run hg rebase --continue
121 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
122 [255]
122 [255]
123
123
124 $ hg tglog
124 $ hg tglog
125 @ 4: 'C1'
125 @ 4: 'C1'
126 |
126 |
127 o 3: 'B bis'
127 o 3: 'B bis'
128 |
128 |
129 | @ 2: 'C'
129 | @ 2: 'C'
130 | |
130 | |
131 | o 1: 'B'
131 | o 1: 'B'
132 |/
132 |/
133 o 0: 'A'
133 o 0: 'A'
134
134
135 $ hg rebase -a
135 $ hg rebase -a
136 rebase aborted
136 rebase aborted
137
137
138 $ hg tglog
138 $ hg tglog
139 @ 4: 'C1'
139 @ 4: 'C1'
140 |
140 |
141 o 3: 'B bis'
141 o 3: 'B bis'
142 |
142 |
143 | o 2: 'C'
143 | o 2: 'C'
144 | |
144 | |
145 | o 1: 'B'
145 | o 1: 'B'
146 |/
146 |/
147 o 0: 'A'
147 o 0: 'A'
148
148
@@ -1,142 +1,142 b''
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [extensions]
2 > [extensions]
3 > graphlog=
3 > graphlog=
4 > rebase=
4 > rebase=
5 >
5 >
6 > [alias]
6 > [alias]
7 > tglog = log -G --template "{rev}: '{desc}' {branches}\n"
7 > tglog = log -G --template "{rev}: '{desc}' {branches}\n"
8 > EOF
8 > EOF
9
9
10
10
11 $ hg init a
11 $ hg init a
12 $ cd a
12 $ cd a
13
13
14 $ echo A > A
14 $ echo A > A
15 $ hg add A
15 $ hg add A
16 $ hg ci -m A
16 $ hg ci -m A
17
17
18 $ echo 'B' > B
18 $ echo 'B' > B
19 $ hg add B
19 $ hg add B
20 $ hg ci -m B
20 $ hg ci -m B
21
21
22 $ echo C >> A
22 $ echo C >> A
23 $ hg ci -m C
23 $ hg ci -m C
24
24
25 $ hg up -q -C 0
25 $ hg up -q -C 0
26
26
27 $ echo D >> A
27 $ echo D >> A
28 $ hg ci -m D
28 $ hg ci -m D
29 created new head
29 created new head
30
30
31 $ echo E > E
31 $ echo E > E
32 $ hg add E
32 $ hg add E
33 $ hg ci -m E
33 $ hg ci -m E
34
34
35 $ hg up -q -C 0
35 $ hg up -q -C 0
36
36
37 $ hg branch 'notdefault'
37 $ hg branch 'notdefault'
38 marked working directory as branch notdefault
38 marked working directory as branch notdefault
39 $ echo F >> A
39 $ echo F >> A
40 $ hg ci -m F
40 $ hg ci -m F
41
41
42 $ cd ..
42 $ cd ..
43
43
44
44
45 Rebasing B onto E - check keep:
45 Rebasing B onto E - check keep:
46
46
47 $ hg clone -q -u . a a1
47 $ hg clone -q -u . a a1
48 $ cd a1
48 $ cd a1
49
49
50 $ hg tglog
50 $ hg tglog
51 @ 5: 'F' notdefault
51 @ 5: 'F' notdefault
52 |
52 |
53 | o 4: 'E'
53 | o 4: 'E'
54 | |
54 | |
55 | o 3: 'D'
55 | o 3: 'D'
56 |/
56 |/
57 | o 2: 'C'
57 | o 2: 'C'
58 | |
58 | |
59 | o 1: 'B'
59 | o 1: 'B'
60 |/
60 |/
61 o 0: 'A'
61 o 0: 'A'
62
62
63 $ hg rebase -s 1 -d 4 --keep
63 $ hg rebase -s 1 -d 4 --keep
64 merging A
64 merging A
65 warning: conflicts during merge.
65 warning: conflicts during merge.
66 merging A failed!
66 merging A failed!
67 abort: fix unresolved conflicts with hg resolve then run hg rebase --continue
67 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
68 [255]
68 [255]
69
69
70 Solve the conflict and go on:
70 Solve the conflict and go on:
71
71
72 $ echo 'conflict solved' > A
72 $ echo 'conflict solved' > A
73 $ rm A.orig
73 $ rm A.orig
74 $ hg resolve -m A
74 $ hg resolve -m A
75 $ hg rebase --continue
75 $ hg rebase --continue
76
76
77 $ hg tglog
77 $ hg tglog
78 @ 7: 'C'
78 @ 7: 'C'
79 |
79 |
80 o 6: 'B'
80 o 6: 'B'
81 |
81 |
82 | o 5: 'F' notdefault
82 | o 5: 'F' notdefault
83 | |
83 | |
84 o | 4: 'E'
84 o | 4: 'E'
85 | |
85 | |
86 o | 3: 'D'
86 o | 3: 'D'
87 |/
87 |/
88 | o 2: 'C'
88 | o 2: 'C'
89 | |
89 | |
90 | o 1: 'B'
90 | o 1: 'B'
91 |/
91 |/
92 o 0: 'A'
92 o 0: 'A'
93
93
94 $ cd ..
94 $ cd ..
95
95
96
96
97 Rebase F onto E - check keepbranches:
97 Rebase F onto E - check keepbranches:
98
98
99 $ hg clone -q -u . a a2
99 $ hg clone -q -u . a a2
100 $ cd a2
100 $ cd a2
101
101
102 $ hg tglog
102 $ hg tglog
103 @ 5: 'F' notdefault
103 @ 5: 'F' notdefault
104 |
104 |
105 | o 4: 'E'
105 | o 4: 'E'
106 | |
106 | |
107 | o 3: 'D'
107 | o 3: 'D'
108 |/
108 |/
109 | o 2: 'C'
109 | o 2: 'C'
110 | |
110 | |
111 | o 1: 'B'
111 | o 1: 'B'
112 |/
112 |/
113 o 0: 'A'
113 o 0: 'A'
114
114
115 $ hg rebase -s 5 -d 4 --keepbranches
115 $ hg rebase -s 5 -d 4 --keepbranches
116 merging A
116 merging A
117 warning: conflicts during merge.
117 warning: conflicts during merge.
118 merging A failed!
118 merging A failed!
119 abort: fix unresolved conflicts with hg resolve then run hg rebase --continue
119 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
120 [255]
120 [255]
121
121
122 Solve the conflict and go on:
122 Solve the conflict and go on:
123
123
124 $ echo 'conflict solved' > A
124 $ echo 'conflict solved' > A
125 $ rm A.orig
125 $ rm A.orig
126 $ hg resolve -m A
126 $ hg resolve -m A
127 $ hg rebase --continue
127 $ hg rebase --continue
128 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/*-backup.hg (glob)
128 saved backup bundle to $TESTTMP/a2/.hg/strip-backup/*-backup.hg (glob)
129
129
130 $ hg tglog
130 $ hg tglog
131 @ 5: 'F' notdefault
131 @ 5: 'F' notdefault
132 |
132 |
133 o 4: 'E'
133 o 4: 'E'
134 |
134 |
135 o 3: 'D'
135 o 3: 'D'
136 |
136 |
137 | o 2: 'C'
137 | o 2: 'C'
138 | |
138 | |
139 | o 1: 'B'
139 | o 1: 'B'
140 |/
140 |/
141 o 0: 'A'
141 o 0: 'A'
142
142
@@ -1,115 +1,115 b''
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [extensions]
2 > [extensions]
3 > graphlog=
3 > graphlog=
4 > rebase=
4 > rebase=
5 >
5 >
6 > [alias]
6 > [alias]
7 > tglog = log -G --template "{rev}: '{desc}' {branches}\n"
7 > tglog = log -G --template "{rev}: '{desc}' {branches}\n"
8 > EOF
8 > EOF
9
9
10 $ hg init a
10 $ hg init a
11 $ cd a
11 $ cd a
12 $ echo c1 >common
12 $ echo c1 >common
13 $ hg add common
13 $ hg add common
14 $ hg ci -m C1
14 $ hg ci -m C1
15
15
16 $ echo c2 >>common
16 $ echo c2 >>common
17 $ hg ci -m C2
17 $ hg ci -m C2
18
18
19 $ echo c3 >>common
19 $ echo c3 >>common
20 $ hg ci -m C3
20 $ hg ci -m C3
21
21
22 $ hg up -q -C 1
22 $ hg up -q -C 1
23
23
24 $ echo l1 >>extra
24 $ echo l1 >>extra
25 $ hg add extra
25 $ hg add extra
26 $ hg ci -m L1
26 $ hg ci -m L1
27 created new head
27 created new head
28
28
29 $ sed -e 's/c2/l2/' common > common.new
29 $ sed -e 's/c2/l2/' common > common.new
30 $ mv common.new common
30 $ mv common.new common
31 $ hg ci -m L2
31 $ hg ci -m L2
32
32
33 $ echo l3 >> extra2
33 $ echo l3 >> extra2
34 $ hg add extra2
34 $ hg add extra2
35 $ hg ci -m L3
35 $ hg ci -m L3
36
36
37 $ hg tglog
37 $ hg tglog
38 @ 5: 'L3'
38 @ 5: 'L3'
39 |
39 |
40 o 4: 'L2'
40 o 4: 'L2'
41 |
41 |
42 o 3: 'L1'
42 o 3: 'L1'
43 |
43 |
44 | o 2: 'C3'
44 | o 2: 'C3'
45 |/
45 |/
46 o 1: 'C2'
46 o 1: 'C2'
47 |
47 |
48 o 0: 'C1'
48 o 0: 'C1'
49
49
50 Try to call --continue:
50 Try to call --continue:
51
51
52 $ hg rebase --continue
52 $ hg rebase --continue
53 abort: no rebase in progress
53 abort: no rebase in progress
54 [255]
54 [255]
55
55
56 Conflicting rebase:
56 Conflicting rebase:
57
57
58 $ hg rebase -s 3 -d 2
58 $ hg rebase -s 3 -d 2
59 merging common
59 merging common
60 warning: conflicts during merge.
60 warning: conflicts during merge.
61 merging common failed!
61 merging common failed!
62 abort: fix unresolved conflicts with hg resolve then run hg rebase --continue
62 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
63 [255]
63 [255]
64
64
65 Try to continue without solving the conflict:
65 Try to continue without solving the conflict:
66
66
67 $ hg rebase --continue
67 $ hg rebase --continue
68 abort: unresolved merge conflicts (see hg resolve)
68 abort: unresolved merge conflicts (see hg resolve)
69 [255]
69 [255]
70
70
71 Conclude rebase:
71 Conclude rebase:
72
72
73 $ echo 'resolved merge' >common
73 $ echo 'resolved merge' >common
74 $ hg resolve -m common
74 $ hg resolve -m common
75 $ hg rebase --continue
75 $ hg rebase --continue
76 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
76 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
77
77
78 $ hg tglog
78 $ hg tglog
79 @ 5: 'L3'
79 @ 5: 'L3'
80 |
80 |
81 o 4: 'L2'
81 o 4: 'L2'
82 |
82 |
83 o 3: 'L1'
83 o 3: 'L1'
84 |
84 |
85 o 2: 'C3'
85 o 2: 'C3'
86 |
86 |
87 o 1: 'C2'
87 o 1: 'C2'
88 |
88 |
89 o 0: 'C1'
89 o 0: 'C1'
90
90
91 Check correctness:
91 Check correctness:
92
92
93 $ hg cat -r 0 common
93 $ hg cat -r 0 common
94 c1
94 c1
95
95
96 $ hg cat -r 1 common
96 $ hg cat -r 1 common
97 c1
97 c1
98 c2
98 c2
99
99
100 $ hg cat -r 2 common
100 $ hg cat -r 2 common
101 c1
101 c1
102 c2
102 c2
103 c3
103 c3
104
104
105 $ hg cat -r 3 common
105 $ hg cat -r 3 common
106 c1
106 c1
107 c2
107 c2
108 c3
108 c3
109
109
110 $ hg cat -r 4 common
110 $ hg cat -r 4 common
111 resolved merge
111 resolved merge
112
112
113 $ hg cat -r 5 common
113 $ hg cat -r 5 common
114 resolved merge
114 resolved merge
115
115
@@ -1,194 +1,194 b''
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [extensions]
2 > [extensions]
3 > graphlog=
3 > graphlog=
4 > rebase=
4 > rebase=
5 >
5 >
6 > [alias]
6 > [alias]
7 > tglog = log -G --template "{rev}: '{desc}' {branches}\n"
7 > tglog = log -G --template "{rev}: '{desc}' {branches}\n"
8 > EOF
8 > EOF
9
9
10
10
11 $ hg init a
11 $ hg init a
12 $ cd a
12 $ cd a
13
13
14 $ echo A > A
14 $ echo A > A
15 $ hg ci -Am A
15 $ hg ci -Am A
16 adding A
16 adding A
17
17
18 $ echo B > B
18 $ echo B > B
19 $ hg ci -Am B
19 $ hg ci -Am B
20 adding B
20 adding B
21
21
22 $ echo C >> A
22 $ echo C >> A
23 $ hg ci -m C
23 $ hg ci -m C
24
24
25 $ hg up -q -C 0
25 $ hg up -q -C 0
26
26
27 $ echo D >> A
27 $ echo D >> A
28 $ hg ci -m D
28 $ hg ci -m D
29 created new head
29 created new head
30
30
31 $ echo E > E
31 $ echo E > E
32 $ hg ci -Am E
32 $ hg ci -Am E
33 adding E
33 adding E
34
34
35 $ cd ..
35 $ cd ..
36
36
37
37
38 Changes during an interruption - continue:
38 Changes during an interruption - continue:
39
39
40 $ hg clone -q -u . a a1
40 $ hg clone -q -u . a a1
41 $ cd a1
41 $ cd a1
42
42
43 $ hg tglog
43 $ hg tglog
44 @ 4: 'E'
44 @ 4: 'E'
45 |
45 |
46 o 3: 'D'
46 o 3: 'D'
47 |
47 |
48 | o 2: 'C'
48 | o 2: 'C'
49 | |
49 | |
50 | o 1: 'B'
50 | o 1: 'B'
51 |/
51 |/
52 o 0: 'A'
52 o 0: 'A'
53
53
54 Rebasing B onto E:
54 Rebasing B onto E:
55
55
56 $ hg rebase -s 1 -d 4
56 $ hg rebase -s 1 -d 4
57 merging A
57 merging A
58 warning: conflicts during merge.
58 warning: conflicts during merge.
59 merging A failed!
59 merging A failed!
60 abort: fix unresolved conflicts with hg resolve then run hg rebase --continue
60 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
61 [255]
61 [255]
62
62
63 Force a commit on C during the interruption:
63 Force a commit on C during the interruption:
64
64
65 $ hg up -q -C 2
65 $ hg up -q -C 2
66
66
67 $ echo 'Extra' > Extra
67 $ echo 'Extra' > Extra
68 $ hg add Extra
68 $ hg add Extra
69 $ hg ci -m 'Extra'
69 $ hg ci -m 'Extra'
70
70
71 $ hg tglog
71 $ hg tglog
72 @ 6: 'Extra'
72 @ 6: 'Extra'
73 |
73 |
74 | o 5: 'B'
74 | o 5: 'B'
75 | |
75 | |
76 | o 4: 'E'
76 | o 4: 'E'
77 | |
77 | |
78 | o 3: 'D'
78 | o 3: 'D'
79 | |
79 | |
80 o | 2: 'C'
80 o | 2: 'C'
81 | |
81 | |
82 o | 1: 'B'
82 o | 1: 'B'
83 |/
83 |/
84 o 0: 'A'
84 o 0: 'A'
85
85
86 Resume the rebasing:
86 Resume the rebasing:
87
87
88 $ hg rebase --continue
88 $ hg rebase --continue
89 merging A
89 merging A
90 warning: conflicts during merge.
90 warning: conflicts during merge.
91 merging A failed!
91 merging A failed!
92 abort: fix unresolved conflicts with hg resolve then run hg rebase --continue
92 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
93 [255]
93 [255]
94
94
95 Solve the conflict and go on:
95 Solve the conflict and go on:
96
96
97 $ echo 'conflict solved' > A
97 $ echo 'conflict solved' > A
98 $ rm A.orig
98 $ rm A.orig
99 $ hg resolve -m A
99 $ hg resolve -m A
100
100
101 $ hg rebase --continue
101 $ hg rebase --continue
102 warning: new changesets detected on source branch, not stripping
102 warning: new changesets detected on source branch, not stripping
103
103
104 $ hg tglog
104 $ hg tglog
105 @ 7: 'C'
105 @ 7: 'C'
106 |
106 |
107 | o 6: 'Extra'
107 | o 6: 'Extra'
108 | |
108 | |
109 o | 5: 'B'
109 o | 5: 'B'
110 | |
110 | |
111 o | 4: 'E'
111 o | 4: 'E'
112 | |
112 | |
113 o | 3: 'D'
113 o | 3: 'D'
114 | |
114 | |
115 | o 2: 'C'
115 | o 2: 'C'
116 | |
116 | |
117 | o 1: 'B'
117 | o 1: 'B'
118 |/
118 |/
119 o 0: 'A'
119 o 0: 'A'
120
120
121 $ cd ..
121 $ cd ..
122
122
123
123
124 Changes during an interruption - abort:
124 Changes during an interruption - abort:
125
125
126 $ hg clone -q -u . a a2
126 $ hg clone -q -u . a a2
127 $ cd a2
127 $ cd a2
128
128
129 $ hg tglog
129 $ hg tglog
130 @ 4: 'E'
130 @ 4: 'E'
131 |
131 |
132 o 3: 'D'
132 o 3: 'D'
133 |
133 |
134 | o 2: 'C'
134 | o 2: 'C'
135 | |
135 | |
136 | o 1: 'B'
136 | o 1: 'B'
137 |/
137 |/
138 o 0: 'A'
138 o 0: 'A'
139
139
140 Rebasing B onto E:
140 Rebasing B onto E:
141
141
142 $ hg rebase -s 1 -d 4
142 $ hg rebase -s 1 -d 4
143 merging A
143 merging A
144 warning: conflicts during merge.
144 warning: conflicts during merge.
145 merging A failed!
145 merging A failed!
146 abort: fix unresolved conflicts with hg resolve then run hg rebase --continue
146 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
147 [255]
147 [255]
148
148
149 Force a commit on B' during the interruption:
149 Force a commit on B' during the interruption:
150
150
151 $ hg up -q -C 5
151 $ hg up -q -C 5
152
152
153 $ echo 'Extra' > Extra
153 $ echo 'Extra' > Extra
154 $ hg add Extra
154 $ hg add Extra
155 $ hg ci -m 'Extra'
155 $ hg ci -m 'Extra'
156
156
157 $ hg tglog
157 $ hg tglog
158 @ 6: 'Extra'
158 @ 6: 'Extra'
159 |
159 |
160 o 5: 'B'
160 o 5: 'B'
161 |
161 |
162 o 4: 'E'
162 o 4: 'E'
163 |
163 |
164 o 3: 'D'
164 o 3: 'D'
165 |
165 |
166 | o 2: 'C'
166 | o 2: 'C'
167 | |
167 | |
168 | o 1: 'B'
168 | o 1: 'B'
169 |/
169 |/
170 o 0: 'A'
170 o 0: 'A'
171
171
172 Abort the rebasing:
172 Abort the rebasing:
173
173
174 $ hg rebase --abort
174 $ hg rebase --abort
175 warning: new changesets detected on target branch, can't abort
175 warning: new changesets detected on target branch, can't abort
176 [255]
176 [255]
177
177
178 $ hg tglog
178 $ hg tglog
179 @ 6: 'Extra'
179 @ 6: 'Extra'
180 |
180 |
181 o 5: 'B'
181 o 5: 'B'
182 |
182 |
183 o 4: 'E'
183 o 4: 'E'
184 |
184 |
185 o 3: 'D'
185 o 3: 'D'
186 |
186 |
187 | o 2: 'C'
187 | o 2: 'C'
188 | |
188 | |
189 | o 1: 'B'
189 | o 1: 'B'
190 |/
190 |/
191 o 0: 'A'
191 o 0: 'A'
192
192
193 $ cd ..
193 $ cd ..
194
194
@@ -1,136 +1,136 b''
1 This emulates the effects of an hg pull --rebase in which the remote repo
1 This emulates the effects of an hg pull --rebase in which the remote repo
2 already has one local mq patch
2 already has one local mq patch
3
3
4 $ cat >> $HGRCPATH <<EOF
4 $ cat >> $HGRCPATH <<EOF
5 > [extensions]
5 > [extensions]
6 > graphlog=
6 > graphlog=
7 > rebase=
7 > rebase=
8 > mq=
8 > mq=
9 >
9 >
10 > [alias]
10 > [alias]
11 > tglog = log -G --template "{rev}: '{desc}' tags: {tags}\n"
11 > tglog = log -G --template "{rev}: '{desc}' tags: {tags}\n"
12 > EOF
12 > EOF
13
13
14
14
15 $ hg init a
15 $ hg init a
16 $ cd a
16 $ cd a
17 $ hg qinit -c
17 $ hg qinit -c
18
18
19 $ echo c1 > c1
19 $ echo c1 > c1
20 $ hg add c1
20 $ hg add c1
21 $ hg ci -m C1
21 $ hg ci -m C1
22
22
23 $ echo r1 > r1
23 $ echo r1 > r1
24 $ hg add r1
24 $ hg add r1
25 $ hg ci -m R1
25 $ hg ci -m R1
26
26
27 $ hg up -q 0
27 $ hg up -q 0
28
28
29 $ hg qnew p0.patch
29 $ hg qnew p0.patch
30 $ echo p0 > p0
30 $ echo p0 > p0
31 $ hg add p0
31 $ hg add p0
32 $ hg qref -m P0
32 $ hg qref -m P0
33
33
34 $ hg qnew p1.patch
34 $ hg qnew p1.patch
35 $ echo p1 > p1
35 $ echo p1 > p1
36 $ hg add p1
36 $ hg add p1
37 $ hg qref -m P1
37 $ hg qref -m P1
38
38
39 $ hg export qtip > p1.patch
39 $ hg export qtip > p1.patch
40
40
41 $ hg up -q -C 1
41 $ hg up -q -C 1
42
42
43 $ hg import p1.patch
43 $ hg import p1.patch
44 applying p1.patch
44 applying p1.patch
45
45
46 $ rm p1.patch
46 $ rm p1.patch
47
47
48 $ hg up -q -C qtip
48 $ hg up -q -C qtip
49
49
50 $ hg rebase
50 $ hg rebase
51 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
51 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
52
52
53 $ hg tglog
53 $ hg tglog
54 @ 3: 'P0' tags: p0.patch qbase qtip tip
54 @ 3: 'P0' tags: p0.patch qbase qtip tip
55 |
55 |
56 o 2: 'P1' tags: qparent
56 o 2: 'P1' tags: qparent
57 |
57 |
58 o 1: 'R1' tags:
58 o 1: 'R1' tags:
59 |
59 |
60 o 0: 'C1' tags:
60 o 0: 'C1' tags:
61
61
62 $ cd ..
62 $ cd ..
63
63
64
64
65 $ hg init b
65 $ hg init b
66 $ cd b
66 $ cd b
67 $ hg qinit -c
67 $ hg qinit -c
68
68
69 $ for i in r0 r1 r2 r3 r4 r5 r6;
69 $ for i in r0 r1 r2 r3 r4 r5 r6;
70 > do
70 > do
71 > echo $i > $i
71 > echo $i > $i
72 > hg ci -Am $i
72 > hg ci -Am $i
73 > done
73 > done
74 adding r0
74 adding r0
75 adding r1
75 adding r1
76 adding r2
76 adding r2
77 adding r3
77 adding r3
78 adding r4
78 adding r4
79 adding r5
79 adding r5
80 adding r6
80 adding r6
81
81
82 $ hg qimport -r 1:tip
82 $ hg qimport -r 1:tip
83
83
84 $ hg up -q 0
84 $ hg up -q 0
85
85
86 $ for i in r1 r3 r7 r8;
86 $ for i in r1 r3 r7 r8;
87 > do
87 > do
88 > echo $i > $i
88 > echo $i > $i
89 > hg ci -Am branch2-$i
89 > hg ci -Am branch2-$i
90 > done
90 > done
91 adding r1
91 adding r1
92 created new head
92 created new head
93 adding r3
93 adding r3
94 adding r7
94 adding r7
95 adding r8
95 adding r8
96
96
97 $ echo somethingelse > r4
97 $ echo somethingelse > r4
98 $ hg ci -Am branch2-r4
98 $ hg ci -Am branch2-r4
99 adding r4
99 adding r4
100
100
101 $ echo r6 > r6
101 $ echo r6 > r6
102 $ hg ci -Am branch2-r6
102 $ hg ci -Am branch2-r6
103 adding r6
103 adding r6
104
104
105 $ hg up -q qtip
105 $ hg up -q qtip
106
106
107 $ HGMERGE=internal:fail hg rebase
107 $ HGMERGE=internal:fail hg rebase
108 abort: fix unresolved conflicts with hg resolve then run hg rebase --continue
108 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
109 [255]
109 [255]
110
110
111 $ HGMERGE=internal:local hg resolve --all
111 $ HGMERGE=internal:local hg resolve --all
112
112
113 $ hg rebase --continue
113 $ hg rebase --continue
114 saved backup bundle to $TESTTMP/b/.hg/strip-backup/*-backup.hg (glob)
114 saved backup bundle to $TESTTMP/b/.hg/strip-backup/*-backup.hg (glob)
115
115
116 $ hg tglog
116 $ hg tglog
117 @ 9: 'r5' tags: 5.diff qtip tip
117 @ 9: 'r5' tags: 5.diff qtip tip
118 |
118 |
119 o 8: 'r4' tags: 4.diff
119 o 8: 'r4' tags: 4.diff
120 |
120 |
121 o 7: 'r2' tags: 2.diff qbase
121 o 7: 'r2' tags: 2.diff qbase
122 |
122 |
123 o 6: 'branch2-r6' tags: qparent
123 o 6: 'branch2-r6' tags: qparent
124 |
124 |
125 o 5: 'branch2-r4' tags:
125 o 5: 'branch2-r4' tags:
126 |
126 |
127 o 4: 'branch2-r8' tags:
127 o 4: 'branch2-r8' tags:
128 |
128 |
129 o 3: 'branch2-r7' tags:
129 o 3: 'branch2-r7' tags:
130 |
130 |
131 o 2: 'branch2-r3' tags:
131 o 2: 'branch2-r3' tags:
132 |
132 |
133 o 1: 'branch2-r1' tags:
133 o 1: 'branch2-r1' tags:
134 |
134 |
135 o 0: 'r0' tags:
135 o 0: 'r0' tags:
136
136
@@ -1,237 +1,237 b''
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [extensions]
2 > [extensions]
3 > graphlog=
3 > graphlog=
4 > rebase=
4 > rebase=
5 > mq=
5 > mq=
6 >
6 >
7 > [mq]
7 > [mq]
8 > plain=true
8 > plain=true
9 >
9 >
10 > [alias]
10 > [alias]
11 > tglog = log -G --template "{rev}: '{desc}' tags: {tags}\n"
11 > tglog = log -G --template "{rev}: '{desc}' tags: {tags}\n"
12 > EOF
12 > EOF
13
13
14
14
15 $ hg init a
15 $ hg init a
16 $ cd a
16 $ cd a
17 $ hg qinit -c
17 $ hg qinit -c
18
18
19 $ echo c1 > f
19 $ echo c1 > f
20 $ hg add f
20 $ hg add f
21 $ hg ci -m C1
21 $ hg ci -m C1
22
22
23 $ echo r1 > f
23 $ echo r1 > f
24 $ hg ci -m R1
24 $ hg ci -m R1
25
25
26 $ hg up -q 0
26 $ hg up -q 0
27
27
28 $ hg qnew f.patch
28 $ hg qnew f.patch
29 $ echo mq1 > f
29 $ echo mq1 > f
30 $ hg qref -m P0
30 $ hg qref -m P0
31
31
32 $ hg qnew f2.patch
32 $ hg qnew f2.patch
33 $ echo mq2 > f
33 $ echo mq2 > f
34 $ hg qref -m P1
34 $ hg qref -m P1
35
35
36 $ hg tglog
36 $ hg tglog
37 @ 3: 'P1' tags: f2.patch qtip tip
37 @ 3: 'P1' tags: f2.patch qtip tip
38 |
38 |
39 o 2: 'P0' tags: f.patch qbase
39 o 2: 'P0' tags: f.patch qbase
40 |
40 |
41 | o 1: 'R1' tags:
41 | o 1: 'R1' tags:
42 |/
42 |/
43 o 0: 'C1' tags: qparent
43 o 0: 'C1' tags: qparent
44
44
45
45
46 Rebase - try to rebase on an applied mq patch:
46 Rebase - try to rebase on an applied mq patch:
47
47
48 $ hg rebase -s 1 -d 3
48 $ hg rebase -s 1 -d 3
49 abort: cannot rebase onto an applied mq patch
49 abort: cannot rebase onto an applied mq patch
50 [255]
50 [255]
51
51
52 Rebase - same thing, but mq patch is default dest:
52 Rebase - same thing, but mq patch is default dest:
53
53
54 $ hg up -q 1
54 $ hg up -q 1
55 $ hg rebase
55 $ hg rebase
56 abort: cannot rebase onto an applied mq patch
56 abort: cannot rebase onto an applied mq patch
57 [255]
57 [255]
58 $ hg up -q qtip
58 $ hg up -q qtip
59
59
60 Rebase - generate a conflict:
60 Rebase - generate a conflict:
61
61
62 $ hg rebase -s 2 -d 1
62 $ hg rebase -s 2 -d 1
63 merging f
63 merging f
64 warning: conflicts during merge.
64 warning: conflicts during merge.
65 merging f failed!
65 merging f failed!
66 abort: fix unresolved conflicts with hg resolve then run hg rebase --continue
66 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
67 [255]
67 [255]
68
68
69 Fix the 1st conflict:
69 Fix the 1st conflict:
70
70
71 $ echo mq1r1 > f
71 $ echo mq1r1 > f
72 $ hg resolve -m f
72 $ hg resolve -m f
73 $ hg rebase -c
73 $ hg rebase -c
74 merging f
74 merging f
75 warning: conflicts during merge.
75 warning: conflicts during merge.
76 merging f failed!
76 merging f failed!
77 abort: fix unresolved conflicts with hg resolve then run hg rebase --continue
77 abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
78 [255]
78 [255]
79
79
80 Fix the 2nd conflict:
80 Fix the 2nd conflict:
81
81
82 $ echo mq1r1mq2 > f
82 $ echo mq1r1mq2 > f
83 $ hg resolve -m f
83 $ hg resolve -m f
84 $ hg rebase -c
84 $ hg rebase -c
85 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
85 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
86
86
87 $ hg tglog
87 $ hg tglog
88 @ 3: 'P1' tags: f2.patch qtip tip
88 @ 3: 'P1' tags: f2.patch qtip tip
89 |
89 |
90 o 2: 'P0' tags: f.patch qbase
90 o 2: 'P0' tags: f.patch qbase
91 |
91 |
92 o 1: 'R1' tags: qparent
92 o 1: 'R1' tags: qparent
93 |
93 |
94 o 0: 'C1' tags:
94 o 0: 'C1' tags:
95
95
96 $ hg up -q qbase
96 $ hg up -q qbase
97
97
98 $ cat f
98 $ cat f
99 mq1r1
99 mq1r1
100
100
101 $ cat .hg/patches/f.patch
101 $ cat .hg/patches/f.patch
102 # HG changeset patch
102 # HG changeset patch
103 # User test
103 # User test
104 # Date ?????????? ? (glob)
104 # Date ?????????? ? (glob)
105 # Node ID ???????????????????????????????????????? (glob)
105 # Node ID ???????????????????????????????????????? (glob)
106 # Parent bac9ed9960d8992bcad75864a879fa76cadaf1b0
106 # Parent bac9ed9960d8992bcad75864a879fa76cadaf1b0
107 P0
107 P0
108
108
109 diff -r bac9ed9960d8 -r ???????????? f (glob)
109 diff -r bac9ed9960d8 -r ???????????? f (glob)
110 --- a/f Thu Jan 01 00:00:00 1970 +0000
110 --- a/f Thu Jan 01 00:00:00 1970 +0000
111 +++ b/f ??? ??? ?? ??:??:?? ???? ????? (glob)
111 +++ b/f ??? ??? ?? ??:??:?? ???? ????? (glob)
112 @@ -1,1 +1,1 @@
112 @@ -1,1 +1,1 @@
113 -r1
113 -r1
114 +mq1r1
114 +mq1r1
115
115
116 Update to qtip:
116 Update to qtip:
117
117
118 $ hg up -q qtip
118 $ hg up -q qtip
119
119
120 $ cat f
120 $ cat f
121 mq1r1mq2
121 mq1r1mq2
122
122
123 $ cat .hg/patches/f2.patch
123 $ cat .hg/patches/f2.patch
124 # HG changeset patch
124 # HG changeset patch
125 # User test
125 # User test
126 # Date ?????????? ? (glob)
126 # Date ?????????? ? (glob)
127 # Node ID ???????????????????????????????????????? (glob)
127 # Node ID ???????????????????????????????????????? (glob)
128 # Parent ???????????????????????????????????????? (glob)
128 # Parent ???????????????????????????????????????? (glob)
129 P1
129 P1
130
130
131 diff -r ???????????? -r ???????????? f (glob)
131 diff -r ???????????? -r ???????????? f (glob)
132 --- a/f ??? ??? ?? ??:??:?? ???? ????? (glob)
132 --- a/f ??? ??? ?? ??:??:?? ???? ????? (glob)
133 +++ b/f ??? ??? ?? ??:??:?? ???? ????? (glob)
133 +++ b/f ??? ??? ?? ??:??:?? ???? ????? (glob)
134 @@ -1,1 +1,1 @@
134 @@ -1,1 +1,1 @@
135 -mq1r1
135 -mq1r1
136 +mq1r1mq2
136 +mq1r1mq2
137
137
138 Adding one git-style patch and one normal:
138 Adding one git-style patch and one normal:
139
139
140 $ hg qpop -a
140 $ hg qpop -a
141 popping f2.patch
141 popping f2.patch
142 popping f.patch
142 popping f.patch
143 patch queue now empty
143 patch queue now empty
144
144
145 $ rm -fr .hg/patches
145 $ rm -fr .hg/patches
146 $ hg qinit -c
146 $ hg qinit -c
147
147
148 $ hg up -q 0
148 $ hg up -q 0
149
149
150 $ hg qnew --git f_git.patch
150 $ hg qnew --git f_git.patch
151 $ echo mq1 > p
151 $ echo mq1 > p
152 $ hg add p
152 $ hg add p
153 $ hg qref --git -m 'P0 (git)'
153 $ hg qref --git -m 'P0 (git)'
154
154
155 $ hg qnew f.patch
155 $ hg qnew f.patch
156 $ echo mq2 > p
156 $ echo mq2 > p
157 $ hg qref -m P1
157 $ hg qref -m P1
158 $ hg qci -m 'save patch state'
158 $ hg qci -m 'save patch state'
159
159
160 $ hg qseries -s
160 $ hg qseries -s
161 f_git.patch: P0 (git)
161 f_git.patch: P0 (git)
162 f.patch: P1
162 f.patch: P1
163
163
164 $ hg -R .hg/patches manifest
164 $ hg -R .hg/patches manifest
165 .hgignore
165 .hgignore
166 f.patch
166 f.patch
167 f_git.patch
167 f_git.patch
168 series
168 series
169
169
170 $ cat .hg/patches/f_git.patch
170 $ cat .hg/patches/f_git.patch
171 P0 (git)
171 P0 (git)
172
172
173 diff --git a/p b/p
173 diff --git a/p b/p
174 new file mode 100644
174 new file mode 100644
175 --- /dev/null
175 --- /dev/null
176 +++ b/p
176 +++ b/p
177 @@ -0,0 +1,1 @@
177 @@ -0,0 +1,1 @@
178 +mq1
178 +mq1
179
179
180 $ cat .hg/patches/f.patch
180 $ cat .hg/patches/f.patch
181 P1
181 P1
182
182
183 diff -r ???????????? p (glob)
183 diff -r ???????????? p (glob)
184 --- a/p ??? ??? ?? ??:??:?? ???? ????? (glob)
184 --- a/p ??? ??? ?? ??:??:?? ???? ????? (glob)
185 +++ b/p ??? ??? ?? ??:??:?? ???? ????? (glob)
185 +++ b/p ??? ??? ?? ??:??:?? ???? ????? (glob)
186 @@ -1,1 +1,1 @@
186 @@ -1,1 +1,1 @@
187 -mq1
187 -mq1
188 +mq2
188 +mq2
189
189
190
190
191 Rebase the applied mq patches:
191 Rebase the applied mq patches:
192
192
193 $ hg rebase -s 2 -d 1
193 $ hg rebase -s 2 -d 1
194 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
194 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
195
195
196 $ hg qci -m 'save patch state'
196 $ hg qci -m 'save patch state'
197
197
198 $ hg qseries -s
198 $ hg qseries -s
199 f_git.patch: P0 (git)
199 f_git.patch: P0 (git)
200 f.patch: P1
200 f.patch: P1
201
201
202 $ hg -R .hg/patches manifest
202 $ hg -R .hg/patches manifest
203 .hgignore
203 .hgignore
204 f.patch
204 f.patch
205 f_git.patch
205 f_git.patch
206 series
206 series
207
207
208 $ cat .hg/patches/f_git.patch
208 $ cat .hg/patches/f_git.patch
209 # HG changeset patch
209 # HG changeset patch
210 # User test
210 # User test
211 # Date ?????????? ? (glob)
211 # Date ?????????? ? (glob)
212 # Node ID ???????????????????????????????????????? (glob)
212 # Node ID ???????????????????????????????????????? (glob)
213 # Parent bac9ed9960d8992bcad75864a879fa76cadaf1b0
213 # Parent bac9ed9960d8992bcad75864a879fa76cadaf1b0
214 P0 (git)
214 P0 (git)
215
215
216 diff --git a/p b/p
216 diff --git a/p b/p
217 new file mode 100644
217 new file mode 100644
218 --- /dev/null
218 --- /dev/null
219 +++ b/p
219 +++ b/p
220 @@ -0,0 +1,1 @@
220 @@ -0,0 +1,1 @@
221 +mq1
221 +mq1
222
222
223 $ cat .hg/patches/f.patch
223 $ cat .hg/patches/f.patch
224 # HG changeset patch
224 # HG changeset patch
225 # User test
225 # User test
226 # Date ?????????? ? (glob)
226 # Date ?????????? ? (glob)
227 # Node ID ???????????????????????????????????????? (glob)
227 # Node ID ???????????????????????????????????????? (glob)
228 # Parent ???????????????????????????????????????? (glob)
228 # Parent ???????????????????????????????????????? (glob)
229 P1
229 P1
230
230
231 diff -r ???????????? -r ???????????? p (glob)
231 diff -r ???????????? -r ???????????? p (glob)
232 --- a/p ??? ??? ?? ??:??:?? ???? ????? (glob)
232 --- a/p ??? ??? ?? ??:??:?? ???? ????? (glob)
233 +++ b/p ??? ??? ?? ??:??:?? ???? ????? (glob)
233 +++ b/p ??? ??? ?? ??:??:?? ???? ????? (glob)
234 @@ -1,1 +1,1 @@
234 @@ -1,1 +1,1 @@
235 -mq1
235 -mq1
236 +mq2
236 +mq2
237
237
General Comments 0
You need to be logged in to leave comments. Login now