# HG changeset patch # User Pierre-Yves David # Date 1430332926 25200 # Node ID 1e3c607cf4a5aebb136442e5f8613cf6b3c7cd07 # Parent 8aa9a21156fe2a5e1835722d830f9d607edc6d39# Parent 12d5c9eaa86d2cfbd09952fc7dd099b710692020 merge with stable diff -r 8aa9a21156fe -r 1e3c607cf4a5 README --- a/README Wed Apr 29 10:36:43 2015 -0700 +++ b/README Wed Apr 29 11:42:06 2015 -0700 @@ -51,6 +51,10 @@ Changelog ========= +5.1.5 -- + +- minor documentation cleanup + 5.1.4 -- 2015-04-23 - significant documentation update diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/concepts.rst --- a/docs/concepts.rst Wed Apr 29 10:36:43 2015 -0700 +++ b/docs/concepts.rst Wed Apr 29 11:42:06 2015 -0700 @@ -24,7 +24,7 @@ isn't quite right yet, and the diagrams are missing for malformatted.) -This document follows standard set theory notation: +This document follows standard set theory notation:: x ∈ A: x is a member of A @@ -133,7 +133,7 @@ public phase; only mutable changesets are divergent). The collective term for unstable, bumped, and divergent changeset is -*troubled*: +*troubled*:: troubled = unstable ∪ bumped ∪ divergent @@ -155,7 +155,7 @@ changesets; these are bugs and will be fixed in due course.) All hidden changesets are obsolete, and all obsolete changesets are -part of your repository. Mathematically speaking: +part of your repository. Mathematically speaking:: repo ⊇ obsolete ⊇ hidden @@ -177,7 +177,7 @@ Why is this changeset visible? ------------------------------ -Any changeset which is not hidden is *visible*. That is, +Any changeset which is not hidden is *visible*. That is, :: visible = repo ∖ hidden @@ -185,7 +185,7 @@ changesets that are in *repo* but not in *hidden*.) After amending or pruning a changeset, you might expect it to be -hidden. It doesn't always work out that way. The precise rules are: +hidden. It doesn't always work out that way. The precise rules are:: hideable = obsolete blockers = bookmarks ∪ parents(workingcopy) ∪ localtags @@ -193,7 +193,7 @@ This will probably be clearer with a worked example. First, here's a repository with some obsolete changesets, some troubled changesets, -one bookmark, a working copy, and some hidden changesets: +one bookmark, a working copy, and some hidden changesets:: x-x / @@ -202,7 +202,7 @@ x-x-o Here's the computation required to determine which changesets are -hidden: +hidden:: repo = { 0, 1, 2, 3, 4, 5, 6, 7, 8 } diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/evolve-collaboration.rst --- a/docs/evolve-collaboration.rst Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -.. Copyright 2011 Pierre-Yves David -.. Logilab SA - ------------------------------------------------- -Collaboration Using Evolve: A user story ------------------------------------------------- - - -After having written some code for ticket #42, Alice starts a patch -(this will be kind of like a 'work-in-progress' checkpoint -initially):: - - $ hg ci -m '[entities] remove magic' - -Instant patch! Note how the default phase of this changeset is (still) -in "draft" state. - -This is easily checkable:: - - $ hg phase tip - 827: draft - -See? Until the day it becomes a "public" changeset, this can be -altered to no end. How? It happens with an explicit:: - - $ hg phase --public - -In practice, pushing to a "publishing" repository can also turn draft -changesets into public ones. Older Mercurial releases are automatically -"publishing" since they do not have the notion of non-public changesets -(or mutable history). - -During the transition from older Mercurial servers to new ones, this will -happen often, so be careful. - -Now let's come back to our patch. Next hour sees good progress and Alice -wants to complete the patch with the recent stuff (all that's shown by -an "hg diff") to share with a co-worker, Bob:: - - $ hg amend -m '[entities] fix frobulator (closes #42)' - -Note that we also fix the commit message. (For recovering MQ users: this -is just like "hg qrefresh -m"). - -Before leaving, let's push to the central shared repository. That will -give Bob the signal that something is ripe for review / further amendments:: - - $ hg push # was done with a modern mercurial, draft phase is preserved - -The next day, Bob, who arrives very early, can immediately work out -some glitches in the patch. - -He then starts two others, for ticket #43 and #44 and finally commits them. -Then, as original worker arrives, he pushes his stuff. - -Alice, now equipped with enough properly sugared coffee to survive the -next two hours:: - - $ hg pull - -Then:: - - $ hg up "tip ~ 2" - -brings her to yesterday's patch. Indeed the patch serial number has -increased (827 still exists but has been obsoleted). - -She understands that her original patch has been altered. But how did it -evolve? - -The enhanced hgview shows the two patches. By default only the most -recent version of a patch is shown. - -Now, when Alice installed the mutable-history extensions, she got an alias -that allows her to see the diff between two amendments, defined like this:: - - odiff=diff --rev 'limit(obsparents(.),1)' --rev . - -She can see exactly how Bob amended her work. - -* odiff - - -Amend ... Stabilize --------------------- - -Almost perfect! Alice just needs to fix a half dozen grammar oddities in -the new docstrings and it will be publishable. - -Then, another round of: - - $ hg amend - -and a quick look at hgview ... shows something strange (at first). - -Ticket #42 yesterday's version is still showing up, with two descendant lineages: - -* the next version, containing grammar fixes, - -* the two stacked changesets for tickets #43 .. 44 committed by Bob. - -Indeed, since this changeset still has non-obsolete descendant -changesets it cannot be hidden. This branch (old version of #42 and -the two descendants by C.W.) is said to be _unstable_. - -Why would one want such a state? Why not auto-stabilize each time "hg -amend" is typed out? - -Alice for one, wouldn't want to merge each time she amends something that -might conflict with the descendant changesets. Remember she is -currently updating the very middle of an history! - -Being now done with grammar and typo fixes, Alice decides it is time to -stabilize again the tree. She does:: - - $ hg evolve - -two times, one for each unstable descendant. The last time, hgview -shows her a straight line again. Wow! that feels a bit like a -well-planned surgical operation. At the end, the patient tree has -been properly trimmed and any conflict properly handled. - -Of course nothing fancy really happened: each "stablilize" can be -understood in terms of a rebase of the next unstable descendant to the -newest version of its parent (including the possible manual conflict -resolution intermission ...). - -Except that rebase is a destructive (it removes information from the -repository), unrecoverable operation, and the "evolve + obsolete" -combo, using changeset copy and obsolescence marker, provides evolution -semantics by only adding new information to the repository (but more -on that later). - -She pushes again. - diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/evolve-faq.rst --- a/docs/evolve-faq.rst Wed Apr 29 10:36:43 2015 -0700 +++ b/docs/evolve-faq.rst Wed Apr 29 11:42:06 2015 -0700 @@ -1,19 +1,19 @@ .. Copyright 2011 Pierre-Yves David .. Logilab SA ---------------------------------------------------------------------- +------------- Evolve How To ---------------------------------------------------------------------- +------------- Add a changeset: ``commit`` ------------------------------------------------------------- +--------------------------- Just use commit as usual. New changesets will be in the `draft` phase. Rewrite a changeset: ``commit --amend`` ------------------------------------------------------------- +--------------------------------------- It writes a new changeset combining working-directory parent changes and parent. It will work on any `draft` or `secret` changeset. It will not work on `public` @@ -36,7 +36,7 @@ Move a changeset: ``grab`` ------------------------------------------------------------- +-------------------------- You can use ``hg grab `` to move a rev at your current location, making the old version obsolete. @@ -45,7 +45,7 @@ Delete a changeset: ``prune`` ------------------------------------------------------------- +----------------------------- A new ``prune`` command allows removing a changeset. @@ -53,7 +53,7 @@ Moving within the history: ``gdown`` and ``gup`` ------------------------------------------------------------- +------------------------------------------------ While working on mutable part of the history you often need to move between mutable commits. @@ -67,7 +67,7 @@ feeling back. Collapse changesets: ``fold`` ------------------------------------------------------------- +----------------------------- You can use ``hg fold`` to collapse multiple changesets in a single one. @@ -78,7 +78,7 @@ ``hg fold -r `` fold everything changeset matching the revset together. Getting changes out of a commit ------------------------------------------------------------- +------------------------------- The ``hg uncommit`` command lets you rewrite the parent commit without selected changed files. Target files content is not altered and @@ -94,7 +94,7 @@ M celestine Split a changeset ------------------------ +----------------- To split on file boundaries, just use ``uncommit`` command. @@ -120,7 +120,7 @@ Update my current work in progress after a pull ----------------------------------------------- +----------------------------------------------- Whenever you are working on some changesets, it is more likely that a pull will, eventually, import new changesets in your tree. @@ -133,7 +133,7 @@ Move multiple changesets: ``rebase`` ------------------------------------------------------------- +------------------------------------ You can still use rebase to move a whole segment of the changeset graph together. @@ -141,7 +141,7 @@ divergent versions of the changesets. Resolve history troubles: ``evolve`` ------------------------------------------------------------- +------------------------------------ When you rewrite (amend) a changeset with children without rewriting those children you create *unstable* changesets and *suspended @@ -155,7 +155,7 @@ Fix my history afterward: ``prune -n`` ------------------------------------------------------------- +-------------------------------------- Sometimes you need to create an obsolete marker by hand. This may happen when upstream has applied some of your patches for example. @@ -164,7 +164,7 @@ marker. View diff from the last amend ------------------------------------------------------------- +----------------------------- An ``odiff`` alias have been added by ``enable.sh`` @@ -173,7 +173,7 @@ odiff = diff --rev 'limit(precursors(.),1)' --rev . View obsolete markers ------------------------------------------------------------- +--------------------- hgview_ is the only viewer that currently supports this feature. You need version 1.6.2 @@ -193,10 +193,10 @@ Important Note -===================================================================== +============== View change to your file ------------------------------------------------------------- +------------------------ Extinct changesets are hidden using the *hidden* feature of mercurial. diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/evolve-good-practice.rst --- a/docs/evolve-good-practice.rst Wed Apr 29 10:36:43 2015 -0700 +++ b/docs/evolve-good-practice.rst Wed Apr 29 11:42:06 2015 -0700 @@ -6,7 +6,7 @@ ----------------------------------------- Avoid unstability --------------------------------- +----------------- The less unstability you have the less you need to resolve. @@ -14,7 +14,7 @@ not ready neither. Branch as much as possible --------------------------------- +-------------------------- This is not MQ; you are not constrained to linear history. @@ -22,7 +22,7 @@ and conflict. Rewrite your changes only ------------------------------------------------- +------------------------- There is no descent conflict detection and handling right now. Rewriting other people's changesets guarantees that you will get @@ -40,7 +40,7 @@ Do not get too confident ---------------------------- +------------------------ This is an experimental extension and a complex concept. This is beautiful, powerful and robust on paper, but the tool and your mind may not be prepared for diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/figures/edit-is-rewrite-step1.svg --- a/docs/figures/edit-is-rewrite-step1.svg Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,509 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - ";Alice;Babar"19b08111 - - - - "19b08111;Alice;Babar,Celeste"925d8319 - - - - "6fcdd7fe;Bob;Babar"⟶ebc2b5a1 - - - - "925d8319;Alice;Babar,Celeste,flore"6fcdd7fe - - - - - - - diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/figures/edit-is-rewrite-step2.svg --- a/docs/figures/edit-is-rewrite-step2.svg Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,832 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - ";Alice;Babar"19b08111 - - - - "19b08111;Alice;Babar,Celeste"925d8319 - - - - "6fcdd7fe;Bob;Babar"⟶ebc2b5a1 - - - - "925d8319;Alice;Babar,Celeste,flore"6fcdd7fe - - - - - - - "19b08111;Bob;Babar,Celeste"1a25964c - - - - "6d9e1549;Bob;Babar"dda72e36 - - - - "1a25964c;Alice;Babar,Celeste,Flore"6d9e1549 - - - - - - diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/figures/error-conflicting.svg --- a/docs/figures/error-conflicting.svg Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - -2012-03-18 23:47ZCanvas 1Layer 1A’AA’’Conflicting diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/figures/error-extinct.svg --- a/docs/figures/error-extinct.svg Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - -2012-03-18 23:47ZCanvas 1Layer 1ABBAA'CC'CObsoleteUnstableextinctsuspended diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/figures/error-obsolete.svg --- a/docs/figures/error-obsolete.svg Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - -2012-03-18 23:47ZCanvas 1Layer 1ACBB’C’Obsolete diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/figures/error-unstable.svg --- a/docs/figures/error-unstable.svg Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - -2012-03-18 23:47ZCanvas 1Layer 1ABAA'ObsoleteUnstableB diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/figures/example-1-update.svg --- a/docs/figures/example-1-update.svg Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - -2012-03-21 08:32ZCanvas 1Layer 1AA’A diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/figures/example-2-split.svg --- a/docs/figures/example-2-split.svg Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - -2012-03-21 08:32ZCanvas 1Layer 1AA1A2A diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/figures/explain-troubles-concurrent-10-solution.svg --- a/docs/figures/explain-troubles-concurrent-10-solution.svg Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,929 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - B - - - - A - - - - Z - - - - - - B' - - - - B'' - - - - - - - - - - B - - - - A - - - - Z - - - - - - B' - - - - B'' - - - - - - - - - - - - B - - - - B' - - - - B'' - - - - B* - - - - - - - - B* - - - diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/figures/explain-troubles-concurrent-10-sumup.svg --- a/docs/figures/explain-troubles-concurrent-10-sumup.svg Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1451 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - Local - Distant - final = divergent - - - - - initial - - - - B - - - - A - - - - Z - - - - - - - - B - - - - A - - - - Z - - - - - - B' - - - - - - - - B - - - - A - - - - Z - - - - - - B'' - - - - - - - - B - - - - A - - - - Z - - - - - - B' - - - - B'' - - - - - - - - diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/figures/explain-troubles-latecomer-10-sumup.svg --- a/docs/figures/explain-troubles-latecomer-10-sumup.svg Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1039 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - Local - Distant - final = tardif - - - - - - - - A - - - - Z - - - - - - - A - - - - Z - - - - - A' - - - - - initial - - - - v4.2 - - - - A - - - - Z - - - - - - A' - - - - - - - - v4.2 - - - - A - - - - Z - - - - - - diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/figures/explain-troubles-latecomer-15-solution.svg --- a/docs/figures/explain-troubles-latecomer-15-solution.svg Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,994 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - v4.2 - - - - A - - - - Z - - - - - - A' - - - - - - - - - v4.2 - - - - A - - - - Z - - - - - - A' - - Aᵟ - - - - - - - - diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/figures/explain-troubles-unstable-10-sumup.svg --- a/docs/figures/explain-troubles-unstable-10-sumup.svg Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - B - - - - A - - - - Z - - - - - - B' - - - - A' - - - - - - - Local - - - - - - B - - - - A - - - - Z - - - - - - C - - - - Distant - - - - - - - B - - - - A - - - - Z - - - - - - B' - - - - A' - - - - - - - - C - - - - final = instable - - - - - - B - - - - A - - - - Z - - - - - initial - - - - - - - diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/figures/explain-troubles-unstable-15-solution.svg --- a/docs/figures/explain-troubles-unstable-15-solution.svg Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1006 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - B - - - - A - - - - Z - - - - - - B' - - - - A' - - - - - - - - C - - - - - - - B - - - - A - - - - Z - - - - - - B' - - - - A' - - - - - - - - C - - - - - C' - - - - - - diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/figures/git.svg --- a/docs/figures/git.svg Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,863 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - B - - - - A - - - - Z - - - - - - B' - - - - A' - - - - - - - - - - - - B - - - - A - - - - Z - - - - - - B' - - - - A' - - - - - - C - - - - - feature-babar - other/feature-babar - feature-babar - - diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/figures/simple-3-merge.svg --- a/docs/figures/simple-3-merge.svg Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - -2012-03-21 08:32ZCanvas 1Layer 1AABBC diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/figures/simple-4-reorder.svg --- a/docs/figures/simple-4-reorder.svg Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - -2012-03-21 08:32ZCanvas 1Layer 1AABBA'B' diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/figures/simple-5-delete.svg --- a/docs/figures/simple-5-delete.svg Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - -2012-03-21 08:32ZCanvas 1Layer 1AA diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/from-mq.rst --- a/docs/from-mq.rst Wed Apr 29 10:36:43 2015 -0700 +++ b/docs/from-mq.rst Wed Apr 29 11:42:06 2015 -0700 @@ -1,12 +1,12 @@ .. Copyright 2011 Pierre-Yves David .. Logilab SA -------------------------------------------- +----------------------------------- From MQ To Evolve, The Refugee Book -------------------------------------------- +----------------------------------- Cheat sheet -------------- +----------- ============================== ============================================ mq command new equivalent @@ -28,10 +28,10 @@ Replacement details ---------------------- +------------------- hg qseries -``````````` +`````````` All your work in progress is now in real changesets all the time. @@ -45,7 +45,7 @@ wip = log -r 'not public()' --template='{rev}:{node|short} {desc|firstline}\n' hg qnew -```````` +``````` With evolve you handle standard changesets without an additional overlay. @@ -66,7 +66,7 @@ new-commit=secret hg qref -```````` +``````` A new command from evolution will allow you to rewrite the changeset you are currently on. Just call: @@ -90,7 +90,7 @@ .. note: refresh is an alias for amend hg qref --exclude -````````````````````` +````````````````` To remove changes from your current commit use:: @@ -98,7 +98,7 @@ hg qpop -````````` +``````` The following command emulates the behavior of hg qpop: @@ -136,14 +136,14 @@ hg qrm -``````` +`````` evolution introduce a new command to mark a changeset as "not wanted anymore".:: $ hg prune hg qfold -````````` +```````` :: @@ -151,14 +151,14 @@ $ hg fold first::last hg qdiff -````````` +```````` ``pdiff`` is an alias for `hg diff -r .^` It works like qdiff, but outside MQ. hg qfinish and hg qimport -```````````````````````````` +````````````````````````` These are not necessary anymore. If you want to control the mutability of changesets, see the phase feature. @@ -166,7 +166,7 @@ hg qcommit -``````````````` +`````````` If you really need to send patches through versioned mq patches, you should look at the qsync extension. diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/index.rst --- a/docs/index.rst Wed Apr 29 10:36:43 2015 -0700 +++ b/docs/index.rst Wed Apr 29 11:42:06 2015 -0700 @@ -4,6 +4,14 @@ Changeset Evolution with Mercurial ================================== +.. toctree:: + :maxdepth: 2 + + user-guide + sharing + concepts + from-mq + `evolve`_ is an experimental Mercurial extension for safe mutable history. .. _`evolve`: http://mercurial.selenic.com/wiki/EvolveExtension @@ -134,6 +142,6 @@ * If you're coming from MQ, see the `MQ migration guide`_ (incomplete). .. _`user guide`: user-guide.html +.. _`sharing mutable history`: sharing.html .. _`concepts`: concepts.html -.. _`sharing mutable history`: sharing.html .. _`MQ migration guide`: from-mq.html diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/instability.rst --- a/docs/instability.rst Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,222 +0,0 @@ -.. Copyright 2011 Pierre-Yves David -.. Logilab SA - ------------------------------------ -The instability Principle ------------------------------------ - - - -An intrinsic contradiction ------------------------------------ - -XXX starts by talking about getting ride of changeset. - -DVCSes bring two new major concepts to the version control scene: - - * History is organized as a robust DAG, - * History can be rewritten. - -However, the two concepts are in contradiction: - -To achieve a robust history, three key elements are gathered in *changesets*: - - * Full snapshot of the versioned content, - * Reference to the previous full snapshot used to build the new one, - * A description of the change which leads from the old content to the new content. - -All three elements are used to compute a *unique* hash that identifies the changeset -(with various other metadata). This identification is a key part of DVCS design. - -This is a very useful property because changing B's parent means -changing B's content too. This requires the creation of **another** -changeset, which is semantically good. - -.. figure:: ./figures/edit-is-rewrite-step2.svg - - -To avoid duplication, the older changeset is usually discarded from accessible -history. I'm calling them *obsolete* changesets. - - -But rewriting a changeset with children does not change the -children's parents! And because children of the rewritten changeset -still **depend** on the older "dead" version of the changeset, we -cannot get rid of this dead version. - -:: - - Schema base, A and A' and B. - -I'm calling these children **unstable** because they are based on a -dead changeset and prevent people from getting rid of it. - -This instability is an **unavoidable consequence** of the strict dependency of -changesets. Rewriting history always needs to take it into account and -provide a way to rewrite the descendants of the new changeset to avoid -coexistence of the old and new versions of a rewritten changeset. - - -Everybody is working around the issue ------------------------------------------------- - -I'm not claiming that rewriting history is impossible. People have been successfully -doing it for years. However they all need to work around *instability*. Several -workaround strategies exist. - - -Rewriting all at once -`````````````````````````` - -The simplest way to avoid instability is to ensure rewriting -operations always end in a stable situation. This is achieved by -rewriting all affected changesets at the same time. - -Rewriting all descendants at the same time when rewriting a changeset. - -:: - - Schema! - -Several Mercurial commands apply it: rebase, collapse, histedit. -Mercurial also refuses to amend changesets with descendants. The git -branch design enforces this approach in git too. - - -However, DVCS are **distributed**. This means that you do not control what -happens outside your repository. Once a changeset has been exchanged *outside*, -there is no way to be sure it does not have descendants somewhere else. -Therefore **if you rewrite changeset that exists elsewhere, you can't eradicate -the risk of instability.** - -Do not rewrite exchanged changesets -``````````````````````````````````` - -To work around the issue above, Mercurial introduced phases, which -prevent you from rewriting shared changesets and ensure others can't -pull certain changesets from you. But this is a very frustrating -limitation that prevents you to efficiently sharing, reviewing and -collaborating on mutable changesets. - -In the Git world, they use another approach to prevent instability. By -convention only a single developer works on a changeset contained in -a named branch. But once again this is a huge blocker for -collaborating. Moreover clueless people **will** mess up social -convention soon or later. - - -Lose the DAG robustness -```````````````````````````` - -The other approach in Mercurial is to keep the mutable part of the -history outside the DVCS constraint. This is the MQ approach of -sticking a quilt queue over Mercurial. - -This allow much more flexible workflow but two major feature are lost in the -process: - -:graceful merge: MQ uses plain patch to store changeset contents, which has - problems in changing context. Applying your queue - becomes very painful when context changes. - -:easy branching: A quilt queue is by definition a linear queue, increasing risk - of conflict. - -It is possible to collaborate over versioned MQ! But you are going to -have a lot of trouble. - -Ignore conflicts -``````````````````````````````````` - -Another ignored issue is a conflicting rewrite of the same changeset. -If a changeset is rewritten two times we have two newer versions, -and duplicated history is complicated to merge. - -Mercurial work around by - -The "One set of mutable changset == One developer" mantra is also a way to work -around conflicting rewriting of changeset. If two different people are able to - -The git branch model allows overwriting changeset version by another -one, but it does not care about divergent version. It is the equivalent -of "common ftp" source management for changesets. - -Facing The Danger Once And For All ------------------------------------------------- - -Above we saw that the more effort you put to avoid instability, the more options -you deny. And even the most restrictive workflow can't guarantee that instability -will never show up! - -Obsolete marker can handle the job -``````````````````````````````````` - -It is time to provide a full-featured solution to deal with -instability and to stop working around the issue! This is why I -am developing a new feature for Mercurial called "Obsolete markers". -Obsolete markers have two key properties: - - -* Any "old" changeset we want to get rid of is **explicitly** marked - as "obsolete" by history rewriting operations. - - By explicitly marking the obsolete part of the history, we will be able to - easily detect instability situation. - -* Relations between old and new version of changesets are tracked by obsolete - markers. - - By storing a meta-history of changeset evolution we are able to easily resolve - instability and edit conflicts [#]_ . - -.. [#] Edit conflicts is another major obstable to collaboration. See the - section dedicated to obsolete marker for details. - -Improved robustness == improved simplicity -```````````````````````````````````````````````` - -This proposal should **first** be seen as a safety measure. - -It allows detecting instability as soon as possible. - -:: - - $ hg pull - added 3 changeset - +2 unstable changeset - (do you want "hg evolve" ?) - working directory parent is obsolete! - $ hg push - outgoing unstable changesets - (use "hg evolve" or force the push) - -And it should not not encourage people to create instability. - -:: - - $ hg up 42 - $ hg commit --amend - changeset have descendant. - $ hg commit --amend -f - +5 unstable changeset - - $ hg rebase -D --rev 40::44 - rebasing already obsolete changeset 42:AAA will conflict with newer version 48:BBB - -While allowing powerful feature -```````````````````````````````````````````````` - - -* Help to automatically solve instability. - -* "prune" changeset remotely. - -* track resulting changeset when submitting patch//pull request. - -* Focus on what you do: - - I do not like the "all at once" model of history rewriting. I'm comfortable - with instability and obsolete marker offer all the tool to safely create and - handle instability locally. - - diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/obs-concept.rst --- a/docs/obs-concept.rst Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,390 +0,0 @@ -.. Copyright 2011 Pierre-Yves David -.. Logilab SA - ------------------------------------------------------------ -Why Do We Need a New Concept ------------------------------------------------------------ - -Current DVCSes are great tools for forging a series of flawless -changesets on your own. But they perform poorly when it comes to -**sharing** some work in progress and **collaborating** on such work -in progress. - -When people forge a new version of a changeset they actually create a -new changeset and get rid of the original changeset. Difficulties to -collaborate mostly came from the way old content is *removed* from -a repository. - -Mercurial Approach: Strip ------------------------------------------------------ - -With the current version of mercurial, every changeset that exists in -your repository is *visible* and *meaningful*. To delete old -(rewritten) changesets, mercurial removes them from the repository -storage with an operation called *strip*. After the *stripping*, the -repository looks as if the changeset never existed. - -This approach is simple and effective except for one big -drawback: you can remove changesets from **your repository only**. If -a stripped changeset exists in another repository it touches, it will -show up again. This is because a shared changeset becomes -part of a shared global history. Stripping a changeset from all -repositories is at best impractical and in most case impossible. - -As consequence, **you can not rewrite something once you exchange it with -others**. The old version will still exist along side the new one [#]_. - -Moreover stripping changesets creates backup bundles. This allows -restoration of the deleted changesets, but the process is painful. - -Finally, as the repository format is not optimized for deletion. stripping a -changeset may be slow in some situations. - -To sum up, the strip approach is very simple but does not handle -interaction with the outer world, which is very unfortunate for a -*Distributed* VCS. - -.. [#] various work around exists but they require their own workflows - which are distinct from the very elegant basic workflow of - Mercurial. - -Git Approach: Overwrite Reference ------------------------------------------------------ - -The Git approach to repository structure is a bit more complex: there -can be any amount of unrelated changesets in a repository, and **only -changesets referenced by a git branch** are *visible* and -*meaningful*. - - -.. figure:: ./figures/git.* - - -This simplifies the process of getting rid of old changesets. You can -just leave them in place and move the reference on the new one. You -can then propagate this change by moving the git-branch on remote host -with the newer version of the marker overwriting the older one. - -This approach goes a bit further but still has a major drawback: - -Because you **overwrite** the git-branch, you have no conflict -resolution. The last to act wins. This makes collaboration on multiple -changesets difficult because you can't merge concurrent updates on a -changeset. - -Every overwrite is a forced operation where the operator says, "yes I -want this to replace that". In highly distributed environments, a user -may end up with conflicting references and no proper way to choose. - -Because of this way to visualize a repository, git-branches are a core -part of git, which makes the user interface more complicated and -constrains moving through history. - -Finally, even if all older changesets still exist in the repository, -accesing them is still painful. - - ------------------------------------------------------ -The Obsolete Marker Concept ------------------------------------------------------ - - -As none of the concepts was powerful enough to fulfill the need of -safely rewriting history, including easy sharing and collaboration on -mutable history, we needed another one. - -Basic concept ------------------------------------------------------ - - -Every history rewriting operation stores the information that old rewritten -changeset is replaced by newer version in a given set of changesets. - -All basic history rewriting operation can create an appropriate obsolete marker. - - -.. figure:: ./figures/example-1-update.* - - *Updating* a changeset - - Create one obsolete marker: ``([A'] obsolete A)`` - - - -.. figure:: ./figures/example-2-split.* - - *Splitting* a changeset in multiple one - - Create one obsolete marker ``([B1, B2] obsolete B)]`` - - -.. figure:: ./figures/simple-3-merge.* - - *Merging* multiple changeset in a single one - - Create two obsolete markers ``([C] obsolete A), ([C] obsolete B)`` - -.. figure:: ./figures/simple-4-reorder.* - - *Moving* changeset around - - Reordering those two changesets need two obsolete markers: - ``([A'] obsolete A), ([B'] obsolete B)`` - - - -.. figure:: ./figures/simple-5-delete.* - - *Removing* a changeset: - - One obselete marker ``([] obsolete B)`` - - -To conclude, a single obsolete marker express a relation from **0..n** new -changesets to **1** old changeset. - -Basic Usage ------------------------------------------------------ - -Obsolete markers create a perpendicular history: **a versioned -changeset graph**. This means that offers the same features we have -for versioned files but applied to changeset: - -First: we can display a **coherent view** of the history graph in which only a -single version of your changesets is displayed by the UI. - -Second, because obsolete changeset content is still **available**. You can -you can - - * **browse** the content of your obsolete commits, - - * **compare** newer and older versions of a changeset, - - * **restore** content of previously obsolete changesets. - -Finally, the obsolete marker can be **exchanged between -repositories**. You are able to share the result on your history -rewriting operations with other prople and **collaborate on the -mutable part of the history**. - -Conflicting history rewriting operation can be detected and -**resolved** as easily as conflicting changes on a file. - - -Detecting and solving tricky situations ------------------------------------------------------ - -History rewriting can lead to complex situations. The obsolete marker -introduces a simple representation for this complex reality. But -people using complex workflows will one day or another have to face -the intrinsic complexity of some real-world situation. - -This section describes possible situations, defines precise sets of -changesets involved in such situations and explains how the error -cases can be resolved automatically using the available information. - - -Obsolete changesets -```````````````````` - -Old changesets left behind by obsolete operation are called **obsolete**. - -With the current version of mercurial, this *obsolete* part is stripped from the -repository before the end of every rewriting operation. - -.. figure:: ./figures/error-obsolete.* - - Rebasing `B` and `C` on `A` (as `B'`, `C'`) - - This rebase operation added two obsolete markers from new - changesets to old changesets. These two old changesets are now - part of the *obsolete* part of the history. - -In most cases, the obsolete set will be fully hidden to both the UI and -discovery, hence users do not have to care about them unless they want to -audit history rewriting operations. - -Unstable changesets -``````````````````` - -While exploring the possibilities of the obsolete marker a bit -further, you may end up with *obsolete* changesets which have -*non-obsolete* children. There is two common ways to achieve this: - -* Pull a changeset based of an old version of a changeset [#]_. - -* Use a partial rewriting operation. For example amend on a changeset with - children. - -*Non-obsolete* changeset based on *obsolete* one are called **unstable** - -.. figure:: ./figures/error-unstable.* - - Amend `A` into `A'` leaving `B` behind. - - In this situation we cannot consider `B` as *obsolete*. But we - have all the necessary data to detect `B` as an *unstable* branch - of the history because its parent `A` is *obsolete*. In addition, - we have enough data to automatically resolve this instability: we - know that the new version of `B` parent (`A`) is `A'`. We can - deduce that we should rebase `B` on `A'` to get a stable history - again. - -Proper warnings should be issued when part of the history becomes -unstable. The UI will be able to use the obsolete marker to -automatically suggest a resolution to the user of even carry them out -for them. - - -XXX details on automatic resolution for - -* movement - -* handling deletion - -* handling split on multiple head - - -.. [#] For this to happen one needs to explicitly enable exchange of draft - changesets. See phase help for details. - -The two parts of the obsolete set -`````````````````````````````````````` - -The previous section shows that there could be two kinds of *obsolete* -changesets: - -* an *obsolete* changeset with no or *obsolete* only descendants is called **extinct**. - -* an *obsolete* changeset with *unstable* descendants is called **suspended**. - - -.. figure:: ./figures/error-extinct.* - - Amend `A` and `C` leaving `B` behind. - - In this example we have two *obsolete* changesets: `C` with no *unstable* - children is *extinct*. `A` with *unstable* descendant (`B`) is *suspended*. - `B` is *unstable* as before. - - -Because nothing outside the obsolete set default on *extinct* -changesets, they can be safely hidden in the UI and even garbage -collected. *Suspended* changesets have to stay visible and available -until their unstable descendant are rewritten into stable version. - - -Conflicting rewrites -```````````````````` - -If people start to concurrently edit the same part of the history they will -likely meet conflicting situations when a changeset has been rewritten in two -different ways. - - -.. figure:: ./figures/error-conflicting.* - - Conflicting rewrite of `A` into `A'` and `A''` - -This kind of conflict is easy to detect with an obsolete marker -because an obsolete changeset can have more than one new version. It -may be seen as the multiple heads case. Mercurial warns you about this -on pull. It is resolved the same way by a merge of A' and A'' that -will keep the same parent than `A'` and `A''` with two obsolete -markers pointing to both `A` and `A'` - -.. figure:: ./figures/explain-troubles-concurrent-10-solution.* - -Allowing multiple new changesets to obsolete a single one allows to -distinguish a split changeset from a history rewriting conflict. - -Reliable history -`````````````````````` - -Obsolete markers help to smooth rewriting operation process. However -they do not change the fact that **you should only rewrite the mutable -part of the history**. The phase concept enforces this rule by -explicitly defining a public immutable set of changesets. Rewriting -operations refuse to work on public changesets, but there are still -some corner cases where previously rewritten changesets are made -public. - -Special rules apply for obsolete markers pointing to public changesets: - -* Public changesets are excluded from the obsolete set (public - changesets are never hidden or candidate to garbage collection) - -* *newer* version of a public changeset are called **bumped** and - highlighted as an error case. - -.. figure:: ./figures/explain-troubles-concurrent-10-sumup.* - -Solving such an error is easy. Because we know what changeset a -*bumped* tries to rewrite, we can easily compute a smaller -changeset containing only the change from the old *public* to the new -*bumped*. - -.. figure:: ./figures/explain-troubles-concurrent-15-solution.* - - -Conclusion ----------------- - -The obsolete marker is a powerful concept that allows mercurial to safely handle -history rewriting operations. It is a new type of relation between Mercurial -changesets which tracks the result of history rewriting operations. - -This concept is simple to define and provides a very solid base for: - - -- Very fast history rewriting operations, - -- auditable and reversible history rewriting process, - -- clean final history, - -- sharing and collaborating on the mutable part of the history, - -- gracefully handling history rewriting conflicts, - -- various history rewriting UI's collaborating with an underlying common API. - -.. list-table:: Comparison on solution [#]_ - :header-rows: 1 - - * - Solution - - Remove changeset locally - - Works on any point of your history - - Propagation - - Collaboration - - Speed - - Access to older version - - * - Strip - - `+` - - `+` - - \ - - \ - - \ - - `- -` - - * - Reference - - `+` - - \ - - `+` - - \ - - `+` - - `-` - - * - Obsolete - - `+` - - `+` - - `++` - - `++` - - `+` - - `+` - - - -.. [#] To preserve good tradition in comparison table, an overwhelming advantage - goes to the defended solution. diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/obs-implementation.rst --- a/docs/obs-implementation.rst Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -.. Copyright 2011 Pierre-Yves David -.. Logilab SA - ------------------------------------------------------ -Implementation of Obsolete Marker ------------------------------------------------------ -.. warning:: This document is still in heavy work in progress - -Main questions about Obsolete Marker Implementation ------------------------------------------------------ - - - - -How shall we exchange Marker over the Wire ? -````````````````````````````````````````````````````````` - -We can have a lot of markers. We do not want to exchange data for the one we -already know. Listkey() is not very appropriate there as you get everything. - -Moreover, we might want to only hear about Marker that impact changeset we are -pulling. - -pushkey is not batchable yet (could be fixed) - -A dedicated discovery and exchange protocol seems mandatory here. - - -Various technical details ------------------------------------------------------ - -Some stuff that worse to note. some may deserve their own section later. - -storing old changeset -`````````````````````` - -The new general delta format allows a very efficient storage of two very similar -changesets. Storing obsolete children using general delta takes no more place -than storing the obsolete diff. Reverted file will even we reused. The whole -operation will take much less space the strip backup. - - -Abstraction from history rewriting UI -``````````````````````````````````````````` - -How Mercurial handles obsolete marker is independent from what decides -to create them and what actual operation solves the error case. Any of -the existing history rewriting UI (rebase, mq, histedit) can lay -obsolete markers and resolve situation created by others. To go -further, a hook system of obsolete marker creation would allow each -mechanism to collaborate with other though a standard and central -mechanism. - - -Obsolete marker storage -``````````````````````````` - -The Obsolete marker will most likely be stored outside standard -history. They are multiple reasons for this: - -First, obsolete markers are really perpendicular to standard history -there is no strong reason to include it here other than convenience. - -Second, storing obsolete marker inside standard history means: - -* A changeset must be created every time an obsolete relation is added. Very - inconvenient for delete operation. - -* Obsolete marker must be forged at the creation of the new changeset. This - is very inconvenient for split operation. And in general it becomes - complicated to fix history afterward in particular when working with older - clients. - -Storing obsolete marker outside history have several pros: - -* It eases Exchange of obsolete markers without unnecessary obsolete - changeset contents. - -* It allows tuning the actual storage and protocol exchange while maintaining - compatibility with older clients through the wire (as we do the repository - format). - -* It eases the exchange of obsolete related information during - discovery to exchange obsolete changeset relevant to conflict - resolution. Exchanging such information deserves a dedicated - protocol. - -Persistent -``````````````````````` - -*Extinct* changeset and obsolete marker will most likely be garbage collected as -some point. However, archive server may decide to keep them forever in order to -keep a fully auditable history in its finest conception. - - -Current status ------------------------------------------------------ - -Obsolete marker are partialy in core. - -2.3: - -- storage over obsolete marker -- exchange suing pushkey -- extinct changeset are properly hidden -- extinct changeset are excluded from exchange diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/obs-terms.rst --- a/docs/obs-terms.rst Wed Apr 29 10:36:43 2015 -0700 +++ b/docs/obs-terms.rst Wed Apr 29 11:42:06 2015 -0700 @@ -1,12 +1,12 @@ .. Copyright 2011 Pierre-Yves David .. Logilab SA ------------------------------------------------------------ +----------------------------------- Terminology of the obsolete concept ------------------------------------------------------------ +----------------------------------- Obsolete markers ---------------------------------- +---------------- The mutable concept is based on **obsolete markers**. Creating an obsolete marker registers a relation between an old obsoleted changeset and its newer @@ -54,7 +54,7 @@ better distinction between *direct successors* and **any successors**. Possible changesets "type" ---------------------------------- +-------------------------- The following table describes names and behaviors of changesets affected by obsolete markers. The left column describes generic categories and the right @@ -182,7 +182,7 @@ Command and operation name ---------------------------------- +-------------------------- Existing terms @@ -196,7 +196,7 @@ Uncommit -````````````` +```````` Remove files from a commit (and leave them as dirty in the working directory) @@ -204,14 +204,14 @@ `rollback` usage. Fold -`````````` +```` Collapse multiple changesets into a unique one. The *evolve* extension will have a `fold` command. Prune -`````````` +````` Make a changeset obsolete without successors. @@ -223,7 +223,7 @@ - obsolete: too vague, too long and too generic. evolve -``````````````` +`````` Automatically resolve *troublesome* changesets (*unstable*, *bumped* and *divergent*) diff -r 8aa9a21156fe -r 1e3c607cf4a5 docs/qsync.rst --- a/docs/qsync.rst Wed Apr 29 10:36:43 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -.. Copyright 2011 Pierre-Yves David -.. Logilab SA - ---------------------------------------------------------------------- -Qsync: Mercurial to MQ exporter ---------------------------------------------------------------------- - - -People may have tools or co-workers that expect to receive mutable history using -a versioned MQ repository. - -For this purpose you can use the ``qsync`` extension. - - -To enable the evolve extension use:: - - $ hg clone http://hg-dev.octopoid.net/hgwebdir.cgi/mutable-history/ - $ mutable-history/iqsync-enable.sh >> ~/.hgrc - $ hg help qsync