Mercurial > evolve
annotate docs/user-guide.rst @ 1267:8cc6e90354a9 stable
docs: tweak wording, punctuation for better readability
author | Greg Ward <greg@gerg.ca> |
---|---|
date | Mon, 13 Apr 2015 15:42:42 -0400 |
parents | 8328337d23b2 |
children | ba3ff8c00304 |
rev | line source |
---|---|
978 | 1 .. Copyright © 2014 Greg Ward <greg@gerg.ca> |
2 | |
3 ------------------ | |
4 Evolve: User Guide | |
5 ------------------ | |
6 | |
7 .. contents:: | |
8 | |
9 Life without ``evolve`` | |
10 ----------------------- | |
11 | |
12 Before we dive into learning about ``evolve``, let's look into some | |
13 features of core Mercurial that interact with ``evolve``. ``commit`` | |
14 affects ``evolve``, and ``evolve`` modifies how ``commit --amend`` | |
15 works. | |
16 | |
17 Example 1: Commit a new changeset | |
18 ================================= | |
19 | |
20 To create a new changeset, simply run ``hg commit`` as usual. | |
21 ``evolve`` does not change the behaviour of ``commit`` at all. | |
22 | |
23 However, it's important to understand that new changesets are in the | |
24 *draft* phase by default: they are mutable. This means that they can | |
25 be modified by Mercurial's existing history-editing commands | |
26 (``rebase``, ``histedit``, etc.), and also by the ``evolve`` | |
27 extension. Specifically, ``evolve`` adds a number of commands that can | |
28 be used to modify history: ``amend``, ``uncommit``, ``prune``, | |
29 ``fold``, and ``evolve``. Generally speaking, changesets remain in | |
30 *draft* phase until they are pushed to another repository, at which | |
31 point they enter *public* phase. :: | |
32 | |
33 $ hg commit -m 'implement feature X' | |
34 $ hg phase -r . | |
35 1: draft | |
36 | |
37 (Strictly speaking, changesets only become public when they are pushed | |
38 to a *publishing* repository. But all repositories are publishing by | |
39 default; you have to explicitly configure repositories to be | |
40 *non-publishing*. Non-publishing repositories are an advanced topic | |
41 which we'll see when we get to `sharing mutable history`_.) | |
42 | |
43 .. _`sharing mutable history`: sharing.html | |
44 | |
45 Example 2: Amend a changeset (traditional) | |
46 ========================================== | |
47 | |
48 Imagine you've just committed a new changeset, and then you discover a | |
49 mistake. Maybe you forgot to run the tests and a failure slipped in. | |
50 You want to modify history so that you push one perfect changeset, | |
51 rather than one flawed changeset followed by an "oops" commit. (Or | |
52 perhaps you made a typo in the commit message—this is really feature | |
53 *Y*, not feature X. You can't fix that with a followup commit.) | |
54 | |
55 This is actually trivial with plain vanilla Mercurial since 2.2: fix | |
56 your mistake and run :: | |
57 | |
58 $ hg commit --amend -m 'implement feature Y' | |
59 | |
60 to create a new, amended changeset. The drawback of doing this with | |
61 vanilla Mercurial is that your original, flawed, changeset is removed | |
62 from the repository. This is *unsafe* history editing. It's probably | |
63 not too serious if all you did was fix a syntax error, but still. | |
64 | |
65 .. figure:: figures/figure-ug01.svg | |
66 | |
67 Figure 1: unsafe history modification with core Mercurial (not | |
68 using ``evolve``): the original revision 1 is destroyed. | |
69 | |
70 (Incidentally, Mercurial's traditional history modification mechanism | |
71 isn't *really* unsafe: any changeset(s) removed from the repository | |
72 are kept in a backup directory, so you can manually restore them later | |
73 if you change your mind. But it's awkward and inconvenient compared to | |
74 the features provided by ``evolve`` and changeset obsolescence.) | |
75 | |
76 Life with ``evolve`` (basic usage) | |
77 ---------------------------------- | |
78 | |
79 Once you enable the ``evolve`` extension, a number of features are | |
80 available to you. First, we're going to explore several examples of | |
81 painless, trouble-free history modification. | |
82 | |
83 Example 3: Amend a changeset (with ``evolve``) | |
84 ============================================== | |
85 | |
86 Outwardly, amending a changeset with ``evolve`` can look exactly the | |
87 same as it does with core Mercurial (example 2):: | |
88 | |
89 $ hg commit --amend -m 'implement feature Y' | |
90 | |
91 Alternately, you can use the new ``amend`` command added by | |
92 ``evolve``:: | |
93 | |
94 $ hg amend -m 'implement feature Y' | |
95 | |
96 (``hg amend`` is nearly synonymous with ``hg commit --amend``. The | |
97 difference is that ``hg amend`` reuses the existing commit message by | |
98 default, whereas ``hg commit --amend`` runs your editor if you don't | |
99 pass ``-m`` or ``-l``.) | |
100 | |
101 Under the hood, though, things are quite different. Mercurial has | |
102 simply marked the old changeset *obsolete*, replacing it with a new | |
103 one. We'll explore what this means in detail later, after working | |
104 through a few more examples. | |
105 | |
106 Example 4: Prune an unwanted changeset | |
107 ====================================== | |
108 | |
109 Sometimes you make a change, and then decide it was such a bad idea | |
110 that you don't want anyone to know about it. Or maybe it was a | |
111 debugging hack that you needed to keep around for a while, but do not | |
112 intend to ever push publicly. :: | |
113 | |
114 $ echo 'debug hack' >> file1.c | |
115 $ hg commit -m 'debug hack' | |
116 | |
117 In either case, ``hg prune`` is the answer. ``prune`` simply marks | |
118 changesets obsolete without creating any new changesets to replace | |
119 them:: | |
120 | |
121 $ hg prune . | |
122 1 changesets pruned | |
123 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
124 working directory now at 934359450037 | |
125 | |
126 Outwardly, it appears that your “debug hack” commit never happened; | |
127 we're right back where we started:: | |
128 | |
129 $ hg parents --template '{rev}:{node|short} {desc|firstline}\n' | |
130 3:934359450037 implement feature Y | |
131 | |
132 In reality, though, the “debug hack” is still there, obsolete and hidden. | |
133 | |
134 Example 5: Uncommit changes to certain files | |
135 ============================================ | |
136 | |
137 Occasionally you commit more than you intended: perhaps you made | |
138 unrelated changes to different files, and thus intend to commit | |
139 different files separately. :: | |
140 | |
141 $ echo 'relevant' >> file1.c | |
142 $ echo 'irrelevant' >> file2.c | |
143 | |
144 If you forget to specify filenames on the ``commit`` command line, | |
145 Mercurial commits all those changes together:: | |
146 | |
147 $ hg commit -m 'fix bug 234' # oops: too many files | |
148 | |
149 Luckily, this mistake is easy to fix with ``uncommit``:: | |
150 | |
151 $ hg uncommit file2.c | |
152 $ hg status | |
153 M file2.c | |
154 | |
155 Let's verify that the replacement changeset looks right (i.e., | |
156 modifies only ``file1.c``):: | |
157 | |
158 $ hg parents --template '{rev}:{node|short} {desc|firstline}\n{files}\n' | |
159 6:c8defeecf7a4 fix bug 234 | |
160 file1.c | |
161 | |
162 As before, the original flawed changeset is still there, but obsolete | |
163 and hidden. It won't be exchanged with other repositories by ``push``, | |
164 ``pull``, or ``clone``. | |
165 | |
166 Example 6: Fold multiple changesets together into one | |
167 ===================================================== | |
168 | |
169 If you're making extensive changes to fragile source code, you might | |
170 commit more frequently than normal so that you can fallback on a | |
171 known good state if one step goes badly. :: | |
172 | |
173 $ echo step1 >> file1.c | |
174 $ hg commit -m 'step 1' # revision 7 | |
175 $ echo step2 >> file1.c | |
176 $ hg commit -m 'step 2' # revision 8 | |
177 $ echo step3 >> file2.c | |
178 $ hg commit -m 'step 3' # revision 9 | |
179 | |
180 At the end of such a sequence, you often end up with a series of small | |
181 changesets that are tedious to review individually. It might make more | |
182 sense to combine them into a single changeset using the ``fold`` | |
183 command. | |
184 | |
185 To make sure we pass the right revisions to ``fold``, let's review the | |
186 changesets we just created, from revision 7:: | |
187 | |
188 $ hg log --template '{rev}:{node|short} {desc|firstline}\n' -r 7:: | |
189 7:05e61aab8294 step 1 | |
190 8:be6d5bc8e4cc step 2 | |
191 9:35f432d9f7c1 step 3 | |
192 | |
193 and fold them:: | |
194 | |
195 $ hg fold -m 'fix bug 64' -r 7:: | |
196 3 changesets folded | |
197 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
198 | |
199 This time, Mercurial marks three changesets obsolete, replacing them | |
200 all with a single *successor*. | |
201 | |
202 (You might be familiar with this operation under other names, like | |
203 *squash* or *collapse*.) | |
204 | |
205 Changeset obsolescence under the hood | |
206 ------------------------------------- | |
207 | |
1267
8cc6e90354a9
docs: tweak wording, punctuation for better readability
Greg Ward <greg@gerg.ca>
parents:
978
diff
changeset
|
208 So far, everything has gone just fine: we haven't run into merge |
978 | 209 conflicts or other trouble. Before we start exploring advanced usage |
210 that can run into trouble, let's step back and see what happens when | |
211 Mercurial marks changesets obsolete. That will make it much easier to | |
212 understand the more advanced use cases we'll see later. | |
213 | |
214 When you have the ``evolve`` extension enabled, all history | |
215 modification uses the same underlying mechanism: the original | |
216 changesets are marked *obsolete* and replaced by zero or more | |
217 *successors*. The obsolete changesets are the *precursors* of their | |
218 successors. This applies equally to built-in commands (``commit | |
219 --amend``), commands added by ``evolve`` (``amend``, ``prune``, | |
1267
8cc6e90354a9
docs: tweak wording, punctuation for better readability
Greg Ward <greg@gerg.ca>
parents:
978
diff
changeset
|
220 ``uncommit``, ``fold``), and commands provided by other extensions |
8cc6e90354a9
docs: tweak wording, punctuation for better readability
Greg Ward <greg@gerg.ca>
parents:
978
diff
changeset
|
221 (``rebase``, ``histedit``). |
978 | 222 |
223 Another way of looking at it is that obsolescence is second-order | |
224 version control, i.e. the history of your history. We'll cover this in | |
225 more detail (and mathematical precision) in the `concepts`_ guide. | |
226 | |
227 .. _`concepts`: concepts.html | |
228 | |
229 Under the hood: Amend a changeset | |
230 ================================= | |
231 | |
232 Consider Example 2, amending a changeset with ``evolve``. We saw above | |
233 that you can do this using the exact same command-line syntax as core | |
234 Mercurial, namely ``hg commit --amend``. But the implementation is | |
235 quite different, and Figure 2 shows how. | |
236 | |
237 .. figure:: figures/figure-ug02.svg | |
238 | |
239 Figure 2: safe history modification using ``evolve``: the original | |
240 revision 1 is preserved as an obsolete changeset. (The "temporary | |
241 amend commit", marked with T, is an implementation detail stemming | |
242 from limitations in Mercurial's current merge machinery. Future | |
243 versions of Mercurial will not create them.) | |
244 | |
245 In this case, the obsolete changesets are also *hidden*. That is the | |
246 usual end state for obsolete changesets. But many scenarios result in | |
247 obsolete changesets that are still visible, which indicates your | |
248 history modification work is not yet done. We'll see examples of that | |
249 later, when we cover advanced usage. | |
250 | |
251 Seeing hidden changesets | |
252 ======================== | |
253 | |
254 TODO | |
255 | |
256 Under the hood: Prune an unwanted changeset | |
257 =========================================== | |
258 | |
259 ``prune`` (example 4 above) is the simplest history modification | |
260 command provided by ``evolve``. All it does is mark the specified | |
261 changeset(s) obsolete, with no successor/precursor relationships | |
262 involved. (If the working directory parent was one of the obsolete | |
263 changesets, ``prune`` updates back to a suitable ancestor.) | |
264 | |
265 .. figure:: figures/figure-ug03.svg | |
266 | |
267 Figure 3: pruning a changeset marks it obsolete with no successors. | |
268 | |
269 Under the hood: Uncommit changes to certain files | |
270 ================================================= | |
271 | |
272 In one sense, ``uncommit`` is a simplified version of ``amend``. Like | |
273 ``amend``, it obsoletes one changeset and leaves it with a single | |
274 successor. Unlike ``amend``, there is no ugly "temporary amend commit" | |
275 cluttering up the repository. | |
276 | |
277 In another sense, ``uncommit`` is the inverse of ``amend``: ``amend`` | |
278 takes any uncommitted changes in the working dir and “adds” | |
279 them to the working directory's parent changeset. (In reality, of | |
280 course, it creates a successor changeset, marking the original | |
281 obsolete.) In contrast, ``uncommit`` takes some changes in the working | |
282 directory's parent and moves them to the working dir, creating a new | |
283 successor changeset in the process. Figure 4 illustrates. | |
284 | |
285 .. figure:: figures/figure-ug04.svg | |
286 | |
287 Figure 4: uncommit moves some of the changes from the working | |
288 directory parent into the working dir, preserving the remaining | |
289 changes as a new successor changeset. (N.B. revision 4 is not shown | |
290 here because it was marked obsolete in the previous example.) | |
291 | |
292 | |
293 Under the hood: Fold multiple changesets together into one | |
294 ========================================================== | |
295 | |
296 The last basic example is folding multiple changesets into one, which | |
297 marks multiple changesets obsolete, replacing them all with a single | |
298 successor. | |
299 | |
300 .. figure:: figures/figure-ug05.svg | |
301 | |
302 Figure 5: fold combines multiple changesets into a single | |
303 successor, marking the original (folded) changesets obsolete. | |
304 | |
305 | |
306 Obsolete is not hidden | |
307 ====================== | |
308 | |
309 TODO | |
310 | |
311 | |
312 Understanding revision numbers | |
313 ============================== | |
314 | |
315 If you're trying these examples on your own, especially using ``hg | |
316 log`` without ``--hidden``, you have probably noticed some funny | |
317 business going on with revision numbers: there are now gaps in the | |
318 sequence. That's something you don't see with plain vanilla Mercurial; | |
319 normally, revision N is always followed by revision N+1. | |
320 | |
321 This is just the visible manifestation of hidden changesets. If | |
322 revision 95 is followed by revision 98, that means there are two | |
323 hidden changesets, 96 and 97, in between. | |
324 | |
325 Note that changeset IDs are still the permanent, immutable identifier | |
326 for changesets. Revision numbers are, as ever, a handy shorthand that | |
327 work in your local repository, but cannot be used across repositories. | |
328 They also have the useful property of showing when there are hidden | |
329 changesets lurking under the covers, which is why this document uses | |
330 revision numbers. | |
331 | |
332 | |
333 Life with ``evolve`` (advanced usage) | |
334 ------------------------------------- | |
335 | |
336 Now that you've got a solid understanding of how ``evolve`` works in | |
337 concert with changeset obsolescence, let's explore some more advanced | |
338 scenarios. All of these scenarios will involve *unstable* changesets, | |
339 which is an unavoidable consequence of obsolescence. What really sets | |
340 ``evolve`` apart from other history modification mechanisms is the | |
341 fact that it recognizes troubles like unstable changesets and provides | |
342 a consistent way for you to get out of trouble. | |
343 | |
344 (Incidentally, there are two other types of trouble that changesets | |
345 can get into with ``evolve``: they may be *divergent* or *bumped*. | |
346 Both of those states are more likely to occur when `sharing mutable | |
347 history`_, so we won't see them in this user guide.) | |
348 | |
349 .. _`sharing mutable history`: sharing.html | |
350 | |
351 | |
352 Example 7: Amend an older changeset | |
353 =================================== | |
354 | |
355 Sometimes you don't notice your mistakes until after you have | |
1267
8cc6e90354a9
docs: tweak wording, punctuation for better readability
Greg Ward <greg@gerg.ca>
parents:
978
diff
changeset
|
356 committed new changesets on top of them. :: |
978 | 357 |
358 $ hg commit -m 'fix bug 17' # rev 11 (mistake here) | |
359 $ hg commit -m 'cleanup' # rev 12 | |
360 $ hg commit -m 'feature 23' # rev 13 | |
361 | |
362 Traditionally, your only option is to commit an "oops" changeset that | |
363 fixes your mistake. That works, of course, but it makes you look bad: | |
364 you made a mistake, and the record of that mistake is recorded in | |
365 history for all eternity. (If the mistake was in the commit message, | |
1267
8cc6e90354a9
docs: tweak wording, punctuation for better readability
Greg Ward <greg@gerg.ca>
parents:
978
diff
changeset
|
366 too bad: you cannot fix it.) |
978 | 367 |
368 More subtly, there now exist changesets that are *worse* than what | |
369 came before—the code no longer builds, the tests don't pass, or | |
1267
8cc6e90354a9
docs: tweak wording, punctuation for better readability
Greg Ward <greg@gerg.ca>
parents:
978
diff
changeset
|
370 similar. Anyone reviewing these patches will waste time on the error |
8cc6e90354a9
docs: tweak wording, punctuation for better readability
Greg Ward <greg@gerg.ca>
parents:
978
diff
changeset
|
371 in the earlier patch, and then the correction later on. |
978 | 372 |
373 You can avoid all this by amending the bad changeset and *evolving* | |
374 subsequent history. Here's how it works, assuming you have just | |
375 committed revision 13 and noticed the mistake in revision 11:: | |
376 | |
377 $ hg update 11 | |
378 [...fix mistake...] | |
379 $ hg amend | |
380 | |
381 At this point, revision 11 is *obsolete* and revisions 12 and 13—the | |
382 descendants of 11—are in a funny state: they are *unstable*. | |
383 | |
384 .. figure:: figures/figure-ug06.svg | |
385 | |
386 Figure 6: amending a changeset with descendants means the amended | |
387 changeset is obsolete but remains visible; its non-obsolete | |
388 descendants are *unstable*. The temporary amend commit, revision | |
389 14, is hidden because it has no non-obsolete descendants. | |
390 | |
391 All non-obsolete descendants of an obsolete changeset are unstable. An | |
392 interesting consequence of this is that revision 11 is still visible, | |
393 even though it is obsolete. Obsolete changesets with non-obsolete | |
394 descendants are not hidden. | |
395 | |
396 The fix is to *evolve* history:: | |
397 | |
398 $ hg evolve --all | |
399 | |
400 This is a separate step, not automatically part of ``hg amend``, | |
401 because there might be conflicts. If your amended changeset modifies a | |
402 file that one of its descendants also modified, Mercurial has to fire | |
403 up your merge tool to resolve the conflict. More importantly, you have | |
404 to switch contexts from "writing code" to "resolving conflicts". That | |
405 can be an expensive context switch, so Mercurial lets you decide when | |
406 to do it. | |
407 | |
408 The end state, after ``evolve`` finishes, is that the original | |
409 revisions (11-13) are obsolete and hidden. Their successor revisions | |
410 (15-17) replace them. | |
411 | |
412 .. figure:: figures/figure-ug07.svg | |
413 | |
414 Figure 7: evolve your repository (``hg evolve --all``) to take care | |
415 of instability. Unstable changesets become obsolete, and are | |
416 replaced by successors just like the amended changeset was. | |
417 | |
418 Example 8: Prune an older changeset | |
419 =================================== | |
420 | |
421 Let's say you've just committed the following changesets:: | |
422 | |
423 $ hg commit -m 'useful work' # rev 18 | |
424 $ hg commit -m 'debug hack' # rev 19 | |
425 $ hg commit -m 'more work' # rev 20 | |
426 | |
427 You want to drop revision 19, but keep 18 and 20. No problem:: | |
428 | |
429 $ hg prune 19 | |
430 1 changesets pruned | |
431 1 new unstable changesets | |
432 | |
433 As above, this leaves your repository in a funny intermediate state: | |
434 revision 20 is the non-obsolete descendant of obsolete revision 19. | |
435 That is, revision 20 is unstable. | |
436 | |
437 .. figure:: figures/figure-ug08.svg | |
438 | |
439 Figure 8: ``hg prune`` marks a changeset obsolete without creating | |
440 a successor. Just like with ``hg amend``, non-obsolete descendants | |
441 of the pruned changeset are now unstable. | |
442 | |
443 As before, the solution to unstable changesets is to evolve your | |
444 repository:: | |
445 | |
446 $ hg evolve --all | |
447 | |
448 This rebases revision 20 on top of 18 as the new revision 21, leaving | |
449 19 and 20 obsolete and hidden: | |
450 | |
451 .. figure:: figures/figure-ug09.svg | |
452 | |
453 Figure 9: once again, ``hg evolve --all`` takes care of instability. | |
454 | |
455 Example 9: Uncommit files from an older changeset (discard changes) | |
456 ======================================================================= | |
457 | |
458 As in example 5, let's say you accidentally commit some unrelated | |
459 changes together. Unlike example 5, you don't notice your mistake | |
460 immediately, but commit a new changeset on top of the bad one. :: | |
461 | |
462 $ echo 'this fixes bug 53' >> file1.c | |
463 $ echo 'debug hack' >> file2.c | |
464 $ hg commit -m 'fix bug 53' # rev 22 (oops) | |
465 $ echo 'and this handles bug 67' >> file1.c | |
466 $ hg commit -m 'fix bug 67' # rev 23 (fine) | |
467 | |
468 As with ``amend``, you need to travel back in time and repair revision | |
469 22, leaving your changes to ``file2.c`` back in the working | |
470 directory:: | |
471 | |
472 $ hg update 22 | |
473 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
474 $ hg uncommit file2.c | |
475 1 new unstable changesets | |
476 $ hg status | |
477 M file2.c | |
478 | |
479 Now your repository has unstable changesets, so you need to evolve it. | |
480 But ``hg evolve`` requires a clean working directory to resolve merge | |
481 conflicts, so you need to decide what to do with ``file2.c``. | |
482 | |
483 In this case, the change to ``file2.c`` was a temporary debugging | |
484 hack, so we can discard it and immediately evolve the instability away:: | |
485 | |
486 $ hg revert file2.c | |
487 $ hg evolve --all | |
488 move:[23] fix bug 67 | |
489 atop:[24] fix bug 53 | |
490 | |
491 Figure 10 illustrates the whole process. | |
492 | |
493 .. figure:: figures/figure-ug10.svg | |
494 | |
495 Figure 10: ``hg uncommit`` of a changeset with descendants results | |
496 in instability *and* a dirty working directory, both of which must | |
497 be dealt with. | |
498 | |
499 | |
500 Example 10: Uncommit files to an older changeset (keep changes) | |
501 =================================================================== | |
502 | |
503 This is very similar to example 9. The difference that this time, our | |
504 change to ``file2.c`` is valuable enough to commit, making things a | |
505 bit more complicated. The setup is nearly identical:: | |
506 | |
507 $ echo 'fix a bug' >> file1.c | |
508 $ echo 'useful but unrelated' >> file2.c | |
509 $ hg commit -u dan -d '11 0' -m 'fix a bug' # rev 26 (oops) | |
510 $ echo 'new feature' >> file1.c | |
511 $ hg commit -u dan -d '12 0' -m 'new feature' # rev 27 (fine) | |
512 | |
513 As before, we update back to the flawed changeset (this time, | |
514 revision 26) and ``uncommit``, leaving uncommitted changes to | |
515 ``file2.c`` in the working dir:: | |
516 | |
517 $ hg update -q 26 | |
518 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
519 $ hg uncommit -q file2.c # obsoletes rev 26, creates rev 28 | |
520 1 new unstable changesets | |
521 $ hg status | |
522 M file2.c | |
523 | |
524 This time, let's save that useful change before evolving:: | |
525 | |
526 $ hg commit -m 'useful tweak' # rev 29 | |
527 | |
528 Figure 11 shows the story so far: ``uncommit`` obsoleted revision 26 | |
529 and created revision 28, the successor of 26. Then we committed | |
530 revision 29, a child of 28. We still have to deal with the unstable | |
531 revision 27. | |
532 | |
533 .. figure:: figures/figure-ug11.svg | |
534 | |
535 Figure 11: Uncommitting a file and then committing that change | |
536 separately will soon result in a two-headed repository. | |
537 | |
538 This is where things get tricky. As usual when a repository has | |
539 unstable changesets, we want to evolve it:: | |
540 | |
541 $ hg evolve --all | |
542 | |
543 The problem is that ``hg evolve`` rebases revision 27 onto revision | |
544 28, creating 30 (the successor of 27). This is entirely logical: 27 | |
545 was the child of 26, and 26's successor is 28. So of course 27's | |
546 successor (30) should be the child of 26's successor (28). | |
547 Unfortunately, that leaves us with a two-headed repository: | |
548 | |
549 .. figure:: figures/figure-ug12.svg | |
550 | |
551 Figure 12: ``evolve`` takes care of unstable changesets; it does | |
552 not solve all the world's problems. | |
553 | |
554 As usual when faced with a two-headed repository, you can either merge | |
555 or rebase. It's up to you. | |
556 | |
557 | |
558 Example 11: Recover an obsolete changeset | |
559 ========================================= | |
560 | |
561 TODO |