##// END OF EJS Templates
rebase: move bookmark to destination for commits becoming empty (issue5627)...
Jun Wu -
r33591:52f82e7d stable
parent child Browse files
Show More
@@ -0,0 +1,202 b''
1 $ cat >> $HGRCPATH<<EOF
2 > [extensions]
3 > rebase=
4 > drawdag=$TESTDIR/drawdag.py
5 > EOF
6
7 $ hg init non-merge
8 $ cd non-merge
9 $ hg debugdrawdag<<'EOS'
10 > F
11 > |
12 > E
13 > |
14 > D
15 > |
16 > B C
17 > |/
18 > A
19 > EOS
20
21 $ for i in C D E F; do
22 > hg bookmark -r $i -i BOOK-$i
23 > done
24
25 $ hg debugdrawdag<<'EOS'
26 > E
27 > |
28 > D
29 > |
30 > B
31 > EOS
32
33 $ hg log -G -T '{rev} {desc} {bookmarks}'
34 o 7 E
35 |
36 o 6 D
37 |
38 | o 5 F BOOK-F
39 | |
40 | o 4 E BOOK-E
41 | |
42 | o 3 D BOOK-D
43 | |
44 | o 2 C BOOK-C
45 | |
46 o | 1 B
47 |/
48 o 0 A
49
50 With --keep, bookmark should not move
51
52 $ hg rebase -r 3+4 -d E --keep
53 rebasing 3:e7b3f00ed42e "D" (BOOK-D)
54 note: rebase of 3:e7b3f00ed42e created no changes to commit
55 rebasing 4:69a34c08022a "E" (BOOK-E)
56 note: rebase of 4:69a34c08022a created no changes to commit
57 $ hg log -G -T '{rev} {desc} {bookmarks}'
58 o 7 E
59 |
60 o 6 D
61 |
62 | o 5 F BOOK-F
63 | |
64 | o 4 E BOOK-E
65 | |
66 | o 3 D BOOK-D
67 | |
68 | o 2 C BOOK-C
69 | |
70 o | 1 B
71 |/
72 o 0 A
73
74 Bookmark is usually an indication of a head. For changes that are introduced by
75 an ancestor of bookmark B, after moving B to B-NEW, the changes are ideally
76 still introduced by an ancestor of changeset on B-NEW. In the below case,
77 "BOOK-D", and "BOOK-E" include changes introduced by "C".
78
79 $ hg rebase -s 2 -d E
80 rebasing 2:dc0947a82db8 "C" (C BOOK-C)
81 rebasing 3:e7b3f00ed42e "D" (BOOK-D)
82 note: rebase of 3:e7b3f00ed42e created no changes to commit
83 rebasing 4:69a34c08022a "E" (BOOK-E)
84 note: rebase of 4:69a34c08022a created no changes to commit
85 rebasing 5:6b2aeab91270 "F" (F BOOK-F)
86 saved backup bundle to $TESTTMP/non-merge/.hg/strip-backup/dc0947a82db8-52bb4973-rebase.hg (glob)
87 $ hg log -G -T '{rev} {desc} {bookmarks}'
88 o 5 F BOOK-F
89 |
90 o 4 C BOOK-C BOOK-D BOOK-E
91 |
92 o 3 E
93 |
94 o 2 D
95 |
96 o 1 B
97 |
98 o 0 A
99
100 Merge and its ancestors all become empty
101
102 $ hg init $TESTTMP/merge1
103 $ cd $TESTTMP/merge1
104
105 $ hg debugdrawdag<<'EOS'
106 > E
107 > /|
108 > B C D
109 > \|/
110 > A
111 > EOS
112
113 $ for i in C D E; do
114 > hg bookmark -r $i -i BOOK-$i
115 > done
116
117 $ hg debugdrawdag<<'EOS'
118 > H
119 > |
120 > D
121 > |
122 > C
123 > |
124 > B
125 > EOS
126
127 $ hg rebase -r '(A::)-(B::)-A' -d H
128 rebasing 2:dc0947a82db8 "C" (BOOK-C)
129 note: rebase of 2:dc0947a82db8 created no changes to commit
130 rebasing 3:b18e25de2cf5 "D" (BOOK-D)
131 note: rebase of 3:b18e25de2cf5 created no changes to commit
132 rebasing 4:86a1f6686812 "E" (E BOOK-E)
133 note: rebase of 4:86a1f6686812 created no changes to commit
134 saved backup bundle to $TESTTMP/merge1/.hg/strip-backup/b18e25de2cf5-1fd0a4ba-rebase.hg (glob)
135
136 $ hg log -G -T '{rev} {desc} {bookmarks}'
137 o 4 H BOOK-C BOOK-D BOOK-E
138 |
139 o 3 D
140 |
141 o 2 C
142 |
143 o 1 B
144 |
145 o 0 A
146
147 Part of ancestors of a merge become empty
148
149 $ hg init $TESTTMP/merge2
150 $ cd $TESTTMP/merge2
151
152 $ hg debugdrawdag<<'EOS'
153 > G
154 > /|
155 > E F
156 > | |
157 > B C D
158 > \|/
159 > A
160 > EOS
161
162 $ for i in C D E F G; do
163 > hg bookmark -r $i -i BOOK-$i
164 > done
165
166 $ hg debugdrawdag<<'EOS'
167 > H
168 > |
169 > F
170 > |
171 > C
172 > |
173 > B
174 > EOS
175
176 $ hg rebase -r '(A::)-(B::)-A' -d H
177 rebasing 2:dc0947a82db8 "C" (BOOK-C)
178 note: rebase of 2:dc0947a82db8 created no changes to commit
179 rebasing 3:b18e25de2cf5 "D" (D BOOK-D)
180 rebasing 4:03ca77807e91 "E" (E BOOK-E)
181 rebasing 5:ad6717a6a58e "F" (BOOK-F)
182 note: rebase of 5:ad6717a6a58e created no changes to commit
183 rebasing 6:c58e8bdac1f4 "G" (G BOOK-G)
184 saved backup bundle to $TESTTMP/merge2/.hg/strip-backup/b18e25de2cf5-2d487005-rebase.hg (glob)
185
186 $ hg log -G -T '{rev} {desc} {bookmarks}'
187 o 7 G BOOK-G
188 |\
189 | o 6 E BOOK-E
190 | |
191 o | 5 D BOOK-D BOOK-F
192 |/
193 o 4 H BOOK-C
194 |
195 o 3 F
196 |
197 o 2 C
198 |
199 o 1 B
200 |
201 o 0 A
202
@@ -512,7 +512,8 b' class rebaseruntime(object):'
512 512 collapsedas = None
513 513 if self.collapsef:
514 514 collapsedas = newnode
515 clearrebased(ui, repo, self.state, self.skipped, collapsedas)
515 clearrebased(ui, repo, self.dest, self.state, self.skipped,
516 collapsedas)
516 517
517 518 clearstatus(repo)
518 519 clearcollapsemsg(repo)
@@ -897,6 +898,58 b' def rebasenode(repo, rev, p1, base, stat'
897 898 copies.duplicatecopies(repo, rev, p1rev, skiprev=dest)
898 899 return stats
899 900
901 def adjustdest(repo, rev, dest, state):
902 """adjust rebase destination given the current rebase state
903
904 rev is what is being rebased. Return a list of two revs, which are the
905 adjusted destinations for rev's p1 and p2, respectively. If a parent is
906 nullrev, return dest without adjustment for it.
907
908 For example, when doing rebase -r B+E -d F, rebase will first move B to B1,
909 and E's destination will be adjusted from F to B1.
910
911 B1 <- written during rebasing B
912 |
913 F <- original destination of B, E
914 |
915 | E <- rev, which is being rebased
916 | |
917 | D <- prev, one parent of rev being checked
918 | |
919 | x <- skipped, ex. no successor or successor in (::dest)
920 | |
921 | C
922 | |
923 | B <- rebased as B1
924 |/
925 A
926
927 Another example about merge changeset, rebase -r C+G+H -d K, rebase will
928 first move C to C1, G to G1, and when it's checking H, the adjusted
929 destinations will be [C1, G1].
930
931 H C1 G1
932 /| | /
933 F G |/
934 K | | -> K
935 | C D |
936 | |/ |
937 | B | ...
938 |/ |/
939 A A
940 """
941 result = []
942 for prev in repo.changelog.parentrevs(rev):
943 adjusted = dest
944 if prev != nullrev:
945 # pick already rebased revs from state
946 source = [s for s, d in state.items() if d > 0]
947 candidate = repo.revs('max(%ld and (::%d))', source, prev).first()
948 if candidate is not None:
949 adjusted = state[candidate]
950 result.append(adjusted)
951 return result
952
900 953 def nearestrebased(repo, rev, state):
901 954 """return the nearest ancestors of rev in the rebase result"""
902 955 rebased = [r for r in state if state[r] > nullmerge]
@@ -1301,12 +1354,21 b' def buildstate(repo, dest, rebaseset, co'
1301 1354 state[r] = revprecursor
1302 1355 return originalwd, dest.rev(), state
1303 1356
1304 def clearrebased(ui, repo, state, skipped, collapsedas=None):
1357 def clearrebased(ui, repo, dest, state, skipped, collapsedas=None):
1305 1358 """dispose of rebased revision at the end of the rebase
1306 1359
1307 1360 If `collapsedas` is not None, the rebase was a collapse whose result if the
1308 1361 `collapsedas` node."""
1309 1362 tonode = repo.changelog.node
1363 # Move bookmark of skipped nodes to destination. This cannot be handled
1364 # by scmutil.cleanupnodes since it will treat rev as removed (no successor)
1365 # and move bookmark backwards.
1366 bmchanges = [(name, tonode(max(adjustdest(repo, rev, dest, state))))
1367 for rev in skipped
1368 for name in repo.nodebookmarks(tonode(rev))]
1369 if bmchanges:
1370 with repo.transaction('rebase') as tr:
1371 repo._bookmarks.applychanges(repo, tr, bmchanges)
1310 1372 mapping = {}
1311 1373 for rev, newrev in sorted(state.items()):
1312 1374 if newrev >= 0 and newrev != rev:
General Comments 0
You need to be logged in to leave comments. Login now