##// END OF EJS Templates
rebase: avoid redundant merges (issue1301)
Stefano Tortarolo -
r7278:45495d78 default
parent child Browse files
Show More
@@ -13,12 +13,31 b' For more information:'
13 http://www.selenic.com/mercurial/wiki/index.cgi/RebaseProject
13 http://www.selenic.com/mercurial/wiki/index.cgi/RebaseProject
14 '''
14 '''
15
15
16 from mercurial import util, repair, merge, cmdutil, dispatch, commands, extensions
16 from mercurial import util, repair, merge, cmdutil, dispatch, commands
17 from mercurial import extensions, ancestor
17 from mercurial.commands import templateopts
18 from mercurial.commands import templateopts
18 from mercurial.node import nullrev
19 from mercurial.node import nullrev
19 from mercurial.i18n import _
20 from mercurial.i18n import _
20 import os, errno
21 import os, errno
21
22
23 def rebasemerge(repo, rev, first=False):
24 'return the correct ancestor'
25 oldancestor = ancestor.ancestor
26
27 def newancestor(a, b, pfunc):
28 ancestor.ancestor = oldancestor
29 anc = ancestor.ancestor(a, b, pfunc)
30 if b == rev:
31 return repo[rev].parents()[0].rev()
32 return ancestor.ancestor(a, b, pfunc)
33
34 if not first:
35 ancestor.ancestor = newancestor
36 else:
37 repo.ui.debug(_("First revision, do not change ancestor\n"))
38 stats = merge.update(repo, rev, True, True, False)
39 return stats
40
22 def rebase(ui, repo, **opts):
41 def rebase(ui, repo, **opts):
23 """move changeset (and descendants) to a different branch
42 """move changeset (and descendants) to a different branch
24
43
@@ -116,10 +135,12 b' def concludenode(repo, rev, p1, p2, stat'
116 """Skip commit if collapsing has been required and rev is not the last
135 """Skip commit if collapsing has been required and rev is not the last
117 revision, commit otherwise
136 revision, commit otherwise
118 """
137 """
119 repo.dirstate.setparents(repo[p1].node(), repo[p2].node())
138 repo.ui.debug(_(" set parents\n"))
139 if collapse and not last:
140 repo.dirstate.setparents(repo[p1].node())
141 return None
120
142
121 if collapse and not last:
143 repo.dirstate.setparents(repo[p1].node(), repo[p2].node())
122 return None
123
144
124 # Commit, record the old nodeid
145 # Commit, record the old nodeid
125 m, a, r = repo.status()[:3]
146 m, a, r = repo.status()[:3]
@@ -147,16 +168,25 b' def concludenode(repo, rev, p1, p2, stat'
147
168
148 def rebasenode(repo, rev, target, state, skipped, targetancestors, collapse):
169 def rebasenode(repo, rev, target, state, skipped, targetancestors, collapse):
149 'Rebase a single revision'
170 'Rebase a single revision'
150 repo.ui.debug(_("rebasing %d:%s\n") % (rev, repo[rev].node()))
171 repo.ui.debug(_("rebasing %d:%s\n") % (rev, repo[rev]))
151
172
152 p1, p2 = defineparents(repo, rev, target, state, targetancestors)
173 p1, p2 = defineparents(repo, rev, target, state, targetancestors)
153
174
175 repo.ui.debug(_(" future parents are %d and %d\n") % (repo[p1].rev(),
176 repo[p2].rev()))
177
154 # Merge phase
178 # Merge phase
155 if len(repo.parents()) != 2:
179 if len(repo.parents()) != 2:
156 # Update to target and merge it with local
180 # Update to target and merge it with local
181 if repo['.'].rev() != repo[p1].rev():
182 repo.ui.debug(_(" update to %d:%s\n") % (repo[p1].rev(), repo[p1]))
157 merge.update(repo, p1, False, True, False)
183 merge.update(repo, p1, False, True, False)
184 else:
185 repo.ui.debug(_(" already in target\n"))
158 repo.dirstate.write()
186 repo.dirstate.write()
159 stats = merge.update(repo, rev, True, False, False)
187 repo.ui.debug(_(" merge against %d:%s\n") % (repo[rev].rev(), repo[rev]))
188 first = repo[rev].rev() == repo[min(state)].rev()
189 stats = rebasemerge(repo, rev, first)
160
190
161 if stats[3] > 0:
191 if stats[3] > 0:
162 raise util.Abort(_('fix unresolved conflicts with hg resolve then '
192 raise util.Abort(_('fix unresolved conflicts with hg resolve then '
@@ -41,15 +41,20 b' createrepo () {'
41
41
42 createrepo > /dev/null 2>&1
42 createrepo > /dev/null 2>&1
43 hg glog --template '{rev}: {desc}\n'
43 hg glog --template '{rev}: {desc}\n'
44 echo '% Rebasing'
44 echo '% Rebasing B onto H'
45 hg up -C 3
45 hg up -C 3
46 hg rebase --collapse 2>&1 | sed 's/\(saving bundle to \).*/\1/'
46 hg rebase --collapse 2>&1 | sed 's/\(saving bundle to \).*/\1/'
47 hg glog --template '{rev}: {desc}\n'
47 hg glog --template '{rev}: {desc}\n'
48 echo "Expected A, B, C, D, F, H"
49 hg manifest
48
50
49 createrepo > /dev/null 2>&1
51 createrepo > /dev/null 2>&1
50 echo '% Rebasing'
52 echo
53 echo '% Rebasing G onto H'
51 hg rebase --base 6 --collapse 2>&1 | sed 's/\(saving bundle to \).*/\1/'
54 hg rebase --base 6 --collapse 2>&1 | sed 's/\(saving bundle to \).*/\1/'
52 hg glog --template '{rev}: {desc}\n'
55 hg glog --template '{rev}: {desc}\n'
56 echo "Expected A, E, F, H"
57 hg manifest
53
58
54 createrepocomplex () {
59 createrepocomplex () {
55 cd $BASE
60 cd $BASE
@@ -76,6 +81,7 b' createrepocomplex () {'
76 addcommit "H" 7
81 addcommit "H" 7
77 }
82 }
78
83
84 echo
79 createrepocomplex > /dev/null 2>&1
85 createrepocomplex > /dev/null 2>&1
80 hg glog --template '{rev}: {desc}\n'
86 hg glog --template '{rev}: {desc}\n'
81
87
@@ -84,8 +90,91 b" echo '% Rebase and collapse - more than "
84 hg rebase -s 2 --collapse
90 hg rebase -s 2 --collapse
85
91
86 echo
92 echo
87 echo '% Rebase and collapse'
93 echo '% Rebase and collapse - E onto H'
88 hg rebase -s 4 --collapse 2>&1 | sed 's/\(saving bundle to \).*/\1/'
94 hg rebase -s 4 --collapse 2>&1 | sed 's/\(saving bundle to \).*/\1/'
89 hg glog --template '{rev}: {desc}\n'
95 hg glog --template '{rev}: {desc}\n'
96 echo "Expected A, B, C, E, F, H"
97 hg manifest
90
98
99 createrepocomplex () {
100 cd $BASE
101 rm -rf a
102 hg init a
103 cd a
104 addcommit "A" 0
105 addcommit "B" 1
106
107 hg up 0
108 addcommit "C" 2
109 hg merge
110 commit "D" 3
111
112 hg up 1
113 addcommit "E" 4
114
115 echo "F" > E
116 commit "F" 5
117
118 addcommit "G" 6
119
120 hg merge
121 commit "H" 7
122
123 hg up 0
124 addcommit "I" 8
125 }
126
127 echo
128 createrepocomplex > /dev/null 2>&1
129 hg glog --template '{rev}: {desc}\n'
130
131 echo
132 echo '% Rebase and collapse - E onto I'
133 hg rebase -s 4 --collapse
134
135 echo '% Fix conflict and continue'
136 echo 'Resolved merge' > E
137 hg resolve -m E
138 hg rebase -c 2>&1 | sed 's/\(saving bundle to \).*/\1/'
139
140 hg glog --template '{rev}: {desc}\n'
141
142 echo "Expected A, B, C, E, G, I"
143 hg manifest
144
145 echo 'Cat E:'
146 cat E
147
148 createrepocomplex () {
149 cd $BASE
150 rm -rf a
151 hg init a
152 cd a
153 addcommit "A" 0
154 addcommit "B" 1
155
156 addcommit "C" 2
157 hg up 1
158
159 addcommit "D" 3
160
161 hg merge
162 commit "E" 4
163
164 hg up 0
165 addcommit "F" 5
166 }
167
168 echo
169 createrepocomplex > /dev/null 2>&1
170 hg glog --template '{rev}: {desc}\n'
171
172 echo
173 echo '% Rebase and collapse - B onto F'
174 hg rebase -s 1 --collapse 2>&1 | sed 's/\(saving bundle to \).*/\1/'
175
176 hg glog --template '{rev}: {desc}\n'
177
178 echo "Expected A, B, C, D, F"
179 hg manifest
91 exit 0
180 exit 0
@@ -14,7 +14,7 b' o | 5: F'
14 |/
14 |/
15 o 0: A
15 o 0: A
16
16
17 % Rebasing
17 % Rebasing B onto H
18 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
18 3 files updated, 0 files merged, 2 files removed, 0 files unresolved
19 saving bundle to
19 saving bundle to
20 adding branch
20 adding branch
@@ -37,7 +37,15 b' o | 2: F'
37 |/
37 |/
38 o 0: A
38 o 0: A
39
39
40 % Rebasing
40 Expected A, B, C, D, F, H
41 A
42 B
43 C
44 D
45 F
46 H
47
48 % Rebasing G onto H
41 saving bundle to
49 saving bundle to
42 adding branch
50 adding branch
43 adding changesets
51 adding changesets
@@ -60,6 +68,12 b' o 4: F'
60 |/
68 |/
61 o 0: A
69 o 0: A
62
70
71 Expected A, E, F, H
72 A
73 E
74 F
75 H
76
63 @ 7: H
77 @ 7: H
64 |
78 |
65 | o 6: G
79 | o 6: G
@@ -80,7 +94,7 b' o 0: A'
80 % Rebase and collapse - more than one external (fail)
94 % Rebase and collapse - more than one external (fail)
81 abort: unable to collapse, there is more than one external parent
95 abort: unable to collapse, there is more than one external parent
82
96
83 % Rebase and collapse
97 % Rebase and collapse - E onto H
84 saving bundle to
98 saving bundle to
85 adding branch
99 adding branch
86 adding changesets
100 adding changesets
@@ -102,3 +116,104 b' o / 1: B'
102 |/
116 |/
103 o 0: A
117 o 0: A
104
118
119 Expected A, B, C, E, F, H
120 A
121 B
122 C
123 E
124 F
125 H
126
127 @ 8: I
128 |
129 | o 7: H
130 | |\
131 | | o 6: G
132 | | |
133 | | o 5: F
134 | | |
135 | | o 4: E
136 | | |
137 | o | 3: D
138 | |\|
139 | o | 2: C
140 |/ /
141 | o 1: B
142 |/
143 o 0: A
144
145
146 % Rebase and collapse - E onto I
147 merging E
148 warning: conflicts during merge.
149 merging E failed!
150 abort: fix unresolved conflicts with hg resolve then run hg rebase --continue
151 % Fix conflict and continue
152 saving bundle to
153 adding branch
154 adding changesets
155 adding manifests
156 adding file changes
157 added 2 changesets with 3 changes to 3 files
158 rebase completed
159 @ 5: Collapsed revision
160 |\ * E
161 | | * F
162 | | * G
163 | | * H
164 | o 4: I
165 | |
166 o | 3: D
167 |\ \
168 | o | 2: C
169 | |/
170 o / 1: B
171 |/
172 o 0: A
173
174 Expected A, B, C, E, G, I
175 A
176 B
177 C
178 E
179 G
180 I
181 Cat E:
182 Resolved merge
183
184 @ 5: F
185 |
186 | o 4: E
187 | |\
188 | | o 3: D
189 | | |
190 | o | 2: C
191 | |/
192 | o 1: B
193 |/
194 o 0: A
195
196
197 % Rebase and collapse - B onto F
198 saving bundle to
199 adding branch
200 adding changesets
201 adding manifests
202 adding file changes
203 added 2 changesets with 4 changes to 4 files
204 rebase completed
205 @ 2: Collapsed revision
206 | * B
207 | * C
208 | * D
209 | * E
210 o 1: F
211 |
212 o 0: A
213
214 Expected A, B, C, D, F
215 A
216 B
217 C
218 D
219 F
@@ -31,6 +31,10 b" sed -e 's/c2/l2/' common > common.new"
31 mv common.new common
31 mv common.new common
32 hg commit -d '4 0' -u test -m "L2"
32 hg commit -d '4 0' -u test -m "L2"
33
33
34 echo 'l3' >> extra2
35 hg add extra2
36 hg commit -d '5 0' -u test -m "L3"
37
34 hg glog --template '{rev}: {desc}\n'
38 hg glog --template '{rev}: {desc}\n'
35
39
36 echo
40 echo
@@ -47,9 +51,28 b' hg rebase --continue'
47
51
48 echo
52 echo
49 echo '% Conclude rebase'
53 echo '% Conclude rebase'
50 echo 'solved merge' >common
54 echo 'resolved merge' >common
51 hg resolve -m common
55 hg resolve -m common
52 hg rebase --continue 2>&1 | cleanoutput
56 hg rebase --continue 2>&1 | cleanoutput
53
57
58 hg glog --template '{rev}: {desc}\n'
54
59
55 hg glog --template '{rev}: {desc}\n'
60 echo
61 echo '% Check correctness'
62 echo ' - Rev. 0'
63 hg cat -r 0 common
64
65 echo ' - Rev. 1'
66 hg cat -r 1 common
67
68 echo ' - Rev. 2'
69 hg cat -r 2 common
70
71 echo ' - Rev. 3'
72 hg cat -r 3 common
73
74 echo ' - Rev. 4'
75 hg cat -r 4 common
76
77 echo ' - Rev. 5'
78 hg cat -r 5 common
@@ -1,6 +1,8 b''
1 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2 created new head
2 created new head
3 @ 4: L2
3 @ 5: L3
4 |
5 o 4: L2
4 |
6 |
5 o 3: L1
7 o 3: L1
6 |
8 |
@@ -29,9 +31,11 b' adding branch'
29 adding changesets
31 adding changesets
30 adding manifests
32 adding manifests
31 adding file changes
33 adding file changes
32 added 2 changesets with 2 changes to 2 files
34 added 3 changesets with 3 changes to 3 files
33 rebase completed
35 rebase completed
34 @ 4: L2
36 @ 5: L3
37 |
38 o 4: L2
35 |
39 |
36 o 3: L1
40 o 3: L1
37 |
41 |
@@ -41,3 +45,22 b' o 1: C2'
41 |
45 |
42 o 0: C1
46 o 0: C1
43
47
48
49 % Check correctness
50 - Rev. 0
51 c1
52 - Rev. 1
53 c1
54 c2
55 - Rev. 2
56 c1
57 c2
58 c3
59 - Rev. 3
60 c1
61 c2
62 c3
63 - Rev. 4
64 resolved merge
65 - Rev. 5
66 resolved merge
General Comments 0
You need to be logged in to leave comments. Login now