Show More
@@ -0,0 +1,68 b'' | |||
|
1 | #!/bin/sh | |
|
2 | ||
|
3 | echo "[extensions]" >> $HGRCPATH | |
|
4 | echo "graphlog=" >> $HGRCPATH | |
|
5 | echo "rebase=" >> $HGRCPATH | |
|
6 | ||
|
7 | BASE=`pwd` | |
|
8 | ||
|
9 | addcommit () { | |
|
10 | echo $1 > $1 | |
|
11 | hg add $1 | |
|
12 | hg commit -d "${2} 0" -m $1 | |
|
13 | } | |
|
14 | ||
|
15 | commit () { | |
|
16 | hg commit -d "${2} 0" -m $1 | |
|
17 | } | |
|
18 | ||
|
19 | createrepo () { | |
|
20 | cd $BASE | |
|
21 | rm -rf a | |
|
22 | hg init a | |
|
23 | cd a | |
|
24 | addcommit "A" 0 | |
|
25 | addcommit "B" 1 | |
|
26 | addcommit "C" 2 | |
|
27 | addcommit "D" 3 | |
|
28 | ||
|
29 | hg update -C 0 | |
|
30 | addcommit "E" 4 | |
|
31 | } | |
|
32 | ||
|
33 | createrepo > /dev/null 2>&1 | |
|
34 | hg glog --template '{rev}: {desc}\n' | |
|
35 | echo '% Rebasing D onto E detaching from C' | |
|
36 | hg rebase --detach -s 3 -d 4 2>&1 | sed 's/\(saving bundle to \).*/\1/' | |
|
37 | hg glog --template '{rev}: {desc}\n' | |
|
38 | echo "Expected A, D, E" | |
|
39 | hg manifest | |
|
40 | ||
|
41 | echo | |
|
42 | createrepo > /dev/null 2>&1 | |
|
43 | hg glog --template '{rev}: {desc}\n' | |
|
44 | echo '% Rebasing C onto E detaching from B' | |
|
45 | hg rebase --detach -s 2 -d 4 2>&1 | sed 's/\(saving bundle to \).*/\1/' | |
|
46 | hg glog --template '{rev}: {desc}\n' | |
|
47 | echo "Expected A, C, D, E" | |
|
48 | hg manifest | |
|
49 | ||
|
50 | echo | |
|
51 | createrepo > /dev/null 2>&1 | |
|
52 | hg glog --template '{rev}: {desc}\n' | |
|
53 | echo '% Rebasing B onto E using detach (same as not using it)' | |
|
54 | hg rebase --detach -s 1 -d 4 2>&1 | sed 's/\(saving bundle to \).*/\1/' | |
|
55 | hg glog --template '{rev}: {desc}\n' | |
|
56 | echo "Expected A, B, C, D, E" | |
|
57 | hg manifest | |
|
58 | ||
|
59 | echo | |
|
60 | createrepo > /dev/null 2>&1 | |
|
61 | hg glog --template '{rev}: {desc}\n' | |
|
62 | echo '% Rebasing C onto E detaching from B and collapsing' | |
|
63 | hg rebase --detach --collapse -s 2 -d 4 2>&1 | sed 's/\(saving bundle to \).*/\1/' | |
|
64 | hg glog --template '{rev}: {desc}\n' | |
|
65 | echo "Expected A, C, D, E" | |
|
66 | hg manifest | |
|
67 | ||
|
68 | exit 0 |
@@ -0,0 +1,134 b'' | |||
|
1 | @ 4: E | |
|
2 | | | |
|
3 | | o 3: D | |
|
4 | | | | |
|
5 | | o 2: C | |
|
6 | | | | |
|
7 | | o 1: B | |
|
8 | |/ | |
|
9 | o 0: A | |
|
10 | ||
|
11 | % Rebasing D onto E detaching from C | |
|
12 | saving bundle to | |
|
13 | adding branch | |
|
14 | adding changesets | |
|
15 | adding manifests | |
|
16 | adding file changes | |
|
17 | added 2 changesets with 2 changes to 2 files (+1 heads) | |
|
18 | rebase completed | |
|
19 | @ 4: D | |
|
20 | | | |
|
21 | o 3: E | |
|
22 | | | |
|
23 | | o 2: C | |
|
24 | | | | |
|
25 | | o 1: B | |
|
26 | |/ | |
|
27 | o 0: A | |
|
28 | ||
|
29 | Expected A, D, E | |
|
30 | A | |
|
31 | D | |
|
32 | E | |
|
33 | ||
|
34 | @ 4: E | |
|
35 | | | |
|
36 | | o 3: D | |
|
37 | | | | |
|
38 | | o 2: C | |
|
39 | | | | |
|
40 | | o 1: B | |
|
41 | |/ | |
|
42 | o 0: A | |
|
43 | ||
|
44 | % Rebasing C onto E detaching from B | |
|
45 | saving bundle to | |
|
46 | adding branch | |
|
47 | adding changesets | |
|
48 | adding manifests | |
|
49 | adding file changes | |
|
50 | added 3 changesets with 3 changes to 3 files (+1 heads) | |
|
51 | rebase completed | |
|
52 | @ 4: D | |
|
53 | | | |
|
54 | o 3: C | |
|
55 | | | |
|
56 | o 2: E | |
|
57 | | | |
|
58 | | o 1: B | |
|
59 | |/ | |
|
60 | o 0: A | |
|
61 | ||
|
62 | Expected A, C, D, E | |
|
63 | A | |
|
64 | C | |
|
65 | D | |
|
66 | E | |
|
67 | ||
|
68 | @ 4: E | |
|
69 | | | |
|
70 | | o 3: D | |
|
71 | | | | |
|
72 | | o 2: C | |
|
73 | | | | |
|
74 | | o 1: B | |
|
75 | |/ | |
|
76 | o 0: A | |
|
77 | ||
|
78 | % Rebasing B onto E using detach (same as not using it) | |
|
79 | saving bundle to | |
|
80 | adding branch | |
|
81 | adding changesets | |
|
82 | adding manifests | |
|
83 | adding file changes | |
|
84 | added 4 changesets with 4 changes to 4 files | |
|
85 | rebase completed | |
|
86 | @ 4: D | |
|
87 | | | |
|
88 | o 3: C | |
|
89 | | | |
|
90 | o 2: B | |
|
91 | | | |
|
92 | o 1: E | |
|
93 | | | |
|
94 | o 0: A | |
|
95 | ||
|
96 | Expected A, B, C, D, E | |
|
97 | A | |
|
98 | B | |
|
99 | C | |
|
100 | D | |
|
101 | E | |
|
102 | ||
|
103 | @ 4: E | |
|
104 | | | |
|
105 | | o 3: D | |
|
106 | | | | |
|
107 | | o 2: C | |
|
108 | | | | |
|
109 | | o 1: B | |
|
110 | |/ | |
|
111 | o 0: A | |
|
112 | ||
|
113 | % Rebasing C onto E detaching from B and collapsing | |
|
114 | saving bundle to | |
|
115 | adding branch | |
|
116 | adding changesets | |
|
117 | adding manifests | |
|
118 | adding file changes | |
|
119 | added 2 changesets with 3 changes to 3 files (+1 heads) | |
|
120 | rebase completed | |
|
121 | @ 3: Collapsed revision | |
|
122 | | * C | |
|
123 | | * D | |
|
124 | o 2: E | |
|
125 | | | |
|
126 | | o 1: B | |
|
127 | |/ | |
|
128 | o 0: A | |
|
129 | ||
|
130 | Expected A, C, D, E | |
|
131 | A | |
|
132 | C | |
|
133 | D | |
|
134 | E |
@@ -22,6 +22,8 b' from mercurial.lock import release' | |||
|
22 | 22 | from mercurial.i18n import _ |
|
23 | 23 | import os, errno |
|
24 | 24 | |
|
25 | nullmerge = -2 | |
|
26 | ||
|
25 | 27 | def rebase(ui, repo, **opts): |
|
26 | 28 | """move changeset (and descendants) to a different branch |
|
27 | 29 | |
@@ -53,6 +55,7 b' def rebase(ui, repo, **opts):' | |||
|
53 | 55 | extrafn = opts.get('extrafn') |
|
54 | 56 | keepf = opts.get('keep', False) |
|
55 | 57 | keepbranchesf = opts.get('keepbranches', False) |
|
58 | detachf = opts.get('detach', False) | |
|
56 | 59 | |
|
57 | 60 | if contf or abortf: |
|
58 | 61 | if contf and abortf: |
@@ -62,6 +65,10 b' def rebase(ui, repo, **opts):' | |||
|
62 | 65 | raise error.ParseError( |
|
63 | 66 | 'rebase', _('cannot use collapse with continue or abort')) |
|
64 | 67 | |
|
68 | if detachf: | |
|
69 | raise error.ParseError( | |
|
70 | 'rebase', _('cannot use detach with continue or abort')) | |
|
71 | ||
|
65 | 72 | if srcf or basef or destf: |
|
66 | 73 | raise error.ParseError('rebase', |
|
67 | 74 | _('abort and continue do not allow specifying revisions')) |
@@ -75,8 +82,16 b' def rebase(ui, repo, **opts):' | |||
|
75 | 82 | if srcf and basef: |
|
76 | 83 | raise error.ParseError('rebase', _('cannot specify both a ' |
|
77 | 84 | 'revision and a base')) |
|
85 | if detachf: | |
|
86 | if not srcf: | |
|
87 | raise error.ParseError( | |
|
88 | 'rebase', _('detach requires a revision to be specified')) | |
|
89 | if basef: | |
|
90 | raise error.ParseError( | |
|
91 | 'rebase', _('cannot specify a base with detach')) | |
|
92 | ||
|
78 | 93 | cmdutil.bail_if_changed(repo) |
|
79 | result = buildstate(repo, destf, srcf, basef) | |
|
94 | result = buildstate(repo, destf, srcf, basef, detachf) | |
|
80 | 95 | if not result: |
|
81 | 96 | # Empty state built, nothing to rebase |
|
82 | 97 | ui.status(_('nothing to rebase\n')) |
@@ -140,10 +155,10 b' def rebase(ui, repo, **opts):' | |||
|
140 | 155 | state, targetancestors) |
|
141 | 156 | commitmsg = 'Collapsed revision' |
|
142 | 157 | for rebased in state: |
|
143 | if rebased not in skipped: | |
|
158 | if rebased not in skipped and state[rebased] != nullmerge: | |
|
144 | 159 | commitmsg += '\n* %s' % repo[rebased].description() |
|
145 | 160 | commitmsg = ui.edit(commitmsg, repo.ui.username()) |
|
146 | concludenode(repo, rev, p1, external, commitmsg=commitmsg, | |
|
161 | newrev = concludenode(repo, rev, p1, external, commitmsg=commitmsg, | |
|
147 | 162 | extra=extrafn) |
|
148 | 163 | |
|
149 | 164 | if 'qtip' in repo.tags(): |
@@ -151,11 +166,13 b' def rebase(ui, repo, **opts):' | |||
|
151 | 166 | |
|
152 | 167 | if not keepf: |
|
153 | 168 | # Remove no more useful revisions |
|
154 | if set(repo.changelog.descendants(min(state))) - set(state): | |
|
155 | ui.warn(_("warning: new changesets detected on source branch, " | |
|
156 | "not stripping\n")) | |
|
157 | else: | |
|
158 | repair.strip(ui, repo, repo[min(state)].node(), "strip") | |
|
169 | rebased = [rev for rev in state if state[rev] != nullmerge] | |
|
170 | if rebased: | |
|
171 | if set(repo.changelog.descendants(min(rebased))) - set(state): | |
|
172 | ui.warn(_("warning: new changesets detected on source branch, " | |
|
173 | "not stripping\n")) | |
|
174 | else: | |
|
175 | repair.strip(ui, repo, repo[min(rebased)].node(), "strip") | |
|
159 | 176 | |
|
160 | 177 | clearstatus(repo) |
|
161 | 178 | ui.status(_("rebase completed\n")) |
@@ -260,7 +277,10 b' def defineparents(repo, rev, target, sta' | |||
|
260 | 277 | if P1n in targetancestors: |
|
261 | 278 | p1 = target |
|
262 | 279 | elif P1n in state: |
|
263 |
|
|
|
280 | if state[P1n] == nullmerge: | |
|
281 | p1 = target | |
|
282 | else: | |
|
283 | p1 = state[P1n] | |
|
264 | 284 | else: # P1n external |
|
265 | 285 | p1 = target |
|
266 | 286 | p2 = P1n |
@@ -379,9 +399,10 b' def abort(repo, originalwd, target, stat' | |||
|
379 | 399 | clearstatus(repo) |
|
380 | 400 | repo.ui.status(_('rebase aborted\n')) |
|
381 | 401 | |
|
382 | def buildstate(repo, dest, src, base): | |
|
402 | def buildstate(repo, dest, src, base, detach): | |
|
383 | 403 | 'Define which revisions are going to be rebased and where' |
|
384 | 404 | targetancestors = set() |
|
405 | detachset = set() | |
|
385 | 406 | |
|
386 | 407 | if not dest: |
|
387 | 408 | # Destination defaults to the latest revision in the current branch |
@@ -400,6 +421,12 b' def buildstate(repo, dest, src, base):' | |||
|
400 | 421 | if commonbase == repo[dest]: |
|
401 | 422 | raise util.Abort(_('source is descendant of destination')) |
|
402 | 423 | source = repo[src].rev() |
|
424 | if detach: | |
|
425 | # We need to keep track of source's ancestors up to the common base | |
|
426 | srcancestors = set(repo.changelog.ancestors(source)) | |
|
427 | baseancestors = set(repo.changelog.ancestors(commonbase.rev())) | |
|
428 | detachset = srcancestors - baseancestors | |
|
429 | detachset.remove(commonbase.rev()) | |
|
403 | 430 | else: |
|
404 | 431 | if base: |
|
405 | 432 | cwd = repo[base].rev() |
@@ -426,6 +453,7 b' def buildstate(repo, dest, src, base):' | |||
|
426 | 453 | |
|
427 | 454 | repo.ui.debug('rebase onto %d starting from %d\n' % (dest, source)) |
|
428 | 455 | state = dict.fromkeys(repo.changelog.descendants(source), nullrev) |
|
456 | state.update(dict.fromkeys(detachset, nullmerge)) | |
|
429 | 457 | state[source] = nullrev |
|
430 | 458 | return repo['.'].rev(), repo[dest].rev(), state |
|
431 | 459 | |
@@ -468,9 +496,11 b' cmdtable = {' | |||
|
468 | 496 | ('', 'collapse', False, _('collapse the rebased changesets')), |
|
469 | 497 | ('', 'keep', False, _('keep original changesets')), |
|
470 | 498 | ('', 'keepbranches', False, _('keep original branch names')), |
|
499 | ('', 'detach', False, _('force detaching of source from its original ' | |
|
500 | 'branch')), | |
|
471 | 501 | ('c', 'continue', False, _('continue an interrupted rebase')), |
|
472 | 502 | ('a', 'abort', False, _('abort an interrupted rebase')),] + |
|
473 | 503 | templateopts, |
|
474 |
_('hg rebase [-s REV | -b REV] [-d REV] [--collapse] [-- |
|
|
475 |
|
|
|
504 | _('hg rebase [-s REV | -b REV] [-d REV] [--collapse] [--detach] ' | |
|
505 | '[--keep] [--keepbranches] | [-c] | [-a]')), | |
|
476 | 506 | } |
@@ -2,7 +2,7 b'' | |||
|
2 | 2 | |
|
3 | 3 | % Use continue and abort |
|
4 | 4 | hg rebase: cannot use both abort and continue |
|
5 | hg rebase [-s REV | -b REV] [-d REV] [--collapse] [--keep] [--keepbranches] | [-c] | [-a] | |
|
5 | hg rebase [-s REV | -b REV] [-d REV] [--collapse] [--detach] [--keep] [--keepbranches] | [-c] | [-a] | |
|
6 | 6 | |
|
7 | 7 | move changeset (and descendants) to a different branch |
|
8 | 8 | |
@@ -21,6 +21,7 b' options:' | |||
|
21 | 21 | --collapse collapse the rebased changesets |
|
22 | 22 | --keep keep original changesets |
|
23 | 23 | --keepbranches keep original branch names |
|
24 | --detach force detaching of source from its original branch | |
|
24 | 25 | -c --continue continue an interrupted rebase |
|
25 | 26 | -a --abort abort an interrupted rebase |
|
26 | 27 | --style display using template map file |
@@ -30,7 +31,7 b' use "hg -v help rebase" to show global o' | |||
|
30 | 31 | |
|
31 | 32 | % Use continue and collapse |
|
32 | 33 | hg rebase: cannot use collapse with continue or abort |
|
33 | hg rebase [-s REV | -b REV] [-d REV] [--collapse] [--keep] [--keepbranches] | [-c] | [-a] | |
|
34 | hg rebase [-s REV | -b REV] [-d REV] [--collapse] [--detach] [--keep] [--keepbranches] | [-c] | [-a] | |
|
34 | 35 | |
|
35 | 36 | move changeset (and descendants) to a different branch |
|
36 | 37 | |
@@ -49,6 +50,7 b' options:' | |||
|
49 | 50 | --collapse collapse the rebased changesets |
|
50 | 51 | --keep keep original changesets |
|
51 | 52 | --keepbranches keep original branch names |
|
53 | --detach force detaching of source from its original branch | |
|
52 | 54 | -c --continue continue an interrupted rebase |
|
53 | 55 | -a --abort abort an interrupted rebase |
|
54 | 56 | --style display using template map file |
@@ -58,7 +60,7 b' use "hg -v help rebase" to show global o' | |||
|
58 | 60 | |
|
59 | 61 | % Use continue/abort and dest/source |
|
60 | 62 | hg rebase: abort and continue do not allow specifying revisions |
|
61 | hg rebase [-s REV | -b REV] [-d REV] [--collapse] [--keep] [--keepbranches] | [-c] | [-a] | |
|
63 | hg rebase [-s REV | -b REV] [-d REV] [--collapse] [--detach] [--keep] [--keepbranches] | [-c] | [-a] | |
|
62 | 64 | |
|
63 | 65 | move changeset (and descendants) to a different branch |
|
64 | 66 | |
@@ -77,6 +79,7 b' options:' | |||
|
77 | 79 | --collapse collapse the rebased changesets |
|
78 | 80 | --keep keep original changesets |
|
79 | 81 | --keepbranches keep original branch names |
|
82 | --detach force detaching of source from its original branch | |
|
80 | 83 | -c --continue continue an interrupted rebase |
|
81 | 84 | -a --abort abort an interrupted rebase |
|
82 | 85 | --style display using template map file |
@@ -86,7 +89,7 b' use "hg -v help rebase" to show global o' | |||
|
86 | 89 | |
|
87 | 90 | % Use source and base |
|
88 | 91 | hg rebase: cannot specify both a revision and a base |
|
89 | hg rebase [-s REV | -b REV] [-d REV] [--collapse] [--keep] [--keepbranches] | [-c] | [-a] | |
|
92 | hg rebase [-s REV | -b REV] [-d REV] [--collapse] [--detach] [--keep] [--keepbranches] | [-c] | [-a] | |
|
90 | 93 | |
|
91 | 94 | move changeset (and descendants) to a different branch |
|
92 | 95 | |
@@ -105,6 +108,7 b' options:' | |||
|
105 | 108 | --collapse collapse the rebased changesets |
|
106 | 109 | --keep keep original changesets |
|
107 | 110 | --keepbranches keep original branch names |
|
111 | --detach force detaching of source from its original branch | |
|
108 | 112 | -c --continue continue an interrupted rebase |
|
109 | 113 | -a --abort abort an interrupted rebase |
|
110 | 114 | --style display using template map file |
General Comments 0
You need to be logged in to leave comments.
Login now