# HG changeset patch # User Greg Ward # Date 1429837713 14400 # Node ID cbc370d6ec3044db6e5babf41e6cd35f7bb6d2a3 # Parent e33990a4c27af9955d10981ce4daacd61c9aa2d8 docs: remove obsolete documentation evolve-collaboration.rst replaced by sharing.rst instability.rst introduction to the concept for Mercurial developers -- no longer needed since most are now convinced obs-concept.rst largely replaced by the user guide obs-implementation.rst more for Mercurial developers; the source code is probably more accurate and up-to-date qsync.rst the extension this referred to no longer exists This fixes several more sphinx warnings. I've left some other old docs around, because they still have useful content that needs to be adapted and updated. diff -r e33990a4c27a -r cbc370d6ec30 docs/evolve-collaboration.rst --- a/docs/evolve-collaboration.rst Thu Apr 23 08:35:38 2015 -0400 +++ /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 e33990a4c27a -r cbc370d6ec30 docs/figures/edit-is-rewrite-step2.svg --- a/docs/figures/edit-is-rewrite-step2.svg Thu Apr 23 08:35:38 2015 -0400 +++ /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 e33990a4c27a -r cbc370d6ec30 docs/figures/error-conflicting.svg --- a/docs/figures/error-conflicting.svg Thu Apr 23 08:35:38 2015 -0400 +++ /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 e33990a4c27a -r cbc370d6ec30 docs/figures/error-extinct.svg --- a/docs/figures/error-extinct.svg Thu Apr 23 08:35:38 2015 -0400 +++ /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 e33990a4c27a -r cbc370d6ec30 docs/figures/error-obsolete.svg --- a/docs/figures/error-obsolete.svg Thu Apr 23 08:35:38 2015 -0400 +++ /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 e33990a4c27a -r cbc370d6ec30 docs/figures/error-unstable.svg --- a/docs/figures/error-unstable.svg Thu Apr 23 08:35:38 2015 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - -2012-03-18 23:47ZCanvas 1Layer 1ABAA'ObsoleteUnstableB diff -r e33990a4c27a -r cbc370d6ec30 docs/figures/example-1-update.svg --- a/docs/figures/example-1-update.svg Thu Apr 23 08:35:38 2015 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - -2012-03-21 08:32ZCanvas 1Layer 1AA’A diff -r e33990a4c27a -r cbc370d6ec30 docs/figures/example-2-split.svg --- a/docs/figures/example-2-split.svg Thu Apr 23 08:35:38 2015 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - -2012-03-21 08:32ZCanvas 1Layer 1AA1A2A diff -r e33990a4c27a -r cbc370d6ec30 docs/figures/explain-troubles-concurrent-10-solution.svg --- a/docs/figures/explain-troubles-concurrent-10-solution.svg Thu Apr 23 08:35:38 2015 -0400 +++ /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 e33990a4c27a -r cbc370d6ec30 docs/figures/explain-troubles-concurrent-10-sumup.svg --- a/docs/figures/explain-troubles-concurrent-10-sumup.svg Thu Apr 23 08:35:38 2015 -0400 +++ /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 e33990a4c27a -r cbc370d6ec30 docs/figures/git.svg --- a/docs/figures/git.svg Thu Apr 23 08:35:38 2015 -0400 +++ /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 e33990a4c27a -r cbc370d6ec30 docs/figures/simple-3-merge.svg --- a/docs/figures/simple-3-merge.svg Thu Apr 23 08:35:38 2015 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - -2012-03-21 08:32ZCanvas 1Layer 1AABBC diff -r e33990a4c27a -r cbc370d6ec30 docs/figures/simple-4-reorder.svg --- a/docs/figures/simple-4-reorder.svg Thu Apr 23 08:35:38 2015 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - -2012-03-21 08:32ZCanvas 1Layer 1AABBA'B' diff -r e33990a4c27a -r cbc370d6ec30 docs/figures/simple-5-delete.svg --- a/docs/figures/simple-5-delete.svg Thu Apr 23 08:35:38 2015 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - -2012-03-21 08:32ZCanvas 1Layer 1AA diff -r e33990a4c27a -r cbc370d6ec30 docs/instability.rst --- a/docs/instability.rst Thu Apr 23 08:35:38 2015 -0400 +++ /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 e33990a4c27a -r cbc370d6ec30 docs/obs-concept.rst --- a/docs/obs-concept.rst Thu Apr 23 08:35:38 2015 -0400 +++ /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 e33990a4c27a -r cbc370d6ec30 docs/obs-implementation.rst --- a/docs/obs-implementation.rst Thu Apr 23 08:35:38 2015 -0400 +++ /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 e33990a4c27a -r cbc370d6ec30 docs/qsync.rst --- a/docs/qsync.rst Thu Apr 23 08:35:38 2015 -0400 +++ /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