1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447
|
---
title: Changeset Evolution training
author: |
<span style="text-transform: none;"><small>Boris Feld<br/><a href="https://octobus.net">octobus.net</a></small></span>
---
# Introduction
## Welcome
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.
This training is designed to last approximately ¾ hours.
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.
```bash
$ hg clone https://bitbucket.org/octobus/evolve_training_repo
$ cd evolve_training_repo
```
Copy the provided hgrc to ensure a smooth training experience:
```bash
$ cp hgrc .hg/hgrc
```
This training support will contains commands you are expected to type and launch. These commands will be in the following format:
```
$ COMMAND YOU ARE EXPECTED TO TYPE
output you are expecting to see
```
## Preliminary checks
#### Mercurial version
First let's use the following command to verify which version of Mercurial you are using:
```
$ hg --version
Mercurial Distributed SCM (version 4.4.2)
(see https://mercurial-scm.org for more information)
Copyright (C) 2005-2017 Matt Mackall and others
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
```
You need at least Mercurial version `4.1`. If you don't have a recent enough version, please call your instructor.
In order to activate the Evolve extension, add these lines in your user configuration (using the command `hg config --edit`):
```ini
[extensions]
evolve =
topic =
```
#### Mercurial extensions
Now let's check the version of your extensions. You will need all of these for the training:
```
$ hg --version --verbose
[...]
evolve external 7.1.0
topic external 0.6.0
rebase internal
histedit internal
```
# The Basics
<!-- #### What is Changeset Evolution?
With core Mercurial, changesets are permanent and history rewriting has been discouraged for a long time. You can
commit new changesets to modify your source code, but you cannot
modify or remove old changesets.
For years, Mercurial has included various commands that allow
history modification: ``rebase``, ``histedit``, ``commit --amend`` and so forth.
However, there's a catch: until now, Mercurial's various mechanisms for
modifying history have been *unsafe* and expensive, in that changesets were
destroyed (“stripped”) rather than simply hidden and still easy to recover.
Changeset Evolution makes things better by changing the behaviour of most existing
history modification commands so they use a safer mechanism (*changeset
obsolescence*, covered below) rather than the older, less safe *strip*
operation.
``evolve`` is built on infrastructure in core Mercurial:
* *Phases* (starting in Mercurial 2.1) allow you to distinguish
mutable and immutable changesets.
* *Changeset obsolescence* (starting in Mercurial 2.3) is how
Mercurial knows how history has been modified, specifically when
one changeset replaces another. In the obsolescence model, a
changeset is neither removed nor modified, but is instead marked
*obsolete* and typically replaced by a *successor*. Obsolete
changesets usually become *hidden* as well. Obsolescence is a
disabled feature in Mercurial until you start using ``evolve``.
XXX More than just than obsolescence in core ? XXX
XXX The part below is a bit overselling XXX
Some of the things you can do with ``evolve`` are:
* Fix a mistake immediately: “Oops! I just committed a changeset
with a syntax error—I'll fix that and amend the changeset so no
one sees my mistake.” (While this is possible using default
features of core Mercurial, Changeset Evolution makes it safer.)
* Fix a mistake a little bit later: “Oops! I broke the tests three
commits back, but only noticed it now—I'll just update back to the
bad changeset, fix my mistake, amend the changeset, and evolve
history to update the affected changesets.”
* Remove unwanted changes: “I hacked in some debug output two
commits back; everything is working now, so I'll just prune that
unwanted changeset and evolve history before pushing.”
* Share mutable history with yourself: say you do most of your
programming work locally, but need to test on a big remote server
somewhere before you know everything is good. You can use
``evolve`` to share mutable history between two computers, pushing
finely polished changesets to a public repository only after
testing on the test server.
* Share mutable history for code review: you don't want to publish
unreviewed changesets, but you can't block every commit waiting
for code review. The solution is to share mutable history with
your reviewer, amending each changeset until it passes review.
* Explore and audit the rewrite history of a changeset. Since Mercurial is
tracking the edits you make to a changeset, you can look at the history of
these edits. This is similar to Mercurial tracking the history of file
edits, but at the changeset level. -->
In this section, we are going to learn how to do basic history rewriting like rewriting a changeset or rebasing.
### Amend
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.
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:
```
$ hg update typo
```
Check what the current repository looks like:
~~~raw-file
output/fix-a-bug-base.log
~~~
~~~graphviz-file
graphs/fix-bug-1.dot
~~~
We have a root commit and another based on it. Double-check that you are on the right changeset with the `hg summary` command:
~~~raw-file
output/fix-a-bug-base-summary.log
~~~
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.
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):
~~~
$ hg commit --amend --message "Fix bug"
~~~
Let's take a look at the repository now:
~~~raw-file
output/amend-after.log
~~~
~~~graphviz-file
graphs/fix-bug-2.dot
~~~
The logs before and after amending looks pretty similar, we are going to analyze the differences later. Did you catch the differences?
### Rebase
<!-- XXX probably needs a sentence about the merge (Why do you want to avoid it) XXX -->
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:
```
$ hg update build/linuxsupport-v2
```
~~~raw-file
output/rebase-before.log
~~~
~~~graphviz-file
graphs/rebase-before.dot
~~~
<!-- XXX-REVIEW: Explain rebase CLI interface -->
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:
1. Explicitly select them using "--rev".
2. Use "--source" to select a root commit and include all of its descendants.
3. Use "--base" to select a commit; rebase will find ancestors and their descendants which are not also ancestors of the destination.
4. If you do not specify any of "--rev", "source", or "--base", rebase will use "--base ." as above.
For this first example, we are gonna stays simple and explicitly select the commits we want to rebase with the `--rev` option.
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:
~~~raw-file
output/rebase.log
~~~
Now we have a nice, clean and flat history:
~~~raw-file
output/rebase-after.log
~~~
~~~graphviz-file
graphs/rebase-after.dot
~~~
For more details about how to use the `hg rebase` command, see `hg help rebase`.
### Under the hood
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?
Let's go back to our previous amend example.
##### Amend
When we did our amend, the status of the repository was:
~~~raw-file
output/behind-the-hood-amend-before-hash-hidden.log
~~~
~~~graphviz-file
graphs/fix-bug-1.dot
~~~
And after the amend, the repository looked like:
~~~raw-file
output/behind-the-hood-amend-after.log
~~~
~~~graphviz-file
graphs/fix-bug-2.dot
~~~
Do you see what is the difference?
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?
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:
~~~raw-file
output/under-the-hood-amend-after-log-hidden.log
~~~
Notice the `x` in the log output which shows that a changeset is hidden.
In addition to hiding the original changeset, we are also storing additional information which is recording the relation between a changeset, the **predecessor** 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:
~~~graphviz-file
graphs/fix-bug-3.dot
~~~
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.
##### Rebase
**Successors** don't need to share anything with their **predecessor**. They could have a different description message, user, date or even parents.
Let's look at our earlier rebase example. The status before the rebase was:
~~~raw-file
output/behind-the-hood-rebase-before-hash-hidden.log
~~~
~~~graphviz-file
graphs/rebase-before.dot
~~~
And after it was:
~~~raw-file
output/behind-the-hood-rebase-after.log
~~~
~~~graphviz-file
graphs/rebase-after.dot
~~~
Did the same thing happen under the hood?
Yes, exactly! The old changesets are still around, and they are just hidden.
~~~raw-file
output/rebase-after-hidden.log
~~~
And we created three **obsolescence markers**, between each rebased commit and its **successor**:
~~~graphviz-file
graphs/rebase-after-hidden.dot
~~~
### Evolution History
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.
As it is a new dimension of history, the classical Mercurial commands are not always the best to visualize this new history.
We have seen that we can see the **hidden** changesets with the `--hidden` option on `hg log`:
~~~raw-file
output/under-the-hood-amend-after-log-hidden.log
~~~
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):
~~~raw-file
output/under-the-hood-amend-after-obslog.log
~~~
We can even print what changed between the two versions with the `--patch` option:
~~~raw-file
output/under-the-hood-amend-after-obslog-patch.log
~~~
Obslog works both ways, as it can display **predecessors** and **successors** with the `--all` option:
```raw-file
output/under-the-hood-amend-after-obslog-no-all.log
```
~~~raw-file
output/under-the-hood-amend-after-obslog-all.log
~~~
~~~graphviz-file
graphs/fix-bug-3.dot
~~~
We can also use obslog on the changesets that we rebased earlier:
~~~raw-file
output/under-the-hood-rebase-after-obslog.log
~~~
Why the `hg obslog` command is only showing two commits while we rebased three of them?
```raw-file
output/under-the-hood-rebase-after-obslog-branch.log
```
And why the `hg obslog` command show disconnected graphs when asking for the obslog of the whole branch?
~~~graphviz-file
graphs/rebase-after-hidden.dot
~~~
While these two obsolescence logs look very similar —because they show a similar change—, the two changesets log histories looked quite different.
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.
#### TortoiseHG
TortoiseHG should be able to display obsolescence history for your repositories.
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:

<!-- #### Deroulement
Travail chacun de son côté pour apprendre à utiliser:
- Réecriture de changeset
- Affichage de l'obsolescence, log, obslog
- Vérifier que chacun sait utiliser les commandes de base
- Vérifier que chacun sait utiliser les commandes de visu, hg log, hg log -G, thg?
=> Pas trop longtemps // répartir
- Créer un commit
- Le amend sans evolve == bundle
- Strip?
- rebase sans evolve?
- Why is it bad? exemple
(Peut-etre pas leur faire pratiquer amend sans evolve, ca prends du temps)
- With evolve, now
- Activate it, check version
- Amend with evolve
- rebase with evolve
- What happened?
- View obs-history, hg log, obslog -->
# Medium level
## More rewriting commands
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:
### Amend
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:
- The `-e`/`--edit` option edits the commit message in an editor, which is not opened by default any more.
- The user and date can be updated to the current ones with the `-U`/`--current-user` and `-D`/`--current-date` options.
- More capabilities for rewriting the changeset.
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.
We are going to use it to rewrite the author of the changeset:
```
$ hg update amend-extract
```
We have two commits on the **amend-extract** branch:
```raw-file
output/amend-extract-before.log
```
The user for the **amend-extract** head seems wrong, so let's fix it with the `hg amend` command:
```raw-file
output/amend-user.log
```
Now let's check that the user has been amended correctly:
```raw-file
output/amend-user-after-export.log
```
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.
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.
### Amend extract
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.
This is often used to remove a file or a line that is not meant to be in the current commit.
As usual, we can either pass file paths or use the `-i` option to select which lines to extract.
First, let's extract the badfile:
```raw-file
output/amend-extract-badfile.log
```
Now let's check the status of the changeset and the working directory:
```raw-file
output/amend-extract-badfile-after-export.log
```
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?
Don't worry, the extracted files and lines still are in your working directory:
```raw-file
output/amend-extract-badfile-after-status.log
```
As we are not going to need this file anymore, let's forget it with the `hg revert` command:
```raw-file
output/amend-extract-badfile-after-revert.log
```
Also don't forget to remove the file:
```bash
$ rm badfile
```
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:
```raw-file
output/amend-extract.log
```
Much better! One last thing, as the line that we extracted is still in our working directory, just like when we extracted a file:
```raw-file
output/amend-extract-after-status.log
```
```raw-file
output/amend-extract-after-diff.log
```
Don't forget to revert the change, as we are not going to need it any more:
```raw-file
output/amend-extract-after-revert.log
```
Now let's take a look at the obsolescence history:
```raw-file
output/amend-extract-after-obslog.log
```
The obslog is read from bottom to top:
- First we rewrite the user,
- Then we extracted a whole file,
- Then we extracted a line from a file
We have made three changes that generated three **successors**.
```graphviz-file
graphs/amend-extract-after-hidden.dot
```
### Fold
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:
```
$ hg update fold
```
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:
```raw-file
output/fold-before.log
```
```graphviz-file
graphs/fold-before.dot
```
We all have been in a similar situation. Let's make a nice and clean changeset with fold:
```raw-file
output/fold.log
```
That was easy!
```raw-file
output/fold-after.log
```
```raw-file
output/fold-after-hidden.log
```
Can you imagine what the graphs will looks like?
```raw-file
output/fold-after-hidden-obslog.log
```
```graphviz-file
graphs/fold-after-hidden.log
```
### Split
Sometimes you want to `fold` changesets together, and sometimes you want to `split` a changeset into several ones, because it is too big.
```
$ hg update split
```
Evolve also has a command for that, `hg split`:
```raw-file
output/split-before.log
```
```graphviz-file
graphs/split-before.dot
```
Split accepts a list of revisions and will interactively ask you how you want to split them:
```raw-file
output/split.log
```
Now let's check the state of the repository:
```raw-file
output/split-before-after.log
```
```graphviz-file
graphs/split-before-after-hidden.dot
```
It looks good. What about the obsolescence history?
```raw-file
output/split-after-obslog.log
```
```raw-file
output/split-after-obslog-all.log
```
### Prune
After rewriting and rebasing changesets, the next common use case for history rewriting is removing a changeset.
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?
The common solution is to mark the changeset as removed, and simulate the fact that it has been removed.
This is why the Evolve extension is offering the `prune` command. Let's try to prune a changeset:
```
$ hg update prune
```
```raw-file
output/prune-before.log
```
```graphviz-file
graphs/prune-before.dot
```
`prune` is easy to use, just give it the revisions you want to prune:
```raw-file
output/prune.log
```
Now the changeset is not visible any more:
```raw-file
output/prune-after.log
```
But we can still access it with the `--hidden` option:
```raw-file
output/prune-after-hidden.log
```
The output of `obslog` changes a bit when displaying pruned changesets:
```raw-file
output/prune-after-obslog.log
```
```graphviz-file
graphs/prune-after-hidden.dot
```
### Histedit
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:
- 'pick' to [re]order a changeset
- 'drop' to omit changeset
- 'mess' to reword the changeset commit message
- 'fold' to combine it with the preceding changeset (using the later date)
- 'roll' like fold, but discarding this commit's description and date
- 'edit' to edit this changeset (preserving date)
- 'base' to checkout changeset and apply further changesets from there
It's similar to the `git rebase -i` command.
First, let's update to the right branch:
```
$ hg update histedit
```
```raw-file
output/histedit-before-log.log
```
```graphviz-file
graphs/histedit-before.dot
```
When launching the `hg histedit` command, an editor will show up with the following contents:
```raw-file
output/histedit-no-edit.log
```
Swap the first two lines with your text editor:
```raw-file
output/histedit-commands.log
```
Save and exit. Histedit will apply your instructions and finish.
Let's see the state of the repository:
```raw-file
output/histedit-after-log.log
```
```raw-file
output/histedit-after-log-hidden.log
```
```graphviz-file
graphs/histedit-after-hidden.dot
```
<!-- #### Deroulement
- prune with evolve
- advanced commands
- fold
- split -->
## Stack
### Stack definition
One big problem when working with a DVCS to identify and switch between the different features/bugfixes you are working on.
### Named branches
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.
This solution has several advantages:
- It's supported in all recent-ish Mercurial versions.
- It's simple to use.
- Most tools are supporting it.
But it also has several disadvantages:
- Branches do not fade out once they are merged. You need to explicitely close them with `hg commit --close-branch`.
- Branches are lost when rebasing them without the `--keepbranches` option of the `hg rebase` command.
- New branches needs to be explicitly pushed with the `--new-branch` option of the `hg push` command.
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).
<!-- #### Topics
-->
### Stack
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:
```
$ hg update typo
```
```raw-file
output/stack-typo.log
```
The stack output shows three important data:
- First, which branch you are working on (a.k.a. the **current** branch).
- Then, all the commits that you are currently working on, with the current one highlighted.
- Finally, which commit your branch is based on (**b0**).
This branch is not very interesting, so let's move to another one.
```
$ hg update build/linuxsupport-v2
```
```raw-file
output/stack-rebase.log
```
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.
### Stack movement
There is an easy way to navigate in your stack, the `hg next` and `hg prev` commands:
```raw-file
output/stack-rebase-prev-from-b3.log
```
```raw-file
output/stack-rebase-stack-b2.log
```
And now for the `hg next` command:
```raw-file
output/stack-rebase-next-from-b2.log
```
```raw-file
output/stack-rebase.log
```
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:
```raw-file
output/stack-rebase-export-b1.log
```
Or with the `hg update` command:
```raw-file
output/stack-rebase-update-b2.log
```
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.
```raw-file
output/stack-rebase-stack-b2.log
```
### Edit mid-stack
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:
```raw-file
output/stack-rebase-stack-b2.log
```
```raw-file
output/edit-mid-stack.log
```
The message `1 new orphan changesets` means that, by amending a changeset having a child, this child is now **orphan**, as we can see with the `hg stack` command:
```raw-file
output/edit-mid-stack-after-stack.log
```
`hg stack` tries to simplify the view for you. We have amended **b2**, and **b3**'s parent is the predecessor version of **b2**, so it is not stable any more. It is now **orphan**.
For once, let's use log to see in detail in which situation we are:
```raw-file
output/edit-mid-stack-after-log.log
```
```graphviz-file
graphs/edit-mid-stack-after.dot
```
How can we resolve this situation? It is actually very easy, and we are going to see how in the next section.
<!-- #### Deroulement
Tout seul:
- Topic? stack?
- Comment définir ce sur quoi on travaille?
- Solution possible: named branches
- Avantages des branches nommées
- Inconvénients des branches nommées
- Solution possible: topic
- Avantages des topic
- Inconvénients des topic
- Commands: hg stack, hg topics, hg topics --age, hg topics --verbose
(Pas forcément topic, risque de confusion)
- Visualiser une stack avec hg stack, hg show stack?
- Se déplacer dans une stack avec hg prev/hg next
- Editer au milieu d'une stac
- Absorb? (Pas sous windows dur à installer) -->
## Basic instabilities + stabilization
Instabilities are a normal step when using Evolve-powered workflows. Several tools are provided to fix them smoothly.
#### Log
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`:
```raw-file
output/basic-stabilize-before-log-obsolete.log
```
A changeset can also be **orphan**, meaning that it could be subject to one or more **instabilities**:
* **orphan**, a changeset whose an ancestor is **obsolete**.
* **content-divergent**, a changeset which has been rewritten in two different versions.
* **phase-divergent**, a changeset which has been both rewritten and published.
For the moment, we will only see the **orphan** instability. We can display the **instabilities** of a commit with the `{instabilities}` template keyword:
```raw-file
output/basic-stabilize-before-log-instabilities.log
```
Here we have also one **orphan** commit, which is the child of the **obsolete** commit.
#### Evolve --list
The `hg evolve` command has a `--list` option which can list all the instabilities of your repository.
```raw-file
output/basic-stabilize-before-evolve-list.log
```
#### TortoiseHG
Tortoise HG also has a nice support for displaying the instabilities of your repository:

If you want to filter to get a better view, you can use the *revset* `branch(build/linuxsupport-v2)`:

#### Stabilization using `hg next --evolve`
```raw-file
output/edit-mid-stack-after-stack.log
```
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:
```raw-file
output/basic-stabilize-next-evolve.log
```
Here, it just rebased our old version of `b3` on top of the new version of `b2`.
And now `hg stack` shows us a clean view again:
```raw-file
output/basic-stabilize-after-stack.log
```
That's better!
```graphviz-file
graphs/basic-stabilize-after-stack.dot
```
<!-- #### hg evolve
XXX-REVIEW: Later -->
# Advanced
## Moving change from one commit to another
Create two commits:
- The first one create a new file, add some content in it.
- The second one create another file and modify the first file.
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.
## Exchange
Coming Soon™
<!-- ## Exchange -->
<!-- #### Obsolescence History Synchronization
XXX Too theoritical (except first sentence maybe) XXX
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.
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.
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`.
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
#### When are exchanged obsolescence markers
Obsolescence markers are exchanges during all usual exchange methods:
- Obsolescence markers related to pushed heads are pushed during `hg push`.
- Obsolescence markers related to pulled heads are also pulled during `hg pull`.
- Obsolescence markers are included in bundles.
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.
XXX-REVIEW: Add example?
The obsolescence markers only apply to draft changesets though.
###### Let's exchange obsmarkers
Let's try to push and pull some obsolescence-markers, first copy your repository somewhere else, for example:
```raw-file
output/basic-exchange-clone.log
```
#### Phases
XXX Too theoritical XXX
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:
* **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.
* **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.
* **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.
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.
These phases are ordered (public < draft < secret) and no changeset can be in
a lower phase than its ancestors. For instance, if a changeset is public, all
its ancestors are also public. Lastly, changeset phases should only be changed
towards the public phase.
Changeset are created in the **draft** phase by default and move to the **public** phase in several scenarios.
#### Phase movement
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.
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.
By default, hg server are in **publishing** mode, meaning that:
- all draft changesets that are pulled or cloned appear in phase public on the client.
- all draft changesets that are pushed appear as public on both client and server.
- secret changesets are neither pushed, pulled, or cloned.
Hg servers could also be configured into **non-publishing** mode with this configuration:
```ini
[phases]
publish = False
```
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:
- a changeset could be updated after it has been reviewed.
- a changeset could be updated after a Continuous Integration tool show that some tests on some platforms are broken.
- a changeset could be updated after a co-worker tried implementing another feature on top of it.
#### Usual phase workflow
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
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**.
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.
#### Phase visualization
Phase is not shown by default in `hg log`, but we can ask for it with the `{phase}` template:
```raw-file
output/split-after-log-phase.log
```
It's also possible to use `hg phase` to recover the phase of a revision(s):
```raw-file
output/split-after-phase.log
```
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:
```graphviz-file
graphs/phases.dot
```
#### Phase selection
Phase have a few revsets for selecting changesets by their phases:
- `public()`, select all public changesets.
- `draft()`, select all draft changesets.
- `secrets()`, select all secret changesets.
It could be used to:
- select all non-public changesets with `hg log -r "not public()"`.
- change all secret changesets to draft with `hg phase --draft "secret()"`. -->
<!-- #### Deroulement
Toujours tout seul:
- push / pull
- phases -->
<!-- ## Advanced -->
<!-- #### Deroulement
Advances use-cases:
- Move part of a changeset to another (split+fold) -->
<!-- ## Let's start the fun -->
<!-- #### Deroulement
À deux:
- instability, divergence, orphan
- instability visualization
- instability resolution
- collaboration workflow
Parler du happy path d'abord -->
<!-- ## Content to integrate (presentation old content)
#### Once upon a time
#### You fix a bug
(With a small typo)
~~~graphviz-file
graphs/fix-bug-1.dot
~~~
#### You write more code
<img src="https://media0.giphy.com/media/13GIgrGdslD9oQ/giphy.gif">
#### Urgent merge
<img src="https://media.giphy.com/media/OBnwDJW77acLK/giphy.gif">
#### Fix the fix
But it's easy to fix them:
~~~ {.sh}
hg commit --amend -m "Fix bug"
~~~
~~~graphviz-file
graphs/fix-bug-2.dot
~~~
#### Too fast!
But wait you had local changes! And they get incorporated into the amend.
<img src="https://media1.giphy.com/media/vMiCDfoKdJP0c/giphy.gif">
10 more minutes to unbundle revert the files, relaunch the tests, etc...
#### With evolve now
~~~graphviz-file
graphs/fix-bug-1.dot
~~~
#### Same CLI
With evolve this time:
~~~ {.sh}
hg commit --amend -m "Fix bug"
~~~
~~~graphviz-file
graphs/fix-bug-2.dot
~~~
#### Ok what the difference?
#### Before / After
<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'>
<div class='left' style='order:1; width: 50%'>
Before:
</div>
<div class='right' style='order:2; width: 50%'>
After:
~~~raw-file
output/fix-a-bug-with-evolve-1.log
~~~
</div>
</div>
#### Difference is hidden
~~~raw-file
output/fix-a-bug-with-evolve-2.log
~~~
The old revision is still there!
#### Impact
* Easier to access obsolete changesets
- No more `.hg/strip-backup/` expedition
* Respect the append only model of Mercurial
- No large data movement on edition
- No cache trauma
#### One more thing
<img src="https://media.giphy.com/media/F3MoHzSjjJ16w/giphy.gif">
#### Track evolution
~~~graphviz-file
graphs/fix-bug-3.dot
~~~
~~~graphviz
digraph G {
rankdir="BT";
node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"];
// Revisions
node[group=main];
Parent -> "Fix bug";
node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"];
Parent -> "Fx bug";
// Obsolescence links
edge[dir=back, style=dotted, arrowtail=dot];
"Fx bug" -> "Fix bug";
}
~~~
#### Obsmarker
Stores relation between evolutions
<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'>
<div class='left' style='order:1; width: 50%'>
~~~graphviz
digraph G {
rankdir="BT";
node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"];
node[group=obsolete, style="dotted, filled" fillcolor="#DFDFFF"];
edge[dir=back, style=dotted, arrowtail=dot];
"Predecessor" -> "Successor";
"Successor" [style="filled", fillcolor="#7F7FFF"];
}
~~~
</div>
<div class='right' style='order:2; width: 50%'>
* And some metas:
* User
* Date
* And others...
</div>
</div>
## Topic
#### Topic
<pre>
$> hg topic myfeature
$> hg topics
<span style="color:green;"> * </span><span style="color:green;">myfeature</span>
</pre>
#### Topic
Topic branches are lightweight branches which fade out when changes are
finalized (move to the public phase). They can help users to organise and share
their unfinished work.
#### Topic storage
Like named-branches, topics are stored on the changeset.
#### Head definition
<pre>
$> hg log -G
@ <span style="color:olive;">changeset: 2:03a68957ddd8</span>
| tag: tip
| parent: 0:478309adfd3c
| user: Boris Feld <boris.feld@octobus.net>
| date: Mon Jul 24 22:39:27 2017 +0200
| summary: default
|
| o <span style="color:olive;">changeset: 1:3d2362d21bb4</span>
|/ <span style="background-color:green;">topic: myfeature</span>
| user: Boris Feld <boris.feld@octobus.net>
| date: Mon Jul 24 22:39:55 2017 +0200
| summary: myfeature
|
o <span style="color:olive;">changeset: 0:478309adfd3c</span>
user: Boris Feld <boris.feld@octobus.net>
date: Mon Jul 24 16:01:32 2017 +0200
summary: ROOT
</pre>
#### Heads
<pre>
$> hg log -r 'head() and branch(default)'
<span style="color:olive;">changeset: 2:03a68957ddd8</span>
tag: tip
parent: 0:478309adfd3c
user: Boris Feld <boris.feld@octobus.net>
date: Mon Jul 24 22:39:27 2017 +0200
summary: default
</pre>
#### Name definition
We can update to a topic directly:
<pre>
$> hg update myfeature
switching to topic myfeature
1 files updated, 0 files merged, 2 files removed, 0 files unresolved
</pre>
#### Pre-rebase
<pre>
$> hg log -G
o <span style="color:olive;">changeset: 2:03a68957ddd8</span>
| tag: tip
| parent: 0:478309adfd3c
| user: Boris Feld <boris.feld@octobus.net>
| date: Mon Jul 24 22:39:27 2017 +0200
| summary: default
|
| @ <span style="color:olive;">changeset: 1:3d2362d21bb4</span>
|/ <span style="background-color:green;">topic: myfeature</span>
| user: Boris Feld <boris.feld@octobus.net>
| date: Mon Jul 24 22:39:55 2017 +0200
| summary: myfeature
|
o <span style="color:olive;">changeset: 0:478309adfd3c</span>
user: Boris Feld <boris.feld@octobus.net>
date: Mon Jul 24 16:01:32 2017 +0200
summary: ROOT
</pre>
#### Topic rebase
Topics can be rebased easily on their base branch
<pre>
$> hg rebase
rebasing 1:3d2362d21bb4 "myfeature"
switching to topic myfeature
</pre>
#### Result
<pre>
$> hg log -G
@ <span style="color:olive;">changeset: 3:0a51e0d4d460</span>
| tag: tip
| <span style="background-color:green;">topic: myfeature</span>
| user: Boris Feld <boris.feld@octobus.net>
| date: Mon Jul 24 22:39:55 2017 +0200
| summary: myfeature
|
o <span style="color:olive;">changeset: 2:03a68957ddd8</span>
| parent: 0:478309adfd3c
| user: Boris Feld <boris.feld@octobus.net>
| date: Mon Jul 24 22:39:27 2017 +0200
| summary: default
|
o <span style="color:olive;">changeset: 0:478309adfd3c</span>
user: Boris Feld <boris.feld@octobus.net>
date: Mon Jul 24 16:01:32 2017 +0200
summary: ROOT
</pre>
#### Topic push
You can push topic without -f if you push only 1 head:
<pre>
hg push -r myfeature
</pre>
Even if the topic is not up-to-date to its branch.
## Stack Workflow
#### Stack
<pre>
$> hg stack
###### topic: <span style="color:green;">myfeature</span>
###### branch: feature
<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>
<span style="color:olive;">t3</span><span style="color:green;">:</span> Step3
<span style="color:olive;">t2</span><span style="color:green;">:</span> Step2
<span style="color:olive;">t1</span><span style="color:green;">:</span> Step
<span style="color:grey;">t0^ Trunk</span>
</pre>
#### Why Stack?
* Feature = multiple steps,
* Smaller = Simpler
* Simpler = Earlier merge in trunk
* Ease experiment with Alternative
* etc…
#### Prev
<pre>
$> hg prev
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
[<span style="color:blue;">7</span>] Step3
$> hg stack
###### topic: <span style="color:green;">myfeature</span>
###### branch: feature
<span style="color:olive;">t4</span><span style="color:green;">:</span> Step4
<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>
<span style="color:olive;">t2</span><span style="color:green;">:</span> Step2
<span style="color:olive;">t1</span><span style="color:green;">:</span> Step
<span style="color:grey;">t0^ Trunk</span>
</pre>
#### Next
<pre>
$> hg next
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
[<span style="color:blue;">8</span>] Step4
$> hg stack
###### topic: <span style="color:green;">myfeature</span>
###### branch: feature
<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>
<span style="color:olive;">t3</span><span style="color:green;">:</span> Step3
<span style="color:olive;">t2</span><span style="color:green;">:</span> Step2
<span style="color:olive;">t1</span><span style="color:green;">:</span> Step
<span style="color:grey;">t0^ Trunk</span>
</pre>
#### T\#
<pre>
$> hg update --rev t2
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
[<span style="color:blue;">8</span>] Step4
$> hg stack
###### topic: <span style="color:green;">myfeature</span>
###### branch: feature
<span style="color:olive;">t4</span><span style="color:green;">:</span> Step4
<span style="color:olive;">t3</span><span style="color:green;">:</span> Step3
<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>
<span style="color:olive;">t1</span><span style="color:green;">:</span> Step
<span style="color:grey;">t0^ Trunk</span>
</pre>
#### Editing mid-stack
<pre>
$> hg update --rev t1
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$> hg commit --amend -m "Step1"
<span style="color:gold;">3 new orphan changesets</span>
</pre>
#### What have we done?
<pre>
$> hg log -G -T compact
@ <span style="color:olive;">9</span>[tip] 1aa1be5ada40 Step1
|
| o <span style="color:olive;">8</span> cf90b2de7e65 Step4 <span style="color:red;">(orphan)</span>
| |
| o <span style="color:olive;">7</span> e208d4205c8e Step3 <span style="color:red;">(orphan)</span>
| |
| o <span style="color:olive;">6</span> 673ff300cf3a Step2 <span style="color:red;">(orphan)</span>
| |
| <span style="color:grey;">x 5 8bb88a31dd28 Step</span>
|/
o <span style="color:olive;">4</span> 3294c1730df7 Trunk
~
</pre>
#### Stack to the rescue!
<pre>
$> hg stack
###### topic: <span style="color:green;">myfeature</span>
###### branch: feature
<span style="color:olive;">t4</span><span style="color:red;">$</span> Step4<span style="color:red;"> (orphan)</span>
<span style="color:olive;">t3</span><span style="color:red;">$</span> Step3<span style="color:red;"> (orphan)</span>
<span style="color:olive;">t2</span><span style="color:red;">$</span> Step2<span style="color:red;"> (orphan)</span>
<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>
<span style="color:grey;">t0^ Trunk</span>
</pre>
#### Don't panic
<pre>
$> hg next --evolve
move:[<span style="color:blue;">6</span>] Step2
atop:[<span style="color:blue;">9</span>] Step1
working directory now at <span style="color:olive;">d72473cbf9a6</span>
$> hg stack
###### topic: <span style="color:green;">myfeature</span>
###### branch: feature
<span style="color:olive;">t4</span><span style="color:red;">$</span> Step4<span style="color:red;"> (orphan)</span>
<span style="color:olive;">t3</span><span style="color:red;">$</span> Step3<span style="color:red;"> (orphan)</span>
<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>
<span style="color:olive;">t1</span><span style="color:green;">:</span> Step1
<span style="color:grey;">t0^ Trunk</span>
</pre>
#### Go on
<img src="https://media.giphy.com/media/KBx7fQoLxuV7G/giphy.gif">
#### Go on
<pre>
$> hg next --evolve
move:[<span style="color:blue;">7</span>] Step3
atop:[<span style="color:blue;">10</span>] Step2
working directory now at <span style="color:olive;">4062d6ecd214</span>
$> hg stack
###### topic: <span style="color:green;">myfeature</span>
###### branch: feature
<span style="color:olive;">t4</span><span style="color:red;">$</span> Step4<span style="color:red;"> (orphan)</span>
<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>
<span style="color:olive;">t2</span><span style="color:green;">:</span> Step2
<span style="color:olive;">t1</span><span style="color:green;">:</span> Step1
<span style="color:grey;">t0^ Trunk</span>
</pre>
#### Go on
<pre>
$> hg next --evolve
move:[<span style="color:blue;">8</span>] Step4
atop:[<span style="color:blue;">11</span>] Step3
working directory now at <span style="color:olive;">4dcd9dfedf1b</span>
$> hg stack
###### topic: <span style="color:green;">myfeature</span>
###### branch: feature
<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>
<span style="color:olive;">t3</span><span style="color:green;">:</span> Step3
<span style="color:olive;">t2</span><span style="color:green;">:</span> Step2
<span style="color:olive;">t1</span><span style="color:green;">:</span> Step1
<span style="color:grey;">t0^ Trunk</span>
</pre>
#### Go on
<pre>
$> hg next --evolve
no children
</pre>
#### Better!
<pre>
$> hg log -G -T compact
@ <span style="color:olive;">12</span>[tip] 4dcd9dfedf1b Step4
|
o <span style="color:olive;">11</span> 4062d6ecd214 Step3
|
o <span style="color:olive;">10</span> d72473cbf9a6 Step2
|
o <span style="color:olive;">9</span> 1aa1be5ada40 Step1
|
o <span style="color:olive;">4</span> 3294c1730df7 Trunk
~
</pre>
#### More Rewrite Tools
<table>
<tr>
<th>Operation</th>
<th>command</th>
</tr>
<tr>
<td>Modify</td>
<td>`hg amend`<br></td>
</tr>
<tr>
<td>Remove</td>
<td>`hg prune`<br></td>
</tr>
<tr>
<td>Move</td>
<td>`hg grab`<br></td>
</tr>
<tr>
<td>Split</td>
<td>`hg split`<br></td>
</tr>
<tr>
<td>Fold</td>
<td>`hg fold`<br></td>
</tr>
</table>
#### Multi headed stack
<pre>
$> hg log -G -T compact
@ <span style="color:olive;">6</span>[tip] 189f54192937 Step4.5
|
| o <span style="color:olive;">5</span> c1a91e7c74f5 Step5
|/
o <span style="color:olive;">4</span> 826d2fbb601a Step4
|
o <span style="color:olive;">3</span> 08bcdd8d972b Step3
|
o <span style="color:olive;">2</span> 06cb53532f1b Step2
|
o <span style="color:olive;">1</span> 3eb38d10980d Step1
~
</pre>
#### Multi headed stack
<pre>
$> hg stack
###### topic: <span style="color:green;">myfeature</span> (<span style="color:olive;">2 heads</span>)
###### branch: feature
<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>
<span style="color:grey;">t4^ Step4 (base)</span>
<span style="color:olive;">t5</span><span style="color:green;">:</span> Step5
<span style="color:olive;">t4</span><span style="color:green;">:</span> Step4
<span style="color:olive;">t3</span><span style="color:green;">:</span> Step3
<span style="color:olive;">t2</span><span style="color:green;">:</span> Step2
<span style="color:olive;">t1</span><span style="color:green;">:</span> Step1
<span style="color:grey;">t0^ Trunk</span>
</pre>
## Distributed Workflow
#### propagation
Obsolescence can be exchanged:
* push, pull
* bundle / unbundle (hg 4.3+)
(affects draft history only)
#### Exchanging draft
* Works on multiple machines
* Collaborate with others
* Whole new play field == new traps
#### Example
<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'>
<div class='left' style='order:1; width: 50%'>
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
// Revisions
node[group=main];
Root -> "A";
Root [shape="circle"];
}
~~~
</div>
<div class='right' style='order:2; width: 50%'>
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
// Revisions
node[group=main];
Root -> "A";
Root [shape="circle"];
}
~~~
</div>
</div>
#### time pass
<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'>
<div class='left' style='order:1; width: 50%'>
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
// Revisions
node[group=main];
Root -> "A1";
node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"];
Root -> "A";
// Obsolescence links
edge[dir=back, style=dotted, arrowtail=dot];
"A" -> "A1";
Root [shape="circle"];
}
~~~
</div>
<div class='right' style='order:2; width: 50%'>
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
// Revisions
node[group=main];
Root -> "A" -> B;
Root [shape="circle"];
}
~~~
</div>
</div>
#### Instability
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
// Revisions
node[group=main];
Root -> "A1";
"B";
node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"];
Root -> "A" -> "B";
// Obsolescence links
edge[dir=back, style=dotted, arrowtail=dot];
"A" -> "A1";
Root [shape="circle"];
B [fillcolor="#FF3535"];
}
~~~
#### It's smart
<img src="https://media2.giphy.com/media/ZThQqlxY5BXMc/giphy.gif">
#### Stabilization
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
// Revisions
node[group=main];
Root -> "A1" -> "B1";
node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"];
Root -> "A" -> "B";
// Obsolescence links
edge[dir=back, style=dotted, arrowtail=dot];
"A" -> "A1";
"B" -> "B1";
Root [shape="circle"];
}
~~~
#### rewrite anything?
Phases enforce a reliable history:
* **draft**: can we rewritten
* **public**: immutable part of the history
Contact your local workflow manager.
## Helpfull Tooling
#### Summary
<pre>
$> hg summary
<span style="color:olive;">parent: 10:890ac95deb83 </span>tip (orphan)
Head
branch: feature
commit: (clean)
update: (current)
phases: 9 draft
orphan: <span style="color:red;">1 changesets</span>
topic: <span style="color:green;">myfeature</span>
</pre>
#### Topics
<pre>
$> hg topics
4.3compat
doc
evolvecolor
import-checker
more-output
obscache
obsfatefixes
obsmarkerbitfield
obsrangecacheiterative
packaging
prev-next
split
stack_orphan_bug
tutorial
* tutorialtypos
</pre>
#### Topics age
<pre>
$> hg topics --age
tutorial (5 hours ago)
<span style="color:green;"> * </span><span style="color:green;">tutorialtypos </span> (5 hours ago)
4.3compat (4 days ago)
prev-next (12 days ago)
obsfatefixes (2 weeks ago)
more-output (3 weeks ago)
obsmarkerbitfield (2 months ago)
obscache (2 months ago)
evolvecolor (2 months ago)
obsrangecacheiterative (2 months ago)
stack_orphan_bug (2 months ago)
doc (3 months ago)
split (3 months ago)
import-checker (4 months ago)
packaging (4 months ago)
</pre>
#### Topics verbose
<pre class="shell_output">
$> hg topics --verbose
4.3compat (on branch: default, 1 changesets, <span style="color:teal;">43 behind</span>)
doc (on branch: stable, 1 changesets, <span style="color:teal;">415 behind</span>)
evolvecolor (on branch: default, 1 changesets, <span style="color:teal;">369 behind</span>)
import-checker (on branch: default, 1 changesets, <span style="color:teal;">637 behind</span>)
more-output (on branch: default, 1 changesets, <span style="color:teal;">104 behind</span>)
obscache (on branch: default, 1 changesets, <span style="color:teal;">325 behind</span>)
obsfatefixes (on branch: default, 1 changesets, <span style="color:teal;">82 behind</span>)
obsmarkerbitfield (on branch: default, 1 changesets, <span style="color:teal;">324 behind</span>)
obsrangecacheiterative (on branch: default, 1 changesets, <span style="color:teal;">461 behind</span>)
packaging (on branch: default, 1 changesets, <span style="color:teal;">2521 behind</span>)
prev-next (on branch: default, 4 changesets, <span style="color:teal;">72 behind</span>)
split (on branch: default, 1 changesets, <span style="color:teal;">492 behind</span>)
stack_orphan_bug (on branch: default, 1 changesets, <span style="color:teal;">474 behind</span>)
tutorial (on branch: default, 2 changesets, <span style="color:teal;">492 behind</span>)
<span style="color:green;"> * </span><span style="color:green;">tutorialtypos </span> (on branch: default, 3 changesets, <span style="color:red;">1 unstable</span>, <span style="color:olive;">2 heads</span>, <span style="color:teal;">2 behind</span>)
</pre>
#### Log
<pre>
$ hg log -G --hidden -T '{node|short}\n{obsfate}\n'
@ c55cb2ee8a91
|
o 23abfc79b7ce
|
| o 4302274177b9 <span style="color:red;">(orphan)</span>
| |
| <span style="color:grey;">x fba593aaaa10</span>
|/ rewritten as c55cb2ee8a91;
o 2ff53d8bf7d7
</pre>
#### Evolve --list
<pre>
$> hg evolve --list
<span style="color:gold;">9ac0d376e01c</span>: changelog: introduce a 'tiprev' method
<span style="color:red;">orphan</span>: <span style="color:grey;">52ec3072fe46</span> (obsolete parent)
<span style="color:gold;">3efd3eab9860</span>: changelog: use 'tiprev()' in 'tip()'
<span style="color:red;">orphan</span>: <span style="color:red;">9ac0d376e01c</span> (orphan parent)
</pre>
(see also `hg evolve --list --rev`)
#### Obslog
<pre>
$> hg obslog
@ <span style="color:olive;">c55cb2ee8a91</span> <span style="color:blue;">(4)</span> A2
|
| o <span style="color:olive;">4302274177b9</span> <span style="color:blue;">(2)</span> A1
|/
x <span style="color:olive;">fba593aaaa10</span> <span style="color:blue;">(1)</span> A
rewritten(description, parent) as <span style="color:olive;">c55cb2ee8a91</span>
by <span style="color:green;">Boris Feld <boris.feld@octobus.net></span>
<span style="color:teal;">(Thu Jun 22 00:00:29 2017 +0200)</span>
rewritten(description) as <span style="color:olive;">4302274177b9</span>
by <span style="color:green;">Boris Feld <boris.feld@octobus.net></span>
<span style="color:teal;">(Thu Jun 22 00:00:28 2017 +0200)</span>
</pre>
#### Obslog --patch
<pre>
$> hg obslog -p
@ <span style="color:olive;">f6b1dded9e95</span> <span style="color:blue;">(2)</span> A1
|
x <span style="color:olive;">364e589e2bac</span> <span style="color:blue;">(1)</span> A
rewritten(description, parent) as <span style="color:olive;">a6be771bedcf</span>
by <span style="color:green;">Boris Feld <boris.feld@octobus.net></span>
<span style="color:teal;">(Thu Jun 22 00:00:29 2017 +0200)</span>
(No patch available yet, changesets rebased)
rewritten(description) as <span style="color:olive;">f6b1dded9e95</span>
by <span style="color:green;">Boris Feld <boris.feld@octobus.net></span>
<span style="color:teal;">(Thu Jun 22 00:00:28 2017 +0200)</span>
--- a/364e589e2bac-changeset-description
+++ b/f6b1dded9e95-changeset-description
@@ -1,1 +1,1 @@
-A
+A1
</pre>
#### Journal
<pre>
$> hg journal
previous locations of '.':
2fb6d364d453 commit --amend -m Step1
701fb5d73e07 update --rev t1
ae11635effb7 commit -A -m Step2
701fb5d73e07 commit -A -m Step
</pre>
## Semantic
#### Use the right commands!
<img src="https://media.giphy.com/media/uRb2p09vY8lEs/giphy.gif">
#### smart commands
<table>
<tr>
<th>Operation</th>
<th>command</th>
</tr>
<tr>
<td>Modify</td>
<td>`hg amend`<br></td>
</tr>
<tr>
<td>Remove</td>
<td>`hg prune`<br></td>
</tr>
<tr>
<td>Move</td>
<td>`hg grab`<br></td>
</tr>
<tr>
<td>Split</td>
<td>`hg split`<br></td>
</tr>
<tr>
<td>Fold</td>
<td>`hg fold`<br></td>
</tr>
</table>
## Instability
#### Evolution
* Unlock powerful unique features
* Hide **most** of the complexity
* Help with orphan situations
- Automatic detection
- Automated resolution `hg help evolve`
#### instability
(currently: *instability*)
* **Orphans:** ancestors were rewritten
* **Divergence:** branching in evolutions
- Content-divergence: independent rewrites
- Phase-divergence: older version got published
## Conclusion
#### Work in progress
* Concepts are solid
* Implementation in progress
* Common case works fine
* Some rough edges
* Feedback → priority
#### Use Evolution Today
install `hg-evolve`
<pre>
[extensions]
evolve=
topic= ## provides hg stack
</pre>
#### Helps
* Mailing-list: `evolve-testers@mercurial-scm.org`
* IRC channel: `#mercurial`
#### Documentation
* Documentation: <br/><small><https://www.mercurial-scm.org/doc/evolution/index.html></small>
* Wiki: <br/><small><https://www.mercurial-scm.org/wiki/EvolveExtension></small>
## Conclusion
#### Rewrite all the things!
<img src="https://cdn.meme.am/cache/instances/folder258/500x/54913258.jpg">
#### Safety first!
<img src="https://media.giphy.com/media/46vrhWWOJ4wHC/giphy.gif">
## extra - Instability
#### Obsolete
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, style="filled", width=1, height=1, fillcolor="#7F7FFF", shape="pentagon"];
node[group=main];
Root -> New;
node[group=obsolete];
Root -> Obsolete;
// Obsolescence links
edge[dir=back, style=dotted, arrowtail=dot];
Obsolete -> New;
Obsolete [fillcolor="#DFDFFF"];
Root[shape="circle"];
}
~~~
#### Orphan
Now called `orphan`
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, style="filled", width=1, height=1, fillcolor="#7F7FFF", shape="pentagon"];
node[group=main];
Root -> New;
node[group=obsolete];
Root -> Obsolete -> Orphan;
// Obsolescence links
edge[dir=back, style=dotted, arrowtail=dot];
Obsolete -> New;
Obsolete [fillcolor="#DFDFFF"];
Orphan [fillcolor="#FF3535"];
Root[shape="circle"];
}
~~~
#### Phase-divergent
Now called `Phase-divergent`
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, style="filled", width=1, height=1, fillcolor="#7F7FFF", shape="pentagon"];
node[group=main];
Root -> New;
node[group=obsolete];
Root -> Obsolete;
node[group=phase-divergent];
Root -> Phase-divergent;
// Obsolescence links
edge[dir=back, style=dotted, arrowtail=dot];
Obsolete -> New;
Obsolete -> Phase-divergent;
New [shape="circle"];
Obsolete [fillcolor="#DFDFFF"];
Phase-divergent [fillcolor="#FF3535"];
Root[shape="circle"];
}
~~~
#### Content-divergent
Now called `Content-divergent`
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, style="filled", width=1, height=1, fillcolor="#7F7FFF", shape="pentagon"];
Root -> Base;
Root -> Content-divergent1;
Root -> Content-divergent2;
// Obsolescence links
edge[dir=back, style=dotted, arrowtail=dot];
Base -> Content-divergent1;
Base -> Content-divergent2;
Base [shape="pentagon", fillcolor="#DFDFFF"];
Content-divergent1 [fillcolor="#FF3535"];
Content-divergent2 [fillcolor="#FF3535"];
Root[shape="circle"];
}
~~~
## extra-commands
#### Amend
<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'>
<div class='left' style='order:1; width: 20%'>
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
// Revisions
node[group=main];
Root -> "A";
Root [shape="circle"];
}
~~~
</div>
<div class="middle" style='order:2; width: 60%'>
To amend A:
hg amend -m 'A1'
</div>
<div class='right' style='order:2; width: 20%'>
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
// Revisions
node[group=main];
Root -> "A1";
node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"];
Root -> "A";
// Obsolescence links
edge[dir=back, style=dotted, arrowtail=dot];
"A" -> "A1";
Root [shape="circle"];
}
~~~
</div>
</div>
#### Prune
<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'>
<div class='left' style='order:1; width: 20%'>
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
// Revisions
node[group=main];
Root -> "A";
Root [shape="circle"];
}
~~~
</div>
<div class="middle" style='order:2; width: 60%'>
To prune A:
hg prune -r "desc(A)"
</div>
<div class='right' style='order:2; width: 20%'>
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
Root [shape="circle"];
// Revisions
node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"];
Root -> "A";
}
~~~
</div>
</div>
#### Rebase
<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'>
<div class='left' style='order:1; width: 20%'>
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
// Revisions
node[group=branch];
Root -> B;
node[group=main];
Root -> "A";
Root [shape="circle"];
}
~~~
</div>
<div class="middle" style='order:2; width: 60%'>
In order to rebase A on top of B;
hg rebase -r "desc(A)" -d "desc(B)"
</div>
<div class='right' style='order:2; width: 20%'>
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
// Revisions
node[group=branch];
Root -> B -> "A'";
node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"];
Root -> "A";
// Obsolescence links
edge[dir=back, style=dotted, arrowtail=dot];
"A" -> "A'";
Root [shape="circle"];
}
~~~
</div>
</div>
#### Fold
<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'>
<div class='left' style='order:1; width: 15%'>
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
// Revisions
node[group=branch];
Root -> A -> B;
Root [shape="circle"];
}
~~~
</div>
<div class="middle" style='order:2; width: 70%'>
To fold A and B:
hg fold -r "desc(A)" -r "desc(B)" -m "C"
</div>
<div class='right' style='order:2; width: 15%'>
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
// Revisions
node[group=branch];
Root -> C;
node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"];
Root -> A -> B;
// Obsolescence links
edge[dir=back, style=dotted, arrowtail=dot];
"A" -> "C";
"B" -> "C";
Root [shape="circle"];
}
~~~
</div>
</div>
#### Split
<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'>
<div class='left' style='order:1; width: 20%'>
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
// Revisions
node[group=branch];
Root -> A;
Root [shape="circle"];
}
~~~
</div>
<div class="middle" style='order:2; width: 60%'>
Split in two:
hg split -r "desc(A)"
</div>
<div class='right' style='order:2; width: 20%'>
~~~graphviz
digraph G {
rankdir="BT";
graph[splines=polyline];
node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"];
// Revisions
node[group=branch];
Root -> B -> C;
node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"];
Root -> A;
// Obsolescence links
edge[dir=back, style=dotted, arrowtail=dot];
"A" -> "C";
"A" -> "B";
Root [shape="circle"];
}
~~~
</div>
</div>
-->
|