Mercurial > evolve
annotate docs/user-guide.rst @ 1422:c868a69c29c5
evolve: distinct between '--all' and '--all --any'
Before this patch, evolve --all implied evolve --all --any. With this patch
evolve --all evolves all the aspiring descendants of the parent of the working
copy. evolve --all --any does what evolve --all did before: evolving all the
troubles in the repo.
We add anew function _aspiringdescendant for this purpose
author | Pierre-Yves David <pierre-yves.david@fb.com> |
---|---|
date | Mon, 22 Jun 2015 21:01:30 -0700 |
parents | 0683e3030316 |
children | 83d2c9637e89 |
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 | |
1268 | 251 |
252 Understanding revision numbers and hidden changesets | |
253 ==================================================== | |
254 | |
255 As the name implies, hidden changesets are normally not visible. If | |
256 you run ``hg log`` on the repository from Figure 2, Mercurial will | |
257 show revisions 0 and 3, but not 1 and 2. That's something you don't | |
258 see with plain vanilla Mercurial—normally, revision *N* is always | |
259 followed by revision *N* + 1. | |
260 | |
261 This is just the visible manifestation of hidden changesets. If | |
262 revision 0 is followed by revision 3, that means there are two hidden | |
263 changesets, 1 and 2, in between. | |
264 | |
265 To see those hidden changesets, use the ``--hidden`` option:: | |
978 | 266 |
1268 | 267 $ hg --hidden log --graph --template '{rev}:{node|short} {desc|firstline}\n' |
268 @ 3:934359450037 implement feature Y | |
269 | | |
270 | x 2:6c5f78d5d467 temporary amend commit for fe0ecd3bd2a4 | |
271 | | | |
272 | x 1:fe0ecd3bd2a4 implement feature Y | |
273 |/ | |
274 o 0:08c4b6f4efc8 init | |
275 | |
276 Note that changeset IDs are still the permanent, immutable identifier | |
277 for changesets. Revision numbers are, as ever, a handy shorthand that | |
278 work in your local repository, but cannot be used across repositories. | |
279 They also have the useful property of showing when there are hidden | |
280 changesets lurking under the covers, which is why this document uses | |
281 revision numbers. | |
282 | |
978 | 283 |
284 Under the hood: Prune an unwanted changeset | |
285 =========================================== | |
286 | |
287 ``prune`` (example 4 above) is the simplest history modification | |
288 command provided by ``evolve``. All it does is mark the specified | |
289 changeset(s) obsolete, with no successor/precursor relationships | |
290 involved. (If the working directory parent was one of the obsolete | |
291 changesets, ``prune`` updates back to a suitable ancestor.) | |
292 | |
293 .. figure:: figures/figure-ug03.svg | |
294 | |
295 Figure 3: pruning a changeset marks it obsolete with no successors. | |
296 | |
297 Under the hood: Uncommit changes to certain files | |
298 ================================================= | |
299 | |
300 In one sense, ``uncommit`` is a simplified version of ``amend``. Like | |
301 ``amend``, it obsoletes one changeset and leaves it with a single | |
302 successor. Unlike ``amend``, there is no ugly "temporary amend commit" | |
303 cluttering up the repository. | |
304 | |
305 In another sense, ``uncommit`` is the inverse of ``amend``: ``amend`` | |
306 takes any uncommitted changes in the working dir and “adds” | |
307 them to the working directory's parent changeset. (In reality, of | |
308 course, it creates a successor changeset, marking the original | |
309 obsolete.) In contrast, ``uncommit`` takes some changes in the working | |
310 directory's parent and moves them to the working dir, creating a new | |
311 successor changeset in the process. Figure 4 illustrates. | |
312 | |
313 .. figure:: figures/figure-ug04.svg | |
314 | |
315 Figure 4: uncommit moves some of the changes from the working | |
316 directory parent into the working dir, preserving the remaining | |
317 changes as a new successor changeset. (N.B. revision 4 is not shown | |
318 here because it was marked obsolete in the previous example.) | |
319 | |
320 | |
321 Under the hood: Fold multiple changesets together into one | |
322 ========================================================== | |
323 | |
324 The last basic example is folding multiple changesets into one, which | |
325 marks multiple changesets obsolete, replacing them all with a single | |
326 successor. | |
327 | |
328 .. figure:: figures/figure-ug05.svg | |
329 | |
330 Figure 5: fold combines multiple changesets into a single | |
331 successor, marking the original (folded) changesets obsolete. | |
332 | |
333 | |
334 Obsolete is not hidden | |
335 ====================== | |
336 | |
1269
250835154f8f
docs: explain that obsolete is not hidden
Greg Ward <greg@gerg.ca>
parents:
1268
diff
changeset
|
337 So far, every obsolete changeset we have seen is also hidden. However, |
250835154f8f
docs: explain that obsolete is not hidden
Greg Ward <greg@gerg.ca>
parents:
1268
diff
changeset
|
338 these are *not* the same thing—that's why they have different names. |
250835154f8f
docs: explain that obsolete is not hidden
Greg Ward <greg@gerg.ca>
parents:
1268
diff
changeset
|
339 It's entirely possible to have obsolete changesets that are not |
250835154f8f
docs: explain that obsolete is not hidden
Greg Ward <greg@gerg.ca>
parents:
1268
diff
changeset
|
340 hidden. We'll see examples of that soon, when we create *unstable* |
250835154f8f
docs: explain that obsolete is not hidden
Greg Ward <greg@gerg.ca>
parents:
1268
diff
changeset
|
341 changesets. |
250835154f8f
docs: explain that obsolete is not hidden
Greg Ward <greg@gerg.ca>
parents:
1268
diff
changeset
|
342 |
250835154f8f
docs: explain that obsolete is not hidden
Greg Ward <greg@gerg.ca>
parents:
1268
diff
changeset
|
343 Note that all hidden changesets are obsolete: hidden is a subset of |
250835154f8f
docs: explain that obsolete is not hidden
Greg Ward <greg@gerg.ca>
parents:
1268
diff
changeset
|
344 obsolete. |
978 | 345 |
346 | |
347 Life with ``evolve`` (advanced usage) | |
348 ------------------------------------- | |
349 | |
350 Now that you've got a solid understanding of how ``evolve`` works in | |
351 concert with changeset obsolescence, let's explore some more advanced | |
352 scenarios. All of these scenarios will involve *unstable* changesets, | |
353 which is an unavoidable consequence of obsolescence. What really sets | |
354 ``evolve`` apart from other history modification mechanisms is the | |
355 fact that it recognizes troubles like unstable changesets and provides | |
356 a consistent way for you to get out of trouble. | |
357 | |
358 (Incidentally, there are two other types of trouble that changesets | |
359 can get into with ``evolve``: they may be *divergent* or *bumped*. | |
360 Both of those states are more likely to occur when `sharing mutable | |
361 history`_, so we won't see them in this user guide.) | |
362 | |
363 .. _`sharing mutable history`: sharing.html | |
364 | |
365 | |
366 Example 7: Amend an older changeset | |
367 =================================== | |
368 | |
369 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
|
370 committed new changesets on top of them. :: |
978 | 371 |
372 $ hg commit -m 'fix bug 17' # rev 11 (mistake here) | |
373 $ hg commit -m 'cleanup' # rev 12 | |
374 $ hg commit -m 'feature 23' # rev 13 | |
375 | |
376 Traditionally, your only option is to commit an "oops" changeset that | |
377 fixes your mistake. That works, of course, but it makes you look bad: | |
378 you made a mistake, and the record of that mistake is recorded in | |
379 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
|
380 too bad: you cannot fix it.) |
978 | 381 |
382 More subtly, there now exist changesets that are *worse* than what | |
383 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
|
384 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
|
385 in the earlier patch, and then the correction later on. |
978 | 386 |
387 You can avoid all this by amending the bad changeset and *evolving* | |
388 subsequent history. Here's how it works, assuming you have just | |
389 committed revision 13 and noticed the mistake in revision 11:: | |
390 | |
391 $ hg update 11 | |
392 [...fix mistake...] | |
393 $ hg amend | |
394 | |
395 At this point, revision 11 is *obsolete* and revisions 12 and 13—the | |
396 descendants of 11—are in a funny state: they are *unstable*. | |
397 | |
398 .. figure:: figures/figure-ug06.svg | |
399 | |
400 Figure 6: amending a changeset with descendants means the amended | |
401 changeset is obsolete but remains visible; its non-obsolete | |
402 descendants are *unstable*. The temporary amend commit, revision | |
403 14, is hidden because it has no non-obsolete descendants. | |
404 | |
405 All non-obsolete descendants of an obsolete changeset are unstable. An | |
406 interesting consequence of this is that revision 11 is still visible, | |
407 even though it is obsolete. Obsolete changesets with non-obsolete | |
408 descendants are not hidden. | |
409 | |
410 The fix is to *evolve* history:: | |
411 | |
412 $ hg evolve --all | |
413 | |
414 This is a separate step, not automatically part of ``hg amend``, | |
415 because there might be conflicts. If your amended changeset modifies a | |
416 file that one of its descendants also modified, Mercurial has to fire | |
417 up your merge tool to resolve the conflict. More importantly, you have | |
418 to switch contexts from "writing code" to "resolving conflicts". That | |
419 can be an expensive context switch, so Mercurial lets you decide when | |
420 to do it. | |
421 | |
422 The end state, after ``evolve`` finishes, is that the original | |
423 revisions (11-13) are obsolete and hidden. Their successor revisions | |
424 (15-17) replace them. | |
425 | |
426 .. figure:: figures/figure-ug07.svg | |
427 | |
428 Figure 7: evolve your repository (``hg evolve --all``) to take care | |
429 of instability. Unstable changesets become obsolete, and are | |
430 replaced by successors just like the amended changeset was. | |
431 | |
432 Example 8: Prune an older changeset | |
433 =================================== | |
434 | |
435 Let's say you've just committed the following changesets:: | |
436 | |
437 $ hg commit -m 'useful work' # rev 18 | |
438 $ hg commit -m 'debug hack' # rev 19 | |
439 $ hg commit -m 'more work' # rev 20 | |
440 | |
441 You want to drop revision 19, but keep 18 and 20. No problem:: | |
442 | |
443 $ hg prune 19 | |
444 1 changesets pruned | |
445 1 new unstable changesets | |
446 | |
447 As above, this leaves your repository in a funny intermediate state: | |
448 revision 20 is the non-obsolete descendant of obsolete revision 19. | |
449 That is, revision 20 is unstable. | |
450 | |
451 .. figure:: figures/figure-ug08.svg | |
452 | |
453 Figure 8: ``hg prune`` marks a changeset obsolete without creating | |
454 a successor. Just like with ``hg amend``, non-obsolete descendants | |
455 of the pruned changeset are now unstable. | |
456 | |
457 As before, the solution to unstable changesets is to evolve your | |
458 repository:: | |
459 | |
460 $ hg evolve --all | |
461 | |
462 This rebases revision 20 on top of 18 as the new revision 21, leaving | |
463 19 and 20 obsolete and hidden: | |
464 | |
465 .. figure:: figures/figure-ug09.svg | |
466 | |
467 Figure 9: once again, ``hg evolve --all`` takes care of instability. | |
468 | |
469 Example 9: Uncommit files from an older changeset (discard changes) | |
470 ======================================================================= | |
471 | |
472 As in example 5, let's say you accidentally commit some unrelated | |
473 changes together. Unlike example 5, you don't notice your mistake | |
474 immediately, but commit a new changeset on top of the bad one. :: | |
475 | |
476 $ echo 'this fixes bug 53' >> file1.c | |
477 $ echo 'debug hack' >> file2.c | |
478 $ hg commit -m 'fix bug 53' # rev 22 (oops) | |
479 $ echo 'and this handles bug 67' >> file1.c | |
480 $ hg commit -m 'fix bug 67' # rev 23 (fine) | |
481 | |
482 As with ``amend``, you need to travel back in time and repair revision | |
483 22, leaving your changes to ``file2.c`` back in the working | |
484 directory:: | |
485 | |
486 $ hg update 22 | |
487 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
488 $ hg uncommit file2.c | |
489 1 new unstable changesets | |
490 $ hg status | |
491 M file2.c | |
492 | |
493 Now your repository has unstable changesets, so you need to evolve it. | |
494 But ``hg evolve`` requires a clean working directory to resolve merge | |
495 conflicts, so you need to decide what to do with ``file2.c``. | |
496 | |
497 In this case, the change to ``file2.c`` was a temporary debugging | |
498 hack, so we can discard it and immediately evolve the instability away:: | |
499 | |
500 $ hg revert file2.c | |
501 $ hg evolve --all | |
502 move:[23] fix bug 67 | |
503 atop:[24] fix bug 53 | |
504 | |
505 Figure 10 illustrates the whole process. | |
506 | |
507 .. figure:: figures/figure-ug10.svg | |
508 | |
509 Figure 10: ``hg uncommit`` of a changeset with descendants results | |
510 in instability *and* a dirty working directory, both of which must | |
511 be dealt with. | |
512 | |
513 | |
514 Example 10: Uncommit files to an older changeset (keep changes) | |
515 =================================================================== | |
516 | |
517 This is very similar to example 9. The difference that this time, our | |
518 change to ``file2.c`` is valuable enough to commit, making things a | |
519 bit more complicated. The setup is nearly identical:: | |
520 | |
521 $ echo 'fix a bug' >> file1.c | |
522 $ echo 'useful but unrelated' >> file2.c | |
523 $ hg commit -u dan -d '11 0' -m 'fix a bug' # rev 26 (oops) | |
524 $ echo 'new feature' >> file1.c | |
525 $ hg commit -u dan -d '12 0' -m 'new feature' # rev 27 (fine) | |
526 | |
527 As before, we update back to the flawed changeset (this time, | |
528 revision 26) and ``uncommit``, leaving uncommitted changes to | |
529 ``file2.c`` in the working dir:: | |
530 | |
531 $ hg update -q 26 | |
532 1 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
533 $ hg uncommit -q file2.c # obsoletes rev 26, creates rev 28 | |
534 1 new unstable changesets | |
535 $ hg status | |
536 M file2.c | |
537 | |
538 This time, let's save that useful change before evolving:: | |
539 | |
540 $ hg commit -m 'useful tweak' # rev 29 | |
541 | |
542 Figure 11 shows the story so far: ``uncommit`` obsoleted revision 26 | |
543 and created revision 28, the successor of 26. Then we committed | |
544 revision 29, a child of 28. We still have to deal with the unstable | |
545 revision 27. | |
546 | |
547 .. figure:: figures/figure-ug11.svg | |
548 | |
549 Figure 11: Uncommitting a file and then committing that change | |
550 separately will soon result in a two-headed repository. | |
551 | |
552 This is where things get tricky. As usual when a repository has | |
553 unstable changesets, we want to evolve it:: | |
554 | |
555 $ hg evolve --all | |
556 | |
557 The problem is that ``hg evolve`` rebases revision 27 onto revision | |
558 28, creating 30 (the successor of 27). This is entirely logical: 27 | |
559 was the child of 26, and 26's successor is 28. So of course 27's | |
560 successor (30) should be the child of 26's successor (28). | |
561 Unfortunately, that leaves us with a two-headed repository: | |
562 | |
563 .. figure:: figures/figure-ug12.svg | |
564 | |
565 Figure 12: ``evolve`` takes care of unstable changesets; it does | |
566 not solve all the world's problems. | |
567 | |
568 As usual when faced with a two-headed repository, you can either merge | |
569 or rebase. It's up to you. | |
570 | |
571 | |
572 Example 11: Recover an obsolete changeset | |
573 ========================================= | |
574 | |
1270 | 575 Sometimes you might obsolete a changeset, and then change your mind. You'll |
576 probably start looking for an “unobsolete” command to restore a changeset | |
577 to normal state. For complicated implementation reasons, that command | |
578 doesn't exist. (If you have already pushed an obsolescence marker to | |
579 another repo, then Mercurial would need a way to revoke that remote | |
580 obsolesence marker. That's a hard problem.) | |
581 | |
582 Instead, ``evolve`` provides a ``touch`` command to resurrect an | |
583 obsolete changeset. An unexpected quirk: you almost certainly need to | |
584 use ``--hidden``, since obsolete changesets tend to be hidden, and you | |
585 can't reference a hidden changeset otherwise. Typical usage thus looks | |
586 like :: | |
587 | |
588 $ hg --hidden touch REV | |
589 | |
590 This creates a new, normal changeset which is the same as ``REV``—except | |
591 with a different changeset ID. The new changeset will have the same parent | |
592 as ``REV``, and will be a successor of ``REV``. | |
593 | |
594 The current implementation of ``hg touch`` is not ideal, and is likely to | |
595 change in the future. Consider the history in Figure 12, where revision 27 | |
596 is obsolete and the child of 26, also obsolete. If we ``hg touch 27``, that | |
597 creates a new revision which is a non-obsolete child of 26—i.e., it is | |
598 unstable. It's also *divergent*, another type of trouble that we'll learn | |
599 about in the `next section`_. | |
600 | |
601 .. _`next section`: sharing.html |