comparison docs/tutorial/slides.md @ 3376:aad37ffd7d58

doc: import the training support Import the training support which was stored in a private-repository before.
author Boris Feld <boris.feld@octobus.net>
date Mon, 08 Jan 2018 11:46:53 +0100
parents
children 8406d9b06130
comparison
equal deleted inserted replaced
3375:1cb549cd6236 3376:aad37ffd7d58
1 ---
2 title: Changeset Evolution training
3 author: |
4 <span style="text-transform: none;"><small>Boris Feld<br/><a href="https://octobus.net">octobus.net</a></small></span>
5 ---
6
7 # Introduction
8
9 ## Welcome
10
11 Hello everyone, and welcome to this Changeset Evolution training. During this session, you will learn how to safely rewrite history with Mercurial and Evolve, and how to collaborate together with your colleagues while rewriting the history at the same time.
12
13 This training is designed to last approximately ¾ hours.
14
15 You will use this repository during the training: [https://bitbucket.org/octobus/evolve_training_repo](https://bitbucket.org/octobus/evolve_training_repo). Please clone it somewhere relevant.
16
17 ```bash
18 $ hg clone https://bitbucket.org/octobus/evolve_training_repo
19 $ cd evolve_training_repo
20 ```
21
22 Copy the provided hgrc to ensure a smooth training experience:
23
24 ```bash
25 $ cp hgrc .hg/hgrc
26 ```
27
28 This training support will contains commands you are expected to type and launch. These commands will be in the following format:
29
30 ```
31 $ COMMAND YOU ARE EXPECTED TO TYPE
32 output you are expecting to see
33 ```
34
35 ## Preliminary checks
36
37 #### Mercurial version
38
39 First let's use the following command to verify which version of Mercurial you are using:
40
41 ```
42 $ hg --version
43 Mercurial Distributed SCM (version 4.4.2)
44 (see https://mercurial-scm.org for more information)
45
46 Copyright (C) 2005-2017 Matt Mackall and others
47 This is free software; see the source for copying conditions. There is NO
48 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
49 ```
50
51 You need at least Mercurial version `4.1`. If you don't have a recent enough version, please call your instructor.
52
53 In order to activate the Evolve extension, add these lines in your user configuration (using the command `hg config --edit`):
54
55 ```ini
56 [extensions]
57 evolve =
58 topic =
59 ```
60
61 #### Mercurial extensions
62
63 Now let's check the version of your extensions. You will need all of these for the training:
64
65 ```
66 $ hg --version --verbose
67 [...]
68 evolve external 7.1.0
69 topic external 0.6.0
70 rebase internal
71 histedit internal
72 ```
73
74 # The Basics
75
76 <!-- #### What is Changeset Evolution?
77
78 With core Mercurial, changesets are permanent and history rewriting has been discouraged for a long time. You can
79 commit new changesets to modify your source code, but you cannot
80 modify or remove old changesets.
81
82 For years, Mercurial has included various commands that allow
83 history modification: ``rebase``, ``histedit``, ``commit --amend`` and so forth.
84 However, there's a catch: until now, Mercurial's various mechanisms for
85 modifying history have been *unsafe* and expensive, in that changesets were
86 destroyed (“stripped”) rather than simply hidden and still easy to recover.
87
88 Changeset Evolution makes things better by changing the behaviour of most existing
89 history modification commands so they use a safer mechanism (*changeset
90 obsolescence*, covered below) rather than the older, less safe *strip*
91 operation.
92
93 ``evolve`` is built on infrastructure in core Mercurial:
94
95 * *Phases* (starting in Mercurial 2.1) allow you to distinguish
96 mutable and immutable changesets.
97
98 * *Changeset obsolescence* (starting in Mercurial 2.3) is how
99 Mercurial knows how history has been modified, specifically when
100 one changeset replaces another. In the obsolescence model, a
101 changeset is neither removed nor modified, but is instead marked
102 *obsolete* and typically replaced by a *successor*. Obsolete
103 changesets usually become *hidden* as well. Obsolescence is a
104 disabled feature in Mercurial until you start using ``evolve``.
105
106 XXX More than just than obsolescence in core ? XXX
107
108 XXX The part below is a bit overselling XXX
109
110 Some of the things you can do with ``evolve`` are:
111
112 * Fix a mistake immediately: “Oops! I just committed a changeset
113 with a syntax error—I'll fix that and amend the changeset so no
114 one sees my mistake.” (While this is possible using default
115 features of core Mercurial, Changeset Evolution makes it safer.)
116
117 * Fix a mistake a little bit later: “Oops! I broke the tests three
118 commits back, but only noticed it now—I'll just update back to the
119 bad changeset, fix my mistake, amend the changeset, and evolve
120 history to update the affected changesets.”
121
122 * Remove unwanted changes: “I hacked in some debug output two
123 commits back; everything is working now, so I'll just prune that
124 unwanted changeset and evolve history before pushing.”
125
126 * Share mutable history with yourself: say you do most of your
127 programming work locally, but need to test on a big remote server
128 somewhere before you know everything is good. You can use
129 ``evolve`` to share mutable history between two computers, pushing
130 finely polished changesets to a public repository only after
131 testing on the test server.
132
133 * Share mutable history for code review: you don't want to publish
134 unreviewed changesets, but you can't block every commit waiting
135 for code review. The solution is to share mutable history with
136 your reviewer, amending each changeset until it passes review.
137
138 * Explore and audit the rewrite history of a changeset. Since Mercurial is
139 tracking the edits you make to a changeset, you can look at the history of
140 these edits. This is similar to Mercurial tracking the history of file
141 edits, but at the changeset level. -->
142
143 In this section, we are going to learn how to do basic history rewriting like rewriting a changeset or rebasing.
144
145 ### Amend
146
147 The smallest possible history rewriting is rewriting a changeset description message. We often save and close the editor too early, and/or haven't seen a typo.
148
149 It is very easy to fix a changeset description message, so let's do that. First be sure that you are in your clone of the `evolve_training_repo`. then update to the `typo` branch:
150
151 ```
152 $ hg update typo
153 ```
154
155 Check what the current repository looks like:
156
157 ~~~raw-file
158 output/fix-a-bug-base.log
159 ~~~
160
161 ~~~graphviz-file
162 graphs/fix-bug-1.dot
163 ~~~
164
165 We have a root commit and another based on it. Double-check that you are on the right changeset with the `hg summary` command:
166
167 ~~~raw-file
168 output/fix-a-bug-base-summary.log
169 ~~~
170
171 The current commit description message seems wrong, `Fx bug`, there is definitely a letter missing. Let's fix this typo with the `hg commit` command.
172
173 Usually, the `hg commit` is used to create new commit but we can use the ``--amend`` option to instead modify the current commit (see `hg help commit` for more information):
174
175 ~~~
176 $ hg commit --amend --message "Fix bug"
177 ~~~
178
179 Let's take a look at the repository now:
180
181 ~~~raw-file
182 output/amend-after.log
183 ~~~
184
185 ~~~graphviz-file
186 graphs/fix-bug-2.dot
187 ~~~
188
189 The logs before and after amending looks pretty similar, we are going to analyze the differences later. Did you catch the differences?
190
191 ### Rebase
192
193 <!-- XXX probably needs a sentence about the merge (Why do you want to avoid it) XXX -->
194
195 Let's try to rebase something now. Let's say that you have a branch named `build/linuxsupport-v2` which was started on another branch named `build/v2`. Everything was fine until `build/v2` grew a new commit, and now you want to rebase `build/linuxsupport-v2` on top of `build/v2` to be up-to-date with other the changes:
196
197 ```
198 $ hg update build/linuxsupport-v2
199 ```
200
201 ~~~raw-file
202 output/rebase-before.log
203 ~~~
204
205 ~~~graphviz-file
206 graphs/rebase-before.dot
207 ~~~
208
209 <!-- XXX-REVIEW: Explain rebase CLI interface -->
210
211 Let's rebase our branch on top of `build/v2` with the `hg rebase` command. The `hg rebase` command have many ways to select commits:
212
213 1. Explicitly select them using "--rev".
214 2. Use "--source" to select a root commit and include all of its descendants.
215 3. Use "--base" to select a commit; rebase will find ancestors and their descendants which are not also ancestors of the destination.
216 4. If you do not specify any of "--rev", "source", or "--base", rebase will use "--base ." as above.
217
218 For this first example, we are gonna stays simple and explicitly select the commits we want to rebase with the `--rev` option.
219
220 The `hg rebase` command also accepts a destination with the ``--dest`` option. And finally, as we are using named branches, don't forget to use the `--keepbranches` or the rebased commits will be on the wrong branch:
221
222 ~~~raw-file
223 output/rebase.log
224 ~~~
225
226 Now we have a nice, clean and flat history:
227
228 ~~~raw-file
229 output/rebase-after.log
230 ~~~
231
232 ~~~graphviz-file
233 graphs/rebase-after.dot
234 ~~~
235
236 For more details about how to use the `hg rebase` command, see `hg help rebase`.
237
238 ### Under the hood
239
240 What did happened when we just ran the `hg amend` and `hg rebase` commands? What was done exactly to make the whole process work seamlessly?
241
242 Let's go back to our previous amend example.
243
244 ##### Amend
245
246 When we did our amend, the status of the repository was:
247
248 ~~~raw-file
249 output/behind-the-hood-amend-before-hash-hidden.log
250 ~~~
251
252 ~~~graphviz-file
253 graphs/fix-bug-1.dot
254 ~~~
255
256 And after the amend, the repository looked like:
257
258 ~~~raw-file
259 output/behind-the-hood-amend-after.log
260 ~~~
261
262 ~~~graphviz-file
263 graphs/fix-bug-2.dot
264 ~~~
265
266 Do you see what is the difference?
267
268 The big difference, apart from the fixed changeset message, is the revision hash and revision number. The `Fix bug` revision changed from `d2eb2ac6a5bd` to `708369dc1bfe`. It means that the fixed changeset is a new one. But where did the old changeset go?
269
270 It didn't actually go very far, as it just became **hidden**. When we rewrite a changeset with the Evolve extension, instead of blindly delete it, we create a new changeset and hide the old one, which is still there, and we can even see it with the `--hidden` option available on most Mercurial commands:
271
272 ~~~raw-file
273 output/under-the-hood-amend-after-log-hidden.log
274 ~~~
275
276 Notice the `x` in the log output which shows that a changeset is hidden.
277
278 In addition to hiding the original changeset, we are also storing additional information which is recording the relation between a changeset, the **precursor** and its **successor**. It basically stores the information that the commit **X** was rewritten into the commit **Y** by the user **U** at the date **D**. This piece of information is stored in something called an **obsolescence marker**. It will be displayed like this:
279
280 ~~~graphviz-file
281 graphs/fix-bug-3.dot
282 ~~~
283
284 Here the commit **5d48a444aba7** was rewritten into **708369dc1bfe**. Also please notice the difference of style of the commit **5d48a444aba7**, that's because it have been rewritten.
285
286 ##### Rebase
287
288 **Successors** don't need to share anything with their **precursor**. They could have a different description message, user, date or even parents.
289
290 Let's look at our earlier rebase example. The status before the rebase was:
291
292 ~~~raw-file
293 output/behind-the-hood-rebase-before-hash-hidden.log
294 ~~~
295
296 ~~~graphviz-file
297 graphs/rebase-before.dot
298 ~~~
299
300 And after it was:
301
302 ~~~raw-file
303 output/behind-the-hood-rebase-after.log
304 ~~~
305
306 ~~~graphviz-file
307 graphs/rebase-after.dot
308 ~~~
309
310 Did the same thing happen under the hood?
311
312 Yes, exactly! The old changesets are still around, and they are just hidden.
313
314 ~~~raw-file
315 output/rebase-after-hidden.log
316 ~~~
317
318 And we created three **obsolescence markers**, between each rebased commit and its **successor**:
319
320 ~~~graphviz-file
321 graphs/rebase-after-hidden.dot
322 ~~~
323
324 ### Evolution History
325
326 Mercurial is designed to track the history of files. Evolution goes beyond, and tracks the history of the history of files. It basically tracks the different versions of your commits.
327
328 As it is a new dimension of history, the classical Mercurial commands are not always the best to visualize this new history.
329
330 We have seen that we can see the **hidden** changesets with the `--hidden` option on `hg log`:
331
332 ~~~raw-file
333 output/under-the-hood-amend-after-log-hidden.log
334 ~~~
335
336 To visualize the **obsolescence history** of a particular changeset, we can use the dedicated command `hg obslog`. The option are quite similar to `hg log` (you can read `hg help obslog` for more information):
337
338 ~~~raw-file
339 output/under-the-hood-amend-after-obslog.log
340 ~~~
341
342 We can even print what changed between the two versions with the `--patch` option:
343
344 ~~~raw-file
345 output/under-the-hood-amend-after-obslog-patch.log
346 ~~~
347
348 Obslog works both ways, as it can display **precursors** and **successors** with the `--all` option:
349
350 ```raw-file
351 output/under-the-hood-amend-after-obslog-no-all.log
352 ```
353
354 ~~~raw-file
355 output/under-the-hood-amend-after-obslog-all.log
356 ~~~
357
358 ~~~graphviz-file
359 graphs/fix-bug-3.dot
360 ~~~
361
362 We can also use obslog on the changesets that we rebased earlier:
363
364 ~~~raw-file
365 output/under-the-hood-rebase-after-obslog.log
366 ~~~
367
368 Why the `hg obslog` command is only showing two commits while we rebased three of them?
369
370 ```raw-file
371 output/under-the-hood-rebase-after-obslog-branch.log
372 ```
373
374 And why the `hg obslog` command show disconnected graphs when asking for the obslog of the whole branch?
375
376 ~~~graphviz-file
377 graphs/rebase-after-hidden.dot
378 ~~~
379
380 While these two obsolescence logs look very similar —because they show a similar change—, the two changesets log histories looked quite different.
381
382 Using the `hg log` command to understand the Evolution history is hard because it is designed for displaying the files history, not the Evolution history. The `hg obslog` has been specially designed for this use-case and is more suited for this use-case.
383
384 #### TortoiseHG
385
386 TortoiseHG should be able to display obsolescence history for your repositories.
387
388 To display all the **hidden** commits, we need to click on the **search icon**, then on the **Show/Hide hidden changesets** at the right of the **filter** check box. It is also possible to provide a *revset* to filter the repository, for example `:6 + ::20` to display only the revisions we have been working with until now:
389
390 ![](img/thg-obs.png)
391
392 <!-- #### Deroulement
393
394 Travail chacun de son côté pour apprendre à utiliser:
395
396 - Réecriture de changeset
397 - Affichage de l'obsolescence, log, obslog
398
399
400 - Vérifier que chacun sait utiliser les commandes de base
401 - Vérifier que chacun sait utiliser les commandes de visu, hg log, hg log -G, thg?
402 => Pas trop longtemps // répartir
403
404 - Créer un commit
405 - Le amend sans evolve == bundle
406 - Strip?
407 - rebase sans evolve?
408 - Why is it bad? exemple
409 (Peut-etre pas leur faire pratiquer amend sans evolve, ca prends du temps)
410
411 - With evolve, now
412 - Activate it, check version
413 - Amend with evolve
414 - rebase with evolve
415
416 - What happened?
417 - View obs-history, hg log, obslog -->
418
419
420 # Medium level
421
422 ## More rewriting commands
423
424 The `hg amend` and `hg rebase` commands are the foundations for changeset evolution in Mercurial. You could do everything with these, but, luckily for us, the evolve extension provides human-friendly commands for common needs. We are going to see them now:
425
426 ### Amend
427
428 The Evolve extension provides its own `hg amend` command, which is similar to the `hg commit --amend` that we used previously, and adds several nice features:
429
430 - The `-e`/`--edit` option edits the commit message in an editor, which is not opened by default any more.
431 - The user and date can be updated to the current ones with the `-U`/`--current-user` and `-D`/`--current-date` options.
432 - More capabilities for rewriting the changeset.
433
434 The `hg amend` command accepts either file paths, to add all the modifications on these files in the current changeset, or the `-i`/`--interactive` option to select precisely what to add in it.
435
436 We are going to use it to rewrite the author of the changeset:
437
438 ```
439 $ hg update amend-extract
440 ```
441
442 We have two commits on the **amend-extract** branch:
443
444 ```raw-file
445 output/amend-extract-before.log
446 ```
447
448 The user for the **amend-extract** head seems wrong, so let's fix it with the `hg amend` command:
449
450 ```raw-file
451 output/amend-user.log
452 ```
453
454 Now let's check that the user has been amended correctly:
455
456 ```raw-file
457 output/amend-user-after-export.log
458 ```
459
460 The user is the good one, but the diff looks weird. It seems that both a bad file **and** an incorrect line have slipped in this commit. We need to fix that.
461
462 There are several solutions here, and we could manually edit the file and amend it. But, luckily for us, the `hg amend` command also has a very helpful option named `--extract` that will help us.
463
464 ### Amend extract
465
466 The `hg amend` command is meant to move file modifications from your working directory to the current changeset (which is considered as the parent of working directory). `hg amend` also provides the option `--extract` that can be used to invert the meaning of the command: with this option, `hg amend` will move the file modifications from your current changeset to your working directory.
467
468 This is often used to remove a file or a line that is not meant to be in the current commit.
469
470 As usual, we can either pass file paths or use the `-i` option to select which lines to extract.
471
472 First, let's extract the badfile:
473
474 ```raw-file
475 output/amend-extract-badfile.log
476 ```
477
478 Now let's check the status of the changeset and the working directory:
479
480 ```raw-file
481 output/amend-extract-badfile-after-export.log
482 ```
483
484 The file is not included in the commit anymore! Did it just vanish? What if you wanted to keep it and, for example, put it in another commit?
485
486 Don't worry, the extracted files and lines still are in your working directory:
487
488 ```raw-file
489 output/amend-extract-badfile-after-status.log
490 ```
491
492 As we are not going to need this file anymore, let's forget it with the `hg revert` command:
493
494 ```raw-file
495 output/amend-extract-badfile-after-revert.log
496 ```
497
498 Also don't forget to remove the file:
499
500 ```bash
501 $ rm badfile
502 ```
503
504 Ok. Now we still have a line to extract from our commit, so let's use the handy interactive mode of `hg amend --extract` to extract lines:
505
506 ```raw-file
507 output/amend-extract.log
508 ```
509
510 Much better! One last thing, as the line that we extracted is still in our working directory, just like when we extracted a file:
511
512 ```raw-file
513 output/amend-extract-after-status.log
514 ```
515
516 ```raw-file
517 output/amend-extract-after-diff.log
518 ```
519
520 Don't forget to revert the change, as we are not going to need it any more:
521
522 ```raw-file
523 output/amend-extract-after-revert.log
524 ```
525
526 Now let's take a look at the obsolescence history:
527
528 ```raw-file
529 output/amend-extract-after-obslog.log
530 ```
531
532 The obslog is read from bottom to top:
533
534 - First we rewrite the user,
535 - Then we extracted a whole file,
536 - Then we extracted a line from a file
537
538 We have made three changes that generated three **successors**.
539
540 ```graphviz-file
541 graphs/amend-extract-after-hidden.dot
542 ```
543
544 ### Fold
545
546 Sometimes we want to group together several consecutive changesets. Evolve has a command for that: `hg fold`. First, let's update to the right branch:
547
548 ```
549 $ hg update fold
550 ```
551
552 Three changesets change the same file, and they could be folded together. This would make a cleaner and more linear history, and hide those pesky intermediate changesets:
553
554 ```raw-file
555 output/fold-before.log
556 ```
557
558 ```graphviz-file
559 graphs/fold-before.dot
560 ```
561
562 We all have been in a similar situation. Let's make a nice and clean changeset with fold:
563
564 ```raw-file
565 output/fold.log
566 ```
567
568 That was easy!
569
570 ```raw-file
571 output/fold-after.log
572 ```
573
574 ```raw-file
575 output/fold-after-hidden.log
576 ```
577
578 Can you imagine what the graphs will looks like?
579
580 ```raw-file
581 output/fold-after-hidden-obslog.log
582 ```
583
584 ```graphviz-file
585 graphs/fold-after-hidden.log
586 ```
587
588 ### Split
589
590 Sometimes you want to `fold` changesets together, and sometimes you want to `split` a changeset into several ones, because it is too big.
591
592 ```
593 $ hg update split
594 ```
595
596 Evolve also has a command for that, `hg split`:
597
598 ```raw-file
599 output/split-before.log
600 ```
601
602 ```graphviz-file
603 graphs/split-before.dot
604 ```
605
606 Split accepts a list of revisions and will interactively ask you how you want to split them:
607
608 ```raw-file
609 output/split.log
610 ```
611
612 Now let's check the state of the repository:
613
614 ```raw-file
615 output/split-before-after.log
616 ```
617
618 ```graphviz-file
619 graphs/split-before-after-hidden.dot
620 ```
621
622 It looks good. What about the obsolescence history?
623
624 ```raw-file
625 output/split-after-obslog.log
626 ```
627
628 ```raw-file
629 output/split-after-obslog-all.log
630 ```
631
632 ### Prune
633
634 After rewriting and rebasing changesets, the next common use case for history rewriting is removing a changeset.
635
636 But we can't permanently remove a changeset without leaving a trace. What if other users are working with the changeset that we want to remove?
637
638 The common solution is to mark the changeset as removed, and simulate the fact that it has been removed.
639
640 This is why the Evolve extension is offering the `prune` command. Let's try to prune a changeset:
641
642 ```
643 $ hg update prune
644 ```
645
646 ```raw-file
647 output/prune-before.log
648 ```
649
650 ```graphviz-file
651 graphs/prune-before.dot
652 ```
653
654 `prune` is easy to use, just give it the revisions you want to prune:
655
656 ```raw-file
657 output/prune.log
658 ```
659
660 Now the changeset is not visible any more:
661
662 ```raw-file
663 output/prune-after.log
664 ```
665
666 But we can still access it with the `--hidden` option:
667
668 ```raw-file
669 output/prune-after-hidden.log
670 ```
671
672 The output of `obslog` changes a bit when displaying pruned changesets:
673
674 ```raw-file
675 output/prune-after-obslog.log
676 ```
677
678 ```graphviz-file
679 graphs/prune-after-hidden.dot
680 ```
681
682 ### Histedit
683
684 The `hg histedit` command is a power-user command. It allows you to edit a linear series of changesets, and applies a combination of operations on them:
685
686 - 'pick' to [re]order a changeset
687 - 'drop' to omit changeset
688 - 'mess' to reword the changeset commit message
689 - 'fold' to combine it with the preceding changeset (using the later date)
690 - 'roll' like fold, but discarding this commit's description and date
691 - 'edit' to edit this changeset (preserving date)
692 - 'base' to checkout changeset and apply further changesets from there
693
694 It's similar to the `git rebase -i` command.
695
696 First, let's update to the right branch:
697
698 ```
699 $ hg update histedit
700 ```
701
702 ```raw-file
703 output/histedit-before-log.log
704 ```
705
706 ```graphviz-file
707 graphs/histedit-before.dot
708 ```
709
710 When launching the `hg histedit` command, an editor will show up with the following contents:
711
712 ```raw-file
713 output/histedit-no-edit.log
714 ```
715
716 Swap the first two lines with your text editor:
717
718 ```raw-file
719 output/histedit-commands.log
720 ```
721
722 Save and exit. Histedit will apply your instructions and finish.
723
724 Let's see the state of the repository:
725
726 ```raw-file
727 output/histedit-after-log.log
728 ```
729
730 ```raw-file
731 output/histedit-after-log-hidden.log
732 ```
733
734 ```graphviz-file
735 graphs/histedit-after-hidden.dot
736 ```
737
738 <!-- #### Deroulement
739
740 - prune with evolve
741
742 - advanced commands
743 - fold
744 - split -->
745
746 ## Stack
747
748 ### Stack definition
749
750 One big problem when working with a DVCS to identify and switch between the different features/bugfixes you are working on.
751
752 ### Named branches
753
754 One solution is to use **named branches**. Named branches are a battle-tested, long-supported solution in Mercurial. Basically, a branch name is stored inside each changeset.
755
756 This solution has several advantages:
757
758 - It's supported in all recent-ish Mercurial versions.
759 - It's simple to use.
760 - Most tools are supporting it.
761
762 But it also has several disadvantages:
763
764 - Branches do not disappear once they are merged. You need to explicitely close them with `hg commit --close-branch`.
765 - Branches are lost when rebasing them without the `--keepbranches` option of the `hg rebase` command.
766 - New branches needs to be explicitly pushed with the `--new-branch` option of the `hg push` command.
767
768 We will use named branches for this training, but other solutions are possible, like [topics](https://www.mercurial-scm.org/doc/evolution/tutorials/topic-tutorial.html).
769
770 <!-- #### Topics
771 -->
772
773 ### Stack
774
775 The `topic` extension provides a command to show your current stack, no matter how you defined it. Let's try it on some changesets that we rewrote earlier:
776
777 ```
778 $ hg update typo
779 ```
780
781 ```raw-file
782 output/stack-typo.log
783 ```
784
785 The stack output shows three important data:
786
787 - First, which branch you are working on (a.k.a. the **current** branch).
788 - Then, all the commits that you are currently working on, with the current one highlighted.
789 - Finally, which commit your branch is based on (**b0**).
790
791 This branch is not very interesting, so let's move to another one.
792
793 ```
794 $ hg update build/linuxsupport-v2
795 ```
796
797 ```raw-file
798 output/stack-rebase.log
799 ```
800
801 This is more interesting, as now we can see all the three changesets grouped together in the same view. The stack view provides a nice and linear view, even if the changesets are not immediate neighbors.
802
803 ### Stack movement
804
805 There is an easy way to navigate in your stack, the `hg next` and `hg prev` commands:
806
807 ```raw-file
808 output/stack-rebase-prev-from-b3.log
809 ```
810
811 ```raw-file
812 output/stack-rebase-stack-b2.log
813 ```
814
815 And now for the `hg next` command:
816
817 ```raw-file
818 output/stack-rebase-next-from-b2.log
819 ```
820
821 ```raw-file
822 output/stack-rebase.log
823 ```
824
825 The stack view also displays nice and easy relative ids for these changesets. You can use theses ids in all commands, for example with the `hg export` command:
826
827 ```raw-file
828 output/stack-rebase-export-b1.log
829 ```
830
831 Or with the `hg update` command:
832
833 ```raw-file
834 output/stack-rebase-update-b2.log
835 ```
836
837 These ids are handy because you don't need to manipulate changeset ids or revision numbers: contrary to the latters, the formers won't be affected by history edition. They only depend on their order in the branch.
838
839 ```raw-file
840 output/stack-rebase-stack-b2.log
841 ```
842
843 ### Edit mid-stack
844
845 Now that we are in the middle of a stack, let's try amending a commit. The current commit message ends with a dot `.`, and we want to remove it:
846
847 ```raw-file
848 output/stack-rebase-stack-b2.log
849 ```
850
851 ```raw-file
852 output/edit-mid-stack.log
853 ```
854
855 The message `1 new orphan changesets` means that, by amending a changeset having a child, this child is now **unstable**, as we can see with the `hg stack` command:
856
857 ```raw-file
858 output/edit-mid-stack-after-stack.log
859 ```
860
861 `hg stack` tries to simplify the view for you. We have amended **b2**, and **b3**'s parent is the precursor version of **b2**, so it is not stable any more. It is now **orphan**.
862
863 For once, let's use log to see in detail in which situation we are:
864
865 ```raw-file
866 output/edit-mid-stack-after-log.log
867 ```
868
869 ```graphviz-file
870 graphs/edit-mid-stack-after.dot
871 ```
872
873 How can we resolve this situation? It is actually very easy, and we are going to see how in the next section.
874
875 <!-- #### Deroulement
876
877 Tout seul:
878
879 - Topic? stack?
880
881 - Comment définir ce sur quoi on travaille?
882
883 - Solution possible: named branches
884 - Avantages des branches nommées
885 - Inconvénients des branches nommées
886
887 - Solution possible: topic
888 - Avantages des topic
889 - Inconvénients des topic
890 - Commands: hg stack, hg topics, hg topics --age, hg topics --verbose
891 (Pas forcément topic, risque de confusion)
892
893 - Visualiser une stack avec hg stack, hg show stack?
894 - Se déplacer dans une stack avec hg prev/hg next
895
896 - Editer au milieu d'une stac
897
898 - Absorb? (Pas sous windows dur à installer) -->
899
900 ## Basic instabilities + stabilization
901
902 Instabilities are a normal step when using Evolve-powered workflows. Several tools are provided to fix them smoothly.
903
904 #### Log
905
906 First, let's clarify some vocabulary. An **obsolete** changeset is a changeset that has been rewritten. In the current stack, only one commit is `obsolete`:
907
908 ```raw-file
909 output/basic-stabilize-before-log-obsolete.log
910 ```
911
912 A changeset can also be **unstable**, meaning that it could be subject to one or more **instabilities**:
913
914 * **orphan**, a changeset whose an ancestor is **obsolete**.
915 * **content-divergent**, a changeset which has been rewritten in two different versions.
916 * **phase-divergent**, a changeset which has been both rewritten and published.
917
918 For the moment, we will only see the **orphan** instability. We can display the **instabilities** of a commit with the `{instabilities}` template keyword:
919
920 ```raw-file
921 output/basic-stabilize-before-log-instabilities.log
922 ```
923
924 Here we have also one **orphan** commit, which is the child of the **obsolete** commit.
925
926 #### Evolve --list
927
928 The `hg evolve` command has a `--list` option which can list all the instabilities of your repository.
929
930 ```raw-file
931 output/basic-stabilize-before-evolve-list.log
932 ```
933
934 #### TortoiseHG
935
936 Tortoise HG also has a nice support for displaying the instabilities of your repository:
937
938 ![](img/thg-mid-stack.png)
939
940 If you want to filter to get a better view, you can use the *revset* `branch(build/linuxsupport-v2)`:
941
942 ![](img/thg-mid-stack-filter.png)
943
944 #### Stabilization using `hg next --evolve`
945
946 ```raw-file
947 output/edit-mid-stack-after-stack.log
948 ```
949
950 In our current situation, a simple solution to solve the instability is to use the `hg next` command with the `--evolve` option. It will update to the next changeset on the stack, and stabilize it if necessary:
951
952 ```raw-file
953 output/basic-stabilize-next-evolve.log
954 ```
955
956 Here, it just rebased our old version of `b3` on top of the new version of `b2`.
957
958 And now `hg stack` shows us a clean view again:
959
960 ```raw-file
961 output/basic-stabilize-after-stack.log
962 ```
963
964 That's better!
965
966 ```graphviz-file
967 graphs/basic-stabilize-after-stack.dot
968 ```
969
970 <!-- #### hg evolve
971
972 XXX-REVIEW: Later -->
973
974 # Advanced
975
976 ## Moving change from one commit to another
977
978 Create two commits:
979
980 - The first one create a new file, add some content in it.
981 - The second one create another file and modify the first file.
982
983 Now try to move the change on the first file present in the second commit back in the first commit so that the first commit contains all change on the first file and the second change contains all changes on the second file.
984
985 ## Exchange
986
987 Coming Soon™
988
989 <!-- ## Exchange -->
990
991 <!-- #### Obsolescence History Synchronization
992
993 XXX Too theoritical (except first sentence maybe) XXX
994
995 While obsolescence markers are already useful locally, they unlock their true power when they are exchanged. They are the piece of information that are fundamental to achieve the goal of synchronizing repositories state.
996
997 If two people starts with the same repository and they each make some modifications, once exchanging all their obsolescence marker with their partner; they should have the same repository state.
998
999 Given a repository state R, if user A creates obs-markers OBSA and user B creates obs-markers OBSB, `R + OBSA + OBSB = R + OBSB + OBSA`.
1000
1001 This characteristic is the foundation to make people confident with their modification as they know that they will be able to synchronize with someone and have exactly the same state. XXX-REVIEW BOF
1002
1003 #### When are exchanged obsolescence markers
1004
1005 Obsolescence markers are exchanges during all usual exchange methods:
1006
1007 - Obsolescence markers related to pushed heads are pushed during `hg push`.
1008 - Obsolescence markers related to pulled heads are also pulled during `hg pull`.
1009 - Obsolescence markers are included in bundles.
1010
1011 New obsolescence markers are automatically applied, so after a `pull` some changesets could become obsolete as they have been rewritten by a new changeset you just pulled.
1012
1013 XXX-REVIEW: Add example?
1014
1015 The obsolescence markers only apply to draft changesets though.
1016
1017 ###### Let's exchange obsmarkers
1018
1019 Let's try to push and pull some obsolescence-markers, first copy your repository somewhere else, for example:
1020
1021 ```raw-file
1022 output/basic-exchange-clone.log
1023 ```
1024
1025 #### Phases
1026
1027 XXX Too theoritical XXX
1028
1029 There is a dimension that have been overlooked until now. **Phases**. What are phases? Phases is an information about a changeset status, a changeset could be in one phase at any time:
1030
1031 * **draft**, the default phase a changeset is just after committing it. This phase denotes that the changeset is still a work in progress. It could be rewritten, rebased, splitted, folded or even pruned before it's considered finished. This state allow a changeset to evolve into another version.
1032 * **public**, the phase a changeset is when it's considered finished. The changeset would likely have been reviewed, tested and even released when they are in this state. This state forbids any rewriting on changeset which are public.
1033 * **secret**, this phase is for changesets that should never be shared. It could be local-only modifications for your environment or a way to commit credentials without sharing it outside. This state allow a changeset to be rewritten, like to be rebased on the most up-to-date head for example.
1034
1035 Phase are about changesets but they are not part of the commit information, meaning that changing the phase of a changeset does not change it's changeset hash.
1036
1037 These phases are ordered (public < draft < secret) and no changeset can be in
1038 a lower phase than its ancestors. For instance, if a changeset is public, all
1039 its ancestors are also public. Lastly, changeset phases should only be changed
1040 towards the public phase.
1041
1042 Changeset are created in the **draft** phase by default and move to the **public** phase in several scenarios.
1043
1044 #### Phase movement
1045
1046 The original scenario for **phases** is to permits local rewriting of changesets that have not been pushed. You create draft changesets, you test them locally, possibly amend them, rebased them or clean it then you push it to a server and they become **public** at this occasion.
1047
1048 While this scenario is pretty sensible, not altering shared commit make a lot of problems disappears, move powerful workflows could be unlocked when decoupling the sharing part with the publishing part.
1049
1050 By default, hg server are in **publishing** mode, meaning that:
1051
1052 - all draft changesets that are pulled or cloned appear in phase public on the client.
1053
1054 - all draft changesets that are pushed appear as public on both client and server.
1055
1056 - secret changesets are neither pushed, pulled, or cloned.
1057
1058 Hg servers could also be configured into **non-publishing** mode with this configuration:
1059
1060 ```ini
1061 [phases]
1062 publish = False
1063 ```
1064
1065 When pushing to a **non-publishing** mode, draft changesets are not longer made **public** anymore, allowing people and teams to share unfinished works. This way, it's still possible to edit a changeset after sharing it, meaning that:
1066
1067 - a changeset could be updated after it has been reviewed.
1068 - a changeset could be updated after a Continuous Integration tool show that some tests on some platforms are broken.
1069 - a changeset could be updated after a co-worker tried implementing another feature on top of it.
1070
1071 #### Usual phase workflow
1072
1073 While sharing unfinished works is powerful, move **draft** changeset to the **public** phase when pushing them to **publishing** server is powerful by its simplicity. Its easy to understand as **non-publishing** servers could be seen as work-in-progress while **publishing** servers is meant for public, finished work that you commit to never alter. XXX-REVIEW Bof
1074
1075 The usual way of having both advantages is to have both a **non-publishing** server where developers push for sharing work and asking for review and another **non-publishing** server when ready changesets are pushed, marking them as **public**.
1076
1077 This way the **publishing** repository will only contains **public** changesets while the **non-publishing** one will contains all the **public** changesets plus all the **drafts** changesets.
1078
1079 #### Phase visualization
1080
1081 Phase is not shown by default in `hg log`, but we can ask for it with the `{phase}` template:
1082
1083 ```raw-file
1084 output/split-after-log-phase.log
1085 ```
1086
1087 It's also possible to use `hg phase` to recover the phase of a revision(s):
1088
1089 ```raw-file
1090 output/split-after-phase.log
1091 ```
1092
1093 You might wondered why you saw different forms in the graphs before, that was the phase that were shown. From now on, public changesets will be shown as circles, drafts changesets will be shown as hexagons and secrets changesets will be shown as squares:
1094
1095 ```graphviz-file
1096 graphs/phases.dot
1097 ```
1098
1099 #### Phase selection
1100
1101 Phase have a few revsets for selecting changesets by their phases:
1102
1103 - `public()`, select all public changesets.
1104 - `draft()`, select all draft changesets.
1105 - `secrets()`, select all secret changesets.
1106
1107 It could be used to:
1108
1109 - select all non-public changesets with `hg log -r "not public()"`.
1110 - change all secret changesets to draft with `hg phase --draft "secret()"`. -->
1111
1112 <!-- #### Deroulement
1113
1114 Toujours tout seul:
1115
1116 - push / pull
1117 - phases -->
1118
1119 <!-- ## Advanced -->
1120
1121 <!-- #### Deroulement
1122
1123 Advances use-cases:
1124
1125 - Move part of a changeset to another (split+fold) -->
1126
1127 <!-- ## Let's start the fun -->
1128
1129 <!-- #### Deroulement
1130
1131 À deux:
1132
1133 - troubles, divergence, orphan
1134 - troubles visualization
1135 - troubles resolution
1136 - collaboration workflow
1137
1138 Parler du happy path d'abord -->
1139
1140 <!-- ## Content to integrate (presentation old content)
1141
1142 #### Once upon a time
1143
1144 #### You fix a bug
1145
1146 (With a small typo)
1147
1148 ~~~graphviz-file
1149 graphs/fix-bug-1.dot
1150 ~~~
1151
1152 #### You write more code
1153
1154 <img src="https://media0.giphy.com/media/13GIgrGdslD9oQ/giphy.gif">
1155
1156 #### Urgent merge
1157
1158 <img src="https://media.giphy.com/media/OBnwDJW77acLK/giphy.gif">
1159
1160 #### Fix the fix
1161
1162 But it's easy to fix them:
1163
1164 ~~~ {.sh}
1165 hg commit --amend -m "Fix bug"
1166 ~~~
1167
1168 ~~~graphviz-file
1169 graphs/fix-bug-2.dot
1170 ~~~
1171
1172 #### Too fast!
1173
1174 But wait you had local changes! And they get incorporated into the amend.
1175
1176 <img src="https://media1.giphy.com/media/vMiCDfoKdJP0c/giphy.gif">
1177
1178 10 more minutes to unbundle revert the files, relaunch the tests, etc...
1179
1180 #### With evolve now
1181
1182 ~~~graphviz-file
1183 graphs/fix-bug-1.dot
1184 ~~~
1185
1186 #### Same CLI
1187
1188 With evolve this time:
1189
1190 ~~~ {.sh}
1191 hg commit --amend -m "Fix bug"
1192 ~~~
1193
1194 ~~~graphviz-file
1195 graphs/fix-bug-2.dot
1196 ~~~
1197
1198 #### Ok what the difference?
1199
1200 #### Before / After
1201
1202
1203 <div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'>
1204 <div class='left' style='order:1; width: 50%'>
1205 Before:
1206
1207 </div>
1208
1209 <div class='right' style='order:2; width: 50%'>
1210 After:
1211
1212 ~~~raw-file
1213 output/fix-a-bug-with-evolve-1.log
1214 ~~~
1215
1216 </div>
1217 </div>
1218
1219 #### Difference is hidden
1220
1221
1222 ~~~raw-file
1223 output/fix-a-bug-with-evolve-2.log
1224 ~~~
1225
1226 The old revision is still there!
1227
1228 #### Impact
1229
1230 * Easier to access obsolete changesets
1231 - No more `.hg/strip-backup/` expedition
1232 * Respect the append only model of Mercurial
1233 - No large data movement on edition
1234 - No cache trauma
1235
1236 #### One more thing
1237
1238 <img src="https://media.giphy.com/media/F3MoHzSjjJ16w/giphy.gif">
1239
1240 #### Track evolution
1241
1242 ~~~graphviz-file
1243 graphs/fix-bug-3.dot
1244 ~~~
1245 ~~~graphviz
1246 digraph G {
1247 rankdir="BT";
1248 node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"];
1249
1250 // Revisions
1251 node[group=main];
1252 Parent -> "Fix bug";
1253 node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"];
1254 Parent -> "Fx bug";
1255
1256 // Obsolescence links
1257 edge[dir=back, style=dotted, arrowtail=dot];
1258 "Fx bug" -> "Fix bug";
1259 }
1260 ~~~
1261
1262 #### Obsmarker
1263
1264 Stores relation between evolutions
1265
1266
1267 <div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'>
1268 <div class='left' style='order:1; width: 50%'>
1269 ~~~graphviz
1270 digraph G {
1271 rankdir="BT";
1272 node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"];
1273
1274 node[group=obsolete, style="dotted, filled" fillcolor="#DFDFFF"];
1275 edge[dir=back, style=dotted, arrowtail=dot];
1276 "Predecessor" -> "Successor";
1277
1278 "Successor" [style="filled", fillcolor="#7F7FFF"];
1279 }
1280 ~~~
1281 </div>
1282
1283 <div class='right' style='order:2; width: 50%'>
1284
1285 * And some metas:
1286 * User
1287 * Date
1288 * And others...
1289 </div>
1290 </div>
1291
1292 ## Topic
1293
1294 #### Topic
1295
1296 <pre>
1297 $> hg topic myfeature
1298 $> hg topics
1299 <span style="color:green;"> * </span><span style="color:green;">myfeature</span>
1300 </pre>
1301
1302 #### Topic
1303
1304 Topic branches are lightweight branches which disappear when changes are
1305 finalized (move to the public phase). They can help users to organise and share
1306 their unfinished work.
1307
1308 #### Topic storage
1309
1310 Like named-branches, topics are stored on the changeset.
1311
1312 #### Head definition
1313
1314 <pre>
1315 $> hg log -G
1316 @ <span style="color:olive;">changeset: 2:03a68957ddd8</span>
1317 | tag: tip
1318 | parent: 0:478309adfd3c
1319 | user: Boris Feld &lt;boris.feld@octobus.net&gt;
1320 | date: Mon Jul 24 22:39:27 2017 +0200
1321 | summary: default
1322 |
1323 | o <span style="color:olive;">changeset: 1:3d2362d21bb4</span>
1324 |/ <span style="background-color:green;">topic: myfeature</span>
1325 | user: Boris Feld &lt;boris.feld@octobus.net&gt;
1326 | date: Mon Jul 24 22:39:55 2017 +0200
1327 | summary: myfeature
1328 |
1329 o <span style="color:olive;">changeset: 0:478309adfd3c</span>
1330 user: Boris Feld &lt;boris.feld@octobus.net&gt;
1331 date: Mon Jul 24 16:01:32 2017 +0200
1332 summary: ROOT
1333 </pre>
1334
1335 #### Heads
1336
1337 <pre>
1338 $> hg log -r 'head() and branch(default)'
1339 <span style="color:olive;">changeset: 2:03a68957ddd8</span>
1340 tag: tip
1341 parent: 0:478309adfd3c
1342 user: Boris Feld &lt;boris.feld@octobus.net&gt;
1343 date: Mon Jul 24 22:39:27 2017 +0200
1344 summary: default
1345 </pre>
1346
1347 #### Name definition
1348
1349 We can update to a topic directly:
1350
1351 <pre>
1352 $> hg update myfeature
1353 switching to topic myfeature
1354 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
1355 </pre>
1356
1357 #### Pre-rebase
1358
1359 <pre>
1360 $> hg log -G
1361 o <span style="color:olive;">changeset: 2:03a68957ddd8</span>
1362 | tag: tip
1363 | parent: 0:478309adfd3c
1364 | user: Boris Feld &lt;boris.feld@octobus.net&gt;
1365 | date: Mon Jul 24 22:39:27 2017 +0200
1366 | summary: default
1367 |
1368 | @ <span style="color:olive;">changeset: 1:3d2362d21bb4</span>
1369 |/ <span style="background-color:green;">topic: myfeature</span>
1370 | user: Boris Feld &lt;boris.feld@octobus.net&gt;
1371 | date: Mon Jul 24 22:39:55 2017 +0200
1372 | summary: myfeature
1373 |
1374 o <span style="color:olive;">changeset: 0:478309adfd3c</span>
1375 user: Boris Feld &lt;boris.feld@octobus.net&gt;
1376 date: Mon Jul 24 16:01:32 2017 +0200
1377 summary: ROOT
1378 </pre>
1379
1380 #### Topic rebase
1381
1382 Topics can be rebased easily on their base branch
1383
1384 <pre>
1385 $> hg rebase
1386 rebasing 1:3d2362d21bb4 &quot;myfeature&quot;
1387 switching to topic myfeature
1388 </pre>
1389
1390 #### Result
1391
1392 <pre>
1393 $> hg log -G
1394 @ <span style="color:olive;">changeset: 3:0a51e0d4d460</span>
1395 | tag: tip
1396 | <span style="background-color:green;">topic: myfeature</span>
1397 | user: Boris Feld &lt;boris.feld@octobus.net&gt;
1398 | date: Mon Jul 24 22:39:55 2017 +0200
1399 | summary: myfeature
1400 |
1401 o <span style="color:olive;">changeset: 2:03a68957ddd8</span>
1402 | parent: 0:478309adfd3c
1403 | user: Boris Feld &lt;boris.feld@octobus.net&gt;
1404 | date: Mon Jul 24 22:39:27 2017 +0200
1405 | summary: default
1406 |
1407 o <span style="color:olive;">changeset: 0:478309adfd3c</span>
1408 user: Boris Feld &lt;boris.feld@octobus.net&gt;
1409 date: Mon Jul 24 16:01:32 2017 +0200
1410 summary: ROOT
1411 </pre>
1412
1413 #### Topic push
1414
1415 You can push topic without -f if you push only 1 head:
1416
1417 <pre>
1418 hg push -r myfeature
1419 </pre>
1420
1421 Even if the topic is not up-to-date to its branch.
1422
1423 ## Stack Workflow
1424
1425 #### Stack
1426
1427 <pre>
1428 $> hg stack
1429 ###### topic: <span style="color:green;">myfeature</span>
1430 ###### branch: feature
1431 <span style="color:teal;">t4</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Step4</span><span style="color:teal;font-weight:bold;"> (current)</span>
1432 <span style="color:olive;">t3</span><span style="color:green;">:</span> Step3
1433 <span style="color:olive;">t2</span><span style="color:green;">:</span> Step2
1434 <span style="color:olive;">t1</span><span style="color:green;">:</span> Step
1435 <span style="color:grey;">t0^ Trunk</span>
1436 </pre>
1437
1438 #### Why Stack?
1439
1440 * Feature = multiple steps,
1441
1442 * Smaller = Simpler
1443
1444 * Simpler = Earlier merge in trunk
1445
1446 * Ease experiment with Alternative
1447
1448 * etc…
1449
1450 #### Prev
1451
1452 <pre>
1453 $> hg prev
1454 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1455 [<span style="color:blue;">7</span>] Step3
1456 $> hg stack
1457 ###### topic: <span style="color:green;">myfeature</span>
1458 ###### branch: feature
1459 <span style="color:olive;">t4</span><span style="color:green;">:</span> Step4
1460 <span style="color:teal;">t3</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Step3</span><span style="color:teal;font-weight:bold;"> (current)</span>
1461 <span style="color:olive;">t2</span><span style="color:green;">:</span> Step2
1462 <span style="color:olive;">t1</span><span style="color:green;">:</span> Step
1463 <span style="color:grey;">t0^ Trunk</span>
1464 </pre>
1465
1466 #### Next
1467
1468 <pre>
1469 $> hg next
1470 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1471 [<span style="color:blue;">8</span>] Step4
1472 $> hg stack
1473 ###### topic: <span style="color:green;">myfeature</span>
1474 ###### branch: feature
1475 <span style="color:teal;">t4</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Step4</span><span style="color:teal;font-weight:bold;"> (current)</span>
1476 <span style="color:olive;">t3</span><span style="color:green;">:</span> Step3
1477 <span style="color:olive;">t2</span><span style="color:green;">:</span> Step2
1478 <span style="color:olive;">t1</span><span style="color:green;">:</span> Step
1479 <span style="color:grey;">t0^ Trunk</span>
1480 </pre>
1481
1482 #### T\#
1483
1484 <pre>
1485 $> hg update --rev t2
1486 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1487 [<span style="color:blue;">8</span>] Step4
1488 $> hg stack
1489 ###### topic: <span style="color:green;">myfeature</span>
1490 ###### branch: feature
1491 <span style="color:olive;">t4</span><span style="color:green;">:</span> Step4
1492 <span style="color:olive;">t3</span><span style="color:green;">:</span> Step3
1493 <span style="color:teal;">t2</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Step2</span><span style="color:teal;font-weight:bold;"> (current)</span>
1494 <span style="color:olive;">t1</span><span style="color:green;">:</span> Step
1495 <span style="color:grey;">t0^ Trunk</span>
1496 </pre>
1497
1498 #### Editing mid-stack
1499
1500 <pre>
1501 $> hg update --rev t1
1502 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1503 $> hg commit --amend -m "Step1"
1504 <span style="color:gold;">3 new unstable changesets</span>
1505 </pre>
1506
1507 #### What have we done?
1508
1509 <pre>
1510 $> hg log -G -T compact
1511 @ <span style="color:olive;">9</span>[tip] 1aa1be5ada40 Step1
1512 |
1513 | o <span style="color:olive;">8</span> cf90b2de7e65 Step4 <span style="color:red;">(unstable)</span>
1514 | |
1515 | o <span style="color:olive;">7</span> e208d4205c8e Step3 <span style="color:red;">(unstable)</span>
1516 | |
1517 | o <span style="color:olive;">6</span> 673ff300cf3a Step2 <span style="color:red;">(unstable)</span>
1518 | |
1519 | <span style="color:grey;">x 5 8bb88a31dd28 Step</span>
1520 |/
1521 o <span style="color:olive;">4</span> 3294c1730df7 Trunk
1522 ~
1523 </pre>
1524
1525 #### Stack to the rescue!
1526
1527 <pre>
1528 $> hg stack
1529 ###### topic: <span style="color:green;">myfeature</span>
1530 ###### branch: feature
1531 <span style="color:olive;">t4</span><span style="color:red;">$</span> Step4<span style="color:red;"> (unstable)</span>
1532 <span style="color:olive;">t3</span><span style="color:red;">$</span> Step3<span style="color:red;"> (unstable)</span>
1533 <span style="color:olive;">t2</span><span style="color:red;">$</span> Step2<span style="color:red;"> (unstable)</span>
1534 <span style="color:teal;">t1</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Step1</span><span style="color:teal;font-weight:bold;"> (current)</span>
1535 <span style="color:grey;">t0^ Trunk</span>
1536 </pre>
1537
1538 #### Don't panic
1539
1540 <pre>
1541 $> hg next --evolve
1542 move:[<span style="color:blue;">6</span>] Step2
1543 atop:[<span style="color:blue;">9</span>] Step1
1544 working directory now at <span style="color:olive;">d72473cbf9a6</span>
1545 $> hg stack
1546 ###### topic: <span style="color:green;">myfeature</span>
1547 ###### branch: feature
1548 <span style="color:olive;">t4</span><span style="color:red;">$</span> Step4<span style="color:red;"> (unstable)</span>
1549 <span style="color:olive;">t3</span><span style="color:red;">$</span> Step3<span style="color:red;"> (unstable)</span>
1550 <span style="color:teal;">t2</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Step2</span><span style="color:teal;font-weight:bold;"> (current)</span>
1551 <span style="color:olive;">t1</span><span style="color:green;">:</span> Step1
1552 <span style="color:grey;">t0^ Trunk</span>
1553 </pre>
1554
1555 #### Go on
1556
1557 <img src="https://media.giphy.com/media/KBx7fQoLxuV7G/giphy.gif">
1558
1559 #### Go on
1560
1561 <pre>
1562 $> hg next --evolve
1563 move:[<span style="color:blue;">7</span>] Step3
1564 atop:[<span style="color:blue;">10</span>] Step2
1565 working directory now at <span style="color:olive;">4062d6ecd214</span>
1566 $> hg stack
1567 ###### topic: <span style="color:green;">myfeature</span>
1568 ###### branch: feature
1569 <span style="color:olive;">t4</span><span style="color:red;">$</span> Step4<span style="color:red;"> (unstable)</span>
1570 <span style="color:teal;">t3</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Step3</span><span style="color:teal;font-weight:bold;"> (current)</span>
1571 <span style="color:olive;">t2</span><span style="color:green;">:</span> Step2
1572 <span style="color:olive;">t1</span><span style="color:green;">:</span> Step1
1573 <span style="color:grey;">t0^ Trunk</span>
1574 </pre>
1575
1576 #### Go on
1577
1578 <pre>
1579 $> hg next --evolve
1580 move:[<span style="color:blue;">8</span>] Step4
1581 atop:[<span style="color:blue;">11</span>] Step3
1582 working directory now at <span style="color:olive;">4dcd9dfedf1b</span>
1583 $> hg stack
1584 ###### topic: <span style="color:green;">myfeature</span>
1585 ###### branch: feature
1586 <span style="color:teal;">t4</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Step4</span><span style="color:teal;font-weight:bold;"> (current)</span>
1587 <span style="color:olive;">t3</span><span style="color:green;">:</span> Step3
1588 <span style="color:olive;">t2</span><span style="color:green;">:</span> Step2
1589 <span style="color:olive;">t1</span><span style="color:green;">:</span> Step1
1590 <span style="color:grey;">t0^ Trunk</span>
1591 </pre>
1592
1593 #### Go on
1594
1595 <pre>
1596 $> hg next --evolve
1597 no children
1598 </pre>
1599
1600 #### Better!
1601
1602 <pre>
1603 $> hg log -G -T compact
1604 @ <span style="color:olive;">12</span>[tip] 4dcd9dfedf1b Step4
1605 |
1606 o <span style="color:olive;">11</span> 4062d6ecd214 Step3
1607 |
1608 o <span style="color:olive;">10</span> d72473cbf9a6 Step2
1609 |
1610 o <span style="color:olive;">9</span> 1aa1be5ada40 Step1
1611 |
1612 o <span style="color:olive;">4</span> 3294c1730df7 Trunk
1613 ~
1614 </pre>
1615
1616 #### More Rewrite Tools
1617
1618 <table>
1619 <tr>
1620 <th>Operation</th>
1621 <th>command</th>
1622 </tr>
1623 <tr>
1624 <td>Modify</td>
1625 <td>`hg amend`<br></td>
1626 </tr>
1627 <tr>
1628 <td>Remove</td>
1629 <td>`hg prune`<br></td>
1630 </tr>
1631 <tr>
1632 <td>Move</td>
1633 <td>`hg grab`<br></td>
1634 </tr>
1635 <tr>
1636 <td>Split</td>
1637 <td>`hg split`<br></td>
1638 </tr>
1639 <tr>
1640 <td>Fold</td>
1641 <td>`hg fold`<br></td>
1642 </tr>
1643 </table>
1644
1645 #### Multi headed stack
1646
1647 <pre>
1648 $> hg log -G -T compact
1649 @ <span style="color:olive;">6</span>[tip] 189f54192937 Step4.5
1650 |
1651 | o <span style="color:olive;">5</span> c1a91e7c74f5 Step5
1652 |/
1653 o <span style="color:olive;">4</span> 826d2fbb601a Step4
1654 |
1655 o <span style="color:olive;">3</span> 08bcdd8d972b Step3
1656 |
1657 o <span style="color:olive;">2</span> 06cb53532f1b Step2
1658 |
1659 o <span style="color:olive;">1</span> 3eb38d10980d Step1
1660 ~
1661
1662 </pre>
1663
1664 #### Multi headed stack
1665
1666 <pre>
1667 $> hg stack
1668 ###### topic: <span style="color:green;">myfeature</span> (<span style="color:olive;">2 heads</span>)
1669 ###### branch: feature
1670 <span style="color:teal;">t6</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Step4.5</span><span style="color:teal;font-weight:bold;"> (current)</span>
1671 <span style="color:grey;">t4^ Step4 (base)</span>
1672 <span style="color:olive;">t5</span><span style="color:green;">:</span> Step5
1673 <span style="color:olive;">t4</span><span style="color:green;">:</span> Step4
1674 <span style="color:olive;">t3</span><span style="color:green;">:</span> Step3
1675 <span style="color:olive;">t2</span><span style="color:green;">:</span> Step2
1676 <span style="color:olive;">t1</span><span style="color:green;">:</span> Step1
1677 <span style="color:grey;">t0^ Trunk</span>
1678 </pre>
1679
1680 ## Distributed Workflow
1681
1682 #### propagation
1683
1684 Obsolescence can be exchanged:
1685
1686 * push, pull
1687 * bundle / unbundle (hg 4.3+)
1688
1689 (affects draft history only)
1690
1691 #### Exchanging draft
1692
1693 * Works on multiple machines
1694
1695 * Collaborate with others
1696
1697 * Whole new play field == new traps
1698
1699 #### Example
1700
1701 <div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'>
1702 <div class='left' style='order:1; width: 50%'>
1703 ~~~graphviz
1704 digraph G {
1705 rankdir="BT";
1706 graph[splines=polyline];
1707 node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
1708
1709 // Revisions
1710 node[group=main];
1711 Root -> "A";
1712 Root [shape="circle"];
1713 }
1714 ~~~
1715 </div>
1716
1717 <div class='right' style='order:2; width: 50%'>
1718 ~~~graphviz
1719 digraph G {
1720 rankdir="BT";
1721 graph[splines=polyline];
1722 node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
1723
1724 // Revisions
1725 node[group=main];
1726 Root -> "A";
1727 Root [shape="circle"];
1728 }
1729 ~~~
1730 </div>
1731 </div>
1732
1733 #### time pass
1734
1735 <div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'>
1736 <div class='left' style='order:1; width: 50%'>
1737 ~~~graphviz
1738 digraph G {
1739 rankdir="BT";
1740 graph[splines=polyline];
1741 node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
1742
1743 // Revisions
1744 node[group=main];
1745 Root -> "A1";
1746 node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"];
1747 Root -> "A";
1748
1749 // Obsolescence links
1750 edge[dir=back, style=dotted, arrowtail=dot];
1751 "A" -> "A1";
1752
1753 Root [shape="circle"];
1754 }
1755 ~~~
1756 </div>
1757
1758 <div class='right' style='order:2; width: 50%'>
1759 ~~~graphviz
1760 digraph G {
1761 rankdir="BT";
1762 graph[splines=polyline];
1763 node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
1764
1765 // Revisions
1766 node[group=main];
1767 Root -> "A" -> B;
1768
1769 Root [shape="circle"];
1770 }
1771 ~~~
1772 </div>
1773 </div>
1774
1775 #### Instability
1776
1777 ~~~graphviz
1778 digraph G {
1779 rankdir="BT";
1780 graph[splines=polyline];
1781 node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
1782
1783 // Revisions
1784 node[group=main];
1785 Root -> "A1";
1786 "B";
1787 node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"];
1788 Root -> "A" -> "B";
1789
1790 // Obsolescence links
1791 edge[dir=back, style=dotted, arrowtail=dot];
1792 "A" -> "A1";
1793
1794 Root [shape="circle"];
1795 B [fillcolor="#FF3535"];
1796 }
1797 ~~~
1798
1799 #### It's smart
1800
1801 <img src="https://media2.giphy.com/media/ZThQqlxY5BXMc/giphy.gif">
1802
1803 #### Stabilization
1804
1805 ~~~graphviz
1806 digraph G {
1807 rankdir="BT";
1808 graph[splines=polyline];
1809 node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
1810
1811 // Revisions
1812 node[group=main];
1813 Root -> "A1" -> "B1";
1814 node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"];
1815 Root -> "A" -> "B";
1816
1817 // Obsolescence links
1818 edge[dir=back, style=dotted, arrowtail=dot];
1819 "A" -> "A1";
1820 "B" -> "B1";
1821
1822 Root [shape="circle"];
1823 }
1824 ~~~
1825
1826 #### rewrite anything?
1827
1828 Phases enforce a reliable history:
1829
1830 * **draft**: can we rewritten
1831 * **public**: immutable part of the history
1832
1833 Contact your local workflow manager.
1834
1835 ## Helpfull Tooling
1836
1837 #### Summary
1838
1839 <pre>
1840 $> hg summary
1841 <span style="color:olive;">parent: 10:890ac95deb83 </span>tip (unstable)
1842 Head
1843 branch: feature
1844 commit: (clean)
1845 update: (current)
1846 phases: 9 draft
1847 unstable: <span style="color:red;">1 changesets</span>
1848 topic: <span style="color:green;">myfeature</span>
1849 </pre>
1850
1851 #### Topics
1852
1853 <pre>
1854 $> hg topics
1855 4.3compat
1856 doc
1857 evolvecolor
1858 import-checker
1859 more-output
1860 obscache
1861 obsfatefixes
1862 obsmarkerbitfield
1863 obsrangecacheiterative
1864 packaging
1865 prev-next
1866 split
1867 stack_unstable_bug
1868 tutorial
1869 * tutorialtypos
1870 </pre>
1871
1872 #### Topics age
1873
1874 <pre>
1875 $> hg topics --age
1876 tutorial (5 hours ago)
1877 <span style="color:green;"> * </span><span style="color:green;">tutorialtypos </span> (5 hours ago)
1878 4.3compat (4 days ago)
1879 prev-next (12 days ago)
1880 obsfatefixes (2 weeks ago)
1881 more-output (3 weeks ago)
1882 obsmarkerbitfield (2 months ago)
1883 obscache (2 months ago)
1884 evolvecolor (2 months ago)
1885 obsrangecacheiterative (2 months ago)
1886 stack_unstable_bug (2 months ago)
1887 doc (3 months ago)
1888 split (3 months ago)
1889 import-checker (4 months ago)
1890 packaging (4 months ago)
1891 </pre>
1892
1893 #### Topics verbose
1894
1895 <pre class="shell_output">
1896 $> hg topics --verbose
1897 4.3compat (on branch: default, 1 changesets, <span style="color:teal;">43 behind</span>)
1898 doc (on branch: stable, 1 changesets, <span style="color:teal;">415 behind</span>)
1899 evolvecolor (on branch: default, 1 changesets, <span style="color:teal;">369 behind</span>)
1900 import-checker (on branch: default, 1 changesets, <span style="color:teal;">637 behind</span>)
1901 more-output (on branch: default, 1 changesets, <span style="color:teal;">104 behind</span>)
1902 obscache (on branch: default, 1 changesets, <span style="color:teal;">325 behind</span>)
1903 obsfatefixes (on branch: default, 1 changesets, <span style="color:teal;">82 behind</span>)
1904 obsmarkerbitfield (on branch: default, 1 changesets, <span style="color:teal;">324 behind</span>)
1905 obsrangecacheiterative (on branch: default, 1 changesets, <span style="color:teal;">461 behind</span>)
1906 packaging (on branch: default, 1 changesets, <span style="color:teal;">2521 behind</span>)
1907 prev-next (on branch: default, 4 changesets, <span style="color:teal;">72 behind</span>)
1908 split (on branch: default, 1 changesets, <span style="color:teal;">492 behind</span>)
1909 stack_unstable_bug (on branch: default, 1 changesets, <span style="color:teal;">474 behind</span>)
1910 tutorial (on branch: default, 2 changesets, <span style="color:teal;">492 behind</span>)
1911 <span style="color:green;"> * </span><span style="color:green;">tutorialtypos </span> (on branch: default, 3 changesets, <span style="color:red;">1 troubled</span>, <span style="color:olive;">2 heads</span>, <span style="color:teal;">2 behind</span>)
1912 </pre>
1913
1914 #### Log
1915
1916 <pre>
1917 $ hg log -G --hidden -T '{node|short}\n{obsfate}\n'
1918 @ c55cb2ee8a91
1919 |
1920 o 23abfc79b7ce
1921 |
1922 | o 4302274177b9 <span style="color:red;">(unstable)</span>
1923 | |
1924 | <span style="color:grey;">x fba593aaaa10</span>
1925 |/ rewritten as c55cb2ee8a91;
1926 o 2ff53d8bf7d7
1927 </pre>
1928
1929 #### Evolve --list
1930
1931 <pre>
1932 $> hg evolve --list
1933 <span style="color:gold;">9ac0d376e01c</span>: changelog: introduce a 'tiprev' method
1934 <span style="color:red;">unstable</span>: <span style="color:grey;">52ec3072fe46</span> (obsolete parent)
1935
1936 <span style="color:gold;">3efd3eab9860</span>: changelog: use 'tiprev()' in 'tip()'
1937 <span style="color:red;">unstable</span>: <span style="color:red;">9ac0d376e01c</span> (unstable parent)
1938 </pre>
1939
1940 (see also `hg evolve --list --rev`)
1941
1942 #### Obslog
1943
1944 <pre>
1945 $> hg obslog
1946 @ <span style="color:olive;">c55cb2ee8a91</span> <span style="color:blue;">(4)</span> A2
1947 |
1948 | o <span style="color:olive;">4302274177b9</span> <span style="color:blue;">(2)</span> A1
1949 |/
1950 x <span style="color:olive;">fba593aaaa10</span> <span style="color:blue;">(1)</span> A
1951 rewritten(description, parent) as <span style="color:olive;">c55cb2ee8a91</span>
1952 by <span style="color:green;">Boris Feld &lt;boris.feld@octobus.net&gt;</span>
1953 <span style="color:teal;">(Thu Jun 22 00:00:29 2017 +0200)</span>
1954 rewritten(description) as <span style="color:olive;">4302274177b9</span>
1955 by <span style="color:green;">Boris Feld &lt;boris.feld@octobus.net&gt;</span>
1956 <span style="color:teal;">(Thu Jun 22 00:00:28 2017 +0200)</span>
1957
1958 </pre>
1959
1960 #### Obslog --patch
1961
1962 <pre>
1963 $> hg obslog -p
1964 @ <span style="color:olive;">f6b1dded9e95</span> <span style="color:blue;">(2)</span> A1
1965 |
1966 x <span style="color:olive;">364e589e2bac</span> <span style="color:blue;">(1)</span> A
1967 rewritten(description, parent) as <span style="color:olive;">a6be771bedcf</span>
1968 by <span style="color:green;">Boris Feld &lt;boris.feld@octobus.net&gt;</span>
1969 <span style="color:teal;">(Thu Jun 22 00:00:29 2017 +0200)</span>
1970 (No patch available yet, changesets rebased)
1971 rewritten(description) as <span style="color:olive;">f6b1dded9e95</span>
1972 by <span style="color:green;">Boris Feld &lt;boris.feld@octobus.net&gt;</span>
1973 <span style="color:teal;">(Thu Jun 22 00:00:28 2017 +0200)</span>
1974 --- a/364e589e2bac-changeset-description
1975 +++ b/f6b1dded9e95-changeset-description
1976 @@ -1,1 +1,1 @@
1977 -A
1978 +A1
1979 </pre>
1980
1981 #### Journal
1982
1983 <pre>
1984 $> hg journal
1985 previous locations of '.':
1986 2fb6d364d453 commit --amend -m Step1
1987 701fb5d73e07 update --rev t1
1988 ae11635effb7 commit -A -m Step2
1989 701fb5d73e07 commit -A -m Step
1990 </pre>
1991
1992 ## Semantic
1993
1994 #### Use the right commands!
1995
1996 <img src="https://media.giphy.com/media/uRb2p09vY8lEs/giphy.gif">
1997
1998 #### smart commands
1999
2000 <table>
2001 <tr>
2002 <th>Operation</th>
2003 <th>command</th>
2004 </tr>
2005 <tr>
2006 <td>Modify</td>
2007 <td>`hg amend`<br></td>
2008 </tr>
2009 <tr>
2010 <td>Remove</td>
2011 <td>`hg prune`<br></td>
2012 </tr>
2013 <tr>
2014 <td>Move</td>
2015 <td>`hg grab`<br></td>
2016 </tr>
2017 <tr>
2018 <td>Split</td>
2019 <td>`hg split`<br></td>
2020 </tr>
2021 <tr>
2022 <td>Fold</td>
2023 <td>`hg fold`<br></td>
2024 </tr>
2025 </table>
2026
2027
2028 ## Troubles
2029
2030 #### Evolution
2031
2032 * Unlock powerful unique features
2033
2034 * Hide **most** of the complexity
2035
2036 * Help with unstable situations
2037
2038 - Automatic detection
2039
2040 - Automated resolution `hg help evolve`
2041
2042 #### instability
2043
2044 (currently: *troubles*)
2045
2046 * **Orphans:** ancestors were rewritten
2047
2048 * **Divergence:** branching in evolutions
2049
2050 - Content-divergence: independent rewrites
2051
2052 - Phase-divergence: older version got published
2053
2054 ## Conclusion
2055
2056 #### Work in progress
2057
2058 * Concepts are solid
2059 * Implementation in progress
2060 * Common case works fine
2061 * Some rough edges
2062 * Feedback → priority
2063
2064 #### Use Evolution Today
2065
2066 install `hg-evolve`
2067
2068 <pre>
2069 [extensions]
2070 evolve=
2071 topic= ## provides hg stack
2072 </pre>
2073
2074 #### Helps
2075
2076 * Mailing-list: `evolve-testers@mercurial-scm.org`
2077 * IRC channel: `#mercurial`
2078
2079 #### Documentation
2080
2081 * Documentation: <br/><small><https://www.mercurial-scm.org/doc/evolution/index.html></small>
2082 * Wiki: <br/><small><https://www.mercurial-scm.org/wiki/EvolveExtension></small>
2083
2084 ## Conclusion
2085
2086 #### Rewrite all the things!
2087
2088 <img src="https://cdn.meme.am/cache/instances/folder258/500x/54913258.jpg">
2089
2090 #### Safety first!
2091
2092 <img src="https://media.giphy.com/media/46vrhWWOJ4wHC/giphy.gif">
2093
2094 ## extra - Troubles
2095
2096 #### Obsolete
2097
2098 ~~~graphviz
2099 digraph G {
2100 rankdir="BT";
2101 graph[splines=polyline];
2102 node[fixedsize=true, style="filled", width=1, height=1, fillcolor="#7F7FFF", shape="pentagon"];
2103
2104
2105 node[group=main];
2106 Root -> New;
2107 node[group=obsolete];
2108 Root -> Obsolete;
2109
2110 // Obsolescence links
2111 edge[dir=back, style=dotted, arrowtail=dot];
2112 Obsolete -> New;
2113
2114 Obsolete [fillcolor="#DFDFFF"];
2115 Root[shape="circle"];
2116 }
2117 ~~~
2118
2119 #### Unstable
2120
2121 Now called `orphan`
2122
2123 ~~~graphviz
2124 digraph G {
2125 rankdir="BT";
2126 graph[splines=polyline];
2127 node[fixedsize=true, style="filled", width=1, height=1, fillcolor="#7F7FFF", shape="pentagon"];
2128
2129 node[group=main];
2130 Root -> New;
2131 node[group=obsolete];
2132 Root -> Obsolete -> Unstable;
2133
2134 // Obsolescence links
2135 edge[dir=back, style=dotted, arrowtail=dot];
2136 Obsolete -> New;
2137
2138 Obsolete [fillcolor="#DFDFFF"];
2139 Unstable [fillcolor="#FF3535"];
2140 Root[shape="circle"];
2141 }
2142 ~~~
2143
2144 #### Bumped
2145
2146 Now called `Phase-divergent`
2147
2148 ~~~graphviz
2149 digraph G {
2150 rankdir="BT";
2151 graph[splines=polyline];
2152 node[fixedsize=true, style="filled", width=1, height=1, fillcolor="#7F7FFF", shape="pentagon"];
2153
2154 node[group=main];
2155 Root -> New;
2156 node[group=obsolete];
2157 Root -> Obsolete;
2158 node[group=bumped];
2159 Root -> Bumped;
2160
2161 // Obsolescence links
2162 edge[dir=back, style=dotted, arrowtail=dot];
2163 Obsolete -> New;
2164 Obsolete -> Bumped;
2165
2166 New [shape="circle"];
2167 Obsolete [fillcolor="#DFDFFF"];
2168 Bumped [fillcolor="#FF3535"];
2169 Root[shape="circle"];
2170 }
2171 ~~~
2172
2173 #### Divergent
2174
2175 Now called `Content-divergent`
2176
2177 ~~~graphviz
2178 digraph G {
2179 rankdir="BT";
2180 graph[splines=polyline];
2181 node[fixedsize=true, style="filled", width=1, height=1, fillcolor="#7F7FFF", shape="pentagon"];
2182
2183 Root -> Base;
2184 Root -> Divergent1;
2185 Root -> Divergent2;
2186
2187 // Obsolescence links
2188 edge[dir=back, style=dotted, arrowtail=dot];
2189 Base -> Divergent1;
2190 Base -> Divergent2;
2191
2192 Base [shape="pentagon", fillcolor="#DFDFFF"];
2193 Divergent1 [fillcolor="#FF3535"];
2194 Divergent2 [fillcolor="#FF3535"];
2195 Root[shape="circle"];
2196 }
2197 ~~~
2198
2199 ## extra-commands
2200
2201 #### Amend
2202
2203 <div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'>
2204 <div class='left' style='order:1; width: 20%'>
2205 ~~~graphviz
2206 digraph G {
2207 rankdir="BT";
2208 graph[splines=polyline];
2209 node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
2210
2211 // Revisions
2212 node[group=main];
2213 Root -> "A";
2214 Root [shape="circle"];
2215 }
2216 ~~~
2217 </div>
2218
2219 <div class="middle" style='order:2; width: 60%'>
2220 To amend A:
2221
2222 hg amend -m 'A1'
2223 </div>
2224
2225 <div class='right' style='order:2; width: 20%'>
2226 ~~~graphviz
2227 digraph G {
2228 rankdir="BT";
2229 graph[splines=polyline];
2230 node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
2231
2232 // Revisions
2233 node[group=main];
2234 Root -> "A1";
2235 node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"];
2236 Root -> "A";
2237
2238 // Obsolescence links
2239 edge[dir=back, style=dotted, arrowtail=dot];
2240 "A" -> "A1";
2241 Root [shape="circle"];
2242 }
2243 ~~~
2244 </div>
2245 </div>
2246
2247 #### Prune
2248
2249 <div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'>
2250 <div class='left' style='order:1; width: 20%'>
2251 ~~~graphviz
2252 digraph G {
2253 rankdir="BT";
2254 graph[splines=polyline];
2255 node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
2256
2257 // Revisions
2258 node[group=main];
2259 Root -> "A";
2260 Root [shape="circle"];
2261 }
2262 ~~~
2263 </div>
2264
2265 <div class="middle" style='order:2; width: 60%'>
2266
2267 To prune A:
2268
2269 hg prune -r "desc(A)"
2270 </div>
2271
2272 <div class='right' style='order:2; width: 20%'>
2273 ~~~graphviz
2274 digraph G {
2275 rankdir="BT";
2276 graph[splines=polyline];
2277 node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
2278
2279 Root [shape="circle"];
2280
2281 // Revisions
2282 node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"];
2283 Root -> "A";
2284 }
2285 ~~~
2286 </div>
2287 </div>
2288
2289 #### Rebase
2290
2291 <div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'>
2292 <div class='left' style='order:1; width: 20%'>
2293 ~~~graphviz
2294 digraph G {
2295 rankdir="BT";
2296 graph[splines=polyline];
2297 node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
2298
2299 // Revisions
2300 node[group=branch];
2301 Root -> B;
2302 node[group=main];
2303 Root -> "A";
2304
2305 Root [shape="circle"];
2306 }
2307 ~~~
2308 </div>
2309
2310 <div class="middle" style='order:2; width: 60%'>
2311
2312 In order to rebase A on top of B;
2313
2314 hg rebase -r "desc(A)" -d "desc(B)"
2315
2316 </div>
2317
2318 <div class='right' style='order:2; width: 20%'>
2319 ~~~graphviz
2320 digraph G {
2321 rankdir="BT";
2322 graph[splines=polyline];
2323 node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
2324
2325 // Revisions
2326 node[group=branch];
2327 Root -> B -> "A'";
2328
2329 node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"];
2330 Root -> "A";
2331
2332 // Obsolescence links
2333 edge[dir=back, style=dotted, arrowtail=dot];
2334 "A" -> "A'";
2335
2336 Root [shape="circle"];
2337 }
2338 ~~~
2339 </div>
2340 </div>
2341
2342 #### Fold
2343
2344 <div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'>
2345 <div class='left' style='order:1; width: 15%'>
2346
2347 ~~~graphviz
2348 digraph G {
2349 rankdir="BT";
2350 graph[splines=polyline];
2351 node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
2352
2353 // Revisions
2354 node[group=branch];
2355 Root -> A -> B;
2356
2357 Root [shape="circle"];
2358 }
2359 ~~~
2360 </div>
2361
2362 <div class="middle" style='order:2; width: 70%'>
2363
2364 To fold A and B:
2365
2366 hg fold -r "desc(A)" -r "desc(B)" -m "C"
2367
2368 </div>
2369
2370 <div class='right' style='order:2; width: 15%'>
2371
2372 ~~~graphviz
2373 digraph G {
2374 rankdir="BT";
2375 graph[splines=polyline];
2376 node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
2377
2378 // Revisions
2379 node[group=branch];
2380 Root -> C;
2381
2382 node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"];
2383 Root -> A -> B;
2384
2385 // Obsolescence links
2386 edge[dir=back, style=dotted, arrowtail=dot];
2387 "A" -> "C";
2388 "B" -> "C";
2389
2390 Root [shape="circle"];
2391 }
2392 ~~~
2393
2394 </div>
2395 </div>
2396
2397 #### Split
2398
2399 <div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'>
2400 <div class='left' style='order:1; width: 20%'>
2401 ~~~graphviz
2402 digraph G {
2403 rankdir="BT";
2404 graph[splines=polyline];
2405 node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
2406
2407 // Revisions
2408 node[group=branch];
2409 Root -> A;
2410
2411 Root [shape="circle"];
2412 }
2413 ~~~
2414 </div>
2415
2416 <div class="middle" style='order:2; width: 60%'>
2417
2418 Split in two:
2419
2420 hg split -r "desc(A)"
2421 </div>
2422
2423 <div class='right' style='order:2; width: 20%'>
2424 ~~~graphviz
2425 digraph G {
2426 rankdir="BT";
2427 graph[splines=polyline];
2428 node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
2429
2430 // Revisions
2431 node[group=branch];
2432 Root -> B -> C;
2433
2434 node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"];
2435 Root -> A;
2436
2437 // Obsolescence links
2438 edge[dir=back, style=dotted, arrowtail=dot];
2439 "A" -> "C";
2440 "A" -> "B";
2441
2442 Root [shape="circle"];
2443 }
2444 ~~~
2445 </div>
2446 </div>
2447 -->