Mercurial > hg > evolve
changeset 227:abe52cf492ee
doc: several update and review.
author | Pierre-Yves.David@ens-lyon.org |
---|---|
date | Wed, 09 May 2012 13:08:46 +0200 |
parents | 0892b91947ef |
children | 5a17c0d41a00 |
files | docs/evolve-faq.rst docs/from-mq.rst docs/index.rst docs/obs-concept.rst docs/obs-implementation.rst docs/unstability.rst |
diffstat | 6 files changed, 259 insertions(+), 127 deletions(-) [+] |
line wrap: on
line diff
--- a/docs/evolve-faq.rst +++ b/docs/evolve-faq.rst @@ -3,8 +3,6 @@ Evolve How To --------------------------------------------------------------------- - - Add a changeset: ``commit`` ------------------------------------------------------------ @@ -13,10 +11,9 @@ Rewrite a changeset: ``amend`` ------------------------------------------------------------ -A new command ``hg amend`` is added by the extension. 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` changesets. +A dedicated command ``hg amend`` is added by the extension. 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` changesets. To understand what the result of amend will be I use the two following aliases [#]_:: @@ -33,13 +30,15 @@ This command can even be invoked on changesets with children (provided none is public) ! -.. note:: the amend command is very similar to mq's ``qrefresh``, a ``refresh`` +.. note:: The amend command is very similar to mq's ``qrefresh``, a ``refresh`` alias for amend is also available. But note that contrary to ``qrefresh``, ``amend`` does not exclude changes on file not specified on the command line. XXX add idank example +.. warning:: The `hg commit --amend` switch does **not** lay obsolete marker + down yet. You should always prefer the dedicated command. .. [#] (added by enable.sh) @@ -52,13 +51,13 @@ branches onto the current branch". The graft command has been altered to allow the creation of an -obsolete marker indicating both the result cset and its source +obsolete marker between both the result cset and its source (actually recording changeset movements). This is achieved using a new flag `-O` (or `old-obsolete`) [#]_. -XXX example +XXX Need a few examples here. .. warning:: when using graft --continue after conflict resolution you **MUST** pass `-O` or `-o` flag again because they are not saved for now @@ -68,13 +67,17 @@ abusive. But this was very convenient for experimental purposes. This will likely change in non experimental release. + Delete a changeset: ``kill`` ------------------------------------------------------------ -A new ``kill`` command allows removing a changeset. +A new ``kill``[#]_ command allows removing a changeset. Just use ``hg kill <some-rev>``. +.. [#] `kill` is a terrible name. **NEVER** forget to add `hg` in front of it + until we find a better name. + Moving within the history: ``up`` ``gdown`` and ``gup`` ------------------------------------------------------------ @@ -91,12 +94,16 @@ Collapse changesets: ``amend`` ------------------------------------------------------------ -you can use amend -c to collapse multiple changeset in a single one. +You can use amend -c to collapse multiple changeset in a single one. + + +.. note:: This is a terrible UI. `hg collapse` should be ported to obsolete + marker for this purpose. Split a changeset ----------------------- -There is no official command to split a changeset. However is it easily achieved +There is no official command to split a changeset [#]_ . However is it easily achieved by manual operation:: ### you want to split changeset A: 42 @@ -112,6 +119,8 @@ # current changeset (.) and previous one (.^) replace A (42) $ hg kill --new . --new .^ 42 +.. [#] Yet + Update my current work in progess after a pull ---------------------------------------------- @@ -119,10 +128,14 @@ Whenever you are working on some changesets, it is more likely that a pull will, eventually, import new changesets in your tree. -And it is likely that you will want your work in progress changsets to be +And it is likely that you will want your work in progress changesets to be rebased on the top of this newly imported subtree. -Doing so is only a matter of rebasing. +Doing so is only a matter of rebasing. Rebase have been wrapped to lay obsolete +marker down. + + +XXX Add an example here. @@ -131,7 +144,7 @@ You can still use rebase to move a whole segment of the changeset graph together. -.. warning:: Beware that rebasing obsolete changesets will result in +.. warning:: Beware that rebasing changesets already obsolete by others will result in conflicting versions of the changesets. Stabilize history: ``stabilize`` @@ -146,15 +159,17 @@ newest version. This is not done automatically to avoid the proliferation of useless hidden changesets. -.. warning:: ``hg stabilize`` have no --continue to use after conflict +.. warning:: + + * ``hg stabilize`` have no --continue to use after conflict resolution -.. warning:: stabilization does not handle deletion yet. + * stabilization does not handle deletion yet. -.. warning:: obsolete currently relies on changesets in secret phase - to avoid exchanging obsolete and unstable changesets. + * stabilization does not handle rewriting conflict yet. - XXX details issue here + * obsolete currently relies on changesets in secret phase + to avoid exchanging extinct() changesets. Fix my history afterward: ``kill -n`` @@ -163,18 +178,17 @@ Sometimes you need to create an obsolete marker by hand. This may happen when upstream has applied some of your patches for example. -you can use ``hg kill --new <new-changeset> <old-changeset>`` to add obsolete +You can use ``hg kill --new <new-changeset> <old-changeset>`` to add obsolete marker. -Export to mq: ``synchronize`` +Export to mq: ``qsync`` ------------------------------------------------------------ -Another extension allows to export. +Another extension allows to export mutable changeset to mq. See the +`enable-qsync.sh` to enable it and read module documentation for details. -View change to your file ------------------------------------------------------------- +If you do not work at Logilab. You probably do not need it. -Another extension allows to export. View diff from the last amend ------------------------------------------------------------ @@ -185,6 +199,9 @@ [alias] odiff = diff --rev 'limit(obsparents(.),1)' --rev . +The qt viewer `hgview` displays obsolete data and allows to see diff again +obsolete parent. + View obsolete markers ------------------------------------------------------------ @@ -195,22 +212,9 @@ -Important Note -===================================================================== - -View change to your file ------------------------------------------------------------- - -Extinct changesets are hidden using the *hidden* feature of mercurial. - -Only ``hg log`` and ``hgview`` support it. ``hg glog`` or other visual viewer don't. - - - -
--- a/docs/from-mq.rst +++ b/docs/from-mq.rst @@ -5,21 +5,23 @@ Cheat sheet ------------- -============================== ============================================ -mq command new equivalent -============================== ============================================ +:: + + ============================== ============================================ + mq command new equivalent + ============================== ============================================ -qseries ``log`` -qnew ``commit`` -qrefresh ``amend`` -qpop ``update`` or ``qdown`` -qpush ``update`` or ``gup`` sometimes ``stabilize`` -qrm ``kill`` -qfold ``amend -c`` (for now, ``collapse`` soon) -qdiff ``odiff`` + qseries ``log`` + qnew ``commit`` + qrefresh ``amend`` + qpop ``update`` or ``qdown`` + qpush ``update`` or ``gup`` sometimes ``stabilize`` + qrm ``kill`` + qfold ``amend -c`` (for now, ``collapse`` soon) + qdiff ``odiff`` -qfinish -- -qimport -- + qfinish -- + qimport -- Replacement details @@ -32,9 +34,7 @@ You can use the standard log to display them. You can use the phase revset to display unfinished business only and templates to have the same kind of compact -output qseries has. - -This will result in something like that:: +output qseries has.:: [alias] wip = log -r 'not public()' --template='{rev}:{node|short} {desc|firstline}\n' @@ -42,7 +42,7 @@ hg qnew ```````` -With evolve you handle standard changesets without an additional overlay. +With evolve you handle standard changesets without additional overlay. Standard changeset are created using hg commit as usual.:: @@ -63,8 +63,8 @@ hg qref ```````` -A new command from evolution will allow you to rewrite the changeset you are -currently on. just call: +A dedicated command from evolve will allow you to rewrite the changeset you are +currently on.:: $ hg amend @@ -80,16 +80,19 @@ $ hg record babar.py $ hg amend -c .^ # .^ refer to "working directoy parent, here 'feature A' +.. warning:: `hg commit --amend` from Mercurial 2.2 does not lay obsolet marker yet and should + **not** be used. + note: refresh is an alias for amend hg qpop ````````` -the following command emule the behavior of hg qpop: +the following command emulate the behavior of hg qpop: $ hg gdown -If you need to go back to an arbitrary commit you can just us: +If you need to go back to an arbitrary commit you can just use: $ hg update @@ -100,10 +103,10 @@ ```````` When you rewrite changesets, descendants of rewritten changesets are marked as -"out of sync". You need to rewrite them on top of the new version of their +"unstable". You need to rewrite them on top of the new version of their ancestor. -The evolution extension adds a command to rewrite the "out of sync" changesets::: +The evolution extension adds a command to rewrite "unstable" changesets:: $ hg stabilize @@ -122,7 +125,7 @@ hg qrm ``````` -evolution introduce a new command to mark a changeset as "not wanted anymore".:: +evolution introduce a new command to mark a changeset as "obsolete".:: $ hg kill <revset> @@ -132,8 +135,8 @@ :: - $ hg up <top changeset> - $ amend --edit -c <bottom changeset> + $ hg up <top-most-changeset> + $ amend --edit -c <bottom-most-changeset> or later:: @@ -152,7 +155,7 @@ hg qfinish and hg qimport ```````````````````````````` -Is not necessary anymore. If you want to control exchange and mutability of +Are not necessary anymore. If you want to control exchange and mutability of changesets, see the phase feature
--- a/docs/index.rst +++ b/docs/index.rst @@ -6,7 +6,14 @@ Here are various Materials on planned improvement to mercurial regarding rewriting history. -The effort splits in two parts: +First read about what challenge arise while rewriting history and how we plan to solve them once and for all. + +.. toctree:: + :maxdepth: 2 + + unstability + +The effort is splits in two parts: * The **obsolete marker** concept aims to provide and alternative to ``strip`` to get ride of changesets. @@ -27,22 +34,26 @@ markers. It is inspired from MQ and pbranch but have multiple advantage over them: -* sticks to "Work where you are" philosophy (I'll need better wording - for that) +* Focus on your current work. + + You can focus your work on a single changeset and take care of adapting + descendent changeset later. * Handle **non-linear history with branches and merges** -* Use **robust merge** mechanism of mercurial. +* Rely internally on **robust merge** mechanism of mercurial. - simple conflict are handled by real merge tools using appropriate ancestor. + Simple conflict are handled by real merge tools using appropriate ancestor. Conflict are much rarer and much more user friendly. -* Mutable history **fully available all the time**. +* Mutable history are **fully available all the time**. You are do not need to unapply and apply patche to access various part of you history. -* Use **plain changeset** only. Evole create and exchange real changeset only. +* Use **plain changeset** only. + + Evolve create and exchange real changeset only, not patches. Mutable history can be used in all usual operation 'pull, push, log, diff …) * Allow **sharing and collaboration** mutable history without fear of duplicate. @@ -55,6 +66,8 @@ implication of the **obsolete marker** concept. I do not recommend non power user to test this at this stage. + XXX make sure to read the XXX section before using it. + Production ready version should hide such details to normal user. To enable the evolve extension use:: @@ -62,17 +75,18 @@ $ hg clone http://hg-dev.octopoid.net/hgwebdir.cgi/mutable-history/ $ mutable-history/enable.sh >> ~/.hgrc -You will probably want to use the associated version of hgview (QT viewer -only). :: +You will probably want to use the associated version of hgview (qt viewer +recommended). :: $ hg clone http://hg-dev.octopoid.net/hgwebdir.cgi/hgview/ $ cd hgview $ python setup.py install --user +works with mercurial 2.1 and 2.2 (recommended) --- -For more information see documents below +For more information see documents below: .. toctree:: :maxdepth: 2 @@ -119,31 +133,45 @@ -Know canveas +Known limitation and bug ================================= Here is a list of know issue that will be fixed later: -* Unstable changeset turns secret. + + +* ``hg stabilize`` does not handle merge conflict. -* ``hg stabilize`` does not handle conflict. + You must fallback to graft or rebase when that happen. -* Mercurial think you are pushing additional heads even when the new head - obsolete another one. You have to use hg push -f more than necessary. +* rewritinf conflict are not detected yet``hg stabilize`` does not handle them. * ``hg update`` can move an obsolete parent -* you need to provideto graft --continue -O if you started you graft using -O. - -* hg graphlog show extinct changeset - -* hg heads show extinct changeset +* you need to provide to `graft --continue -O` if you started you graft using `-O`. * hg merge considered extinct head as valid target. requiring you to manually specify target all the time. * obsolete relation exchange crash (as in traceback) on static http repo. +* Extinct changeset are turned secret by various commands. + +* Extinct changesets are hidden using the *hidden* feature of mercurial only + supported by a few commands. + + Only ``hg log``, ``hgview`` and `hg glog` (2.2 only) support it. ``hg head`` or other visual viewer don't. + +* hg heads show extinct changeset + +Fixed in 2.2 +--------------------------------- + +* hg graphlog show extinct changeset + +* Mercurial 2.1 think you are pushing additional heads even when the new head + obsolete another one. You have to use hg push -f more than necessary. +
--- a/docs/obs-concept.rst +++ b/docs/obs-concept.rst @@ -76,6 +76,8 @@ replace that. In highly distributed environments, a user may end up with conflicting references and no proper way to choose. +XXX for the above paragraph link to "unstable issue" + 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. @@ -91,7 +93,7 @@ As None of the concepts was powerful enough to fulfill the need of safely rewriting history, including easy sharing and collaborating on mutable history, -we needed another one. +we needed another one. Basic concept -----------------------------------------------------
--- a/docs/obs-implementation.rst +++ b/docs/obs-implementation.rst @@ -21,13 +21,27 @@ Abstraction from history rewriting UI ``````````````````````````````````````````` -How Mercurial handle obsolete marker is independent from who decide to create -them and what actual operation solve error case. Any of the existing history +How Mercurial handle obsolete marker is independent from what create +them and what actual operation solves error case. Any of the existing history rewriting UI (rebase, mq, histedit) can lay obsolete marker and resolve situation created by other. 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 content +``````````````````````````` + +In the current implementation obsolete marker contains:: + + 'id': "unique id of the obsolete marker" + 'subjects': "0-N newer version of changeset in "object" (as ordered list) + 'object': "old and obsolete version" + 'date': "When was this marker created ?" + 'user': "Who did that ?" + 'reason': "Why was it done" + +Grouping them for operation that create multiple markers are once may be a good +idea. (would help, exchange and cancelation) Obsolete marker storage ``````````````````````````` @@ -76,18 +90,18 @@ An experimental implementatione exists. What have been done so far. -* 1-1 obsolete marker stored outside history, +* rich markers stored outside history, +* obsolete markers exchange through pushkey, -* compute obsolete-tip - -* obsolete marker exchange through pushkey, +* compute obsolete-tip (newest version of a changeset) * compute obsolete, unstable, extinct and suspended set. * hidden extinct changesets for UI. -* Use secret phase to remove from discovery obsolete and unstable changeset (to - be improved soon) +* Require `--force` to push unstable history. + +* Use secret phase to remove extinct changesets from discovery. * alter rebase to use obsolete marker instead of stripping. (XXX break --keep for now)
--- a/docs/unstability.rst +++ b/docs/unstability.rst @@ -1,3 +1,4 @@ + ----------------------------------- The Unstability Principle ----------------------------------- @@ -7,6 +8,7 @@ An intrinsic contradiction ----------------------------------- +XXX starts by talking about getting ride of changeset. DVCS bring two new major concepts to the Version Control Scene: @@ -25,6 +27,8 @@ All three elements are used generate a *unique* hash that identify the changeset (with various other metadata). This identification is a key part of DVCS design. +XXX missing lines ? + :: Schema base, A, B and B' @@ -56,73 +60,150 @@ Everybody is working around the issue ------------------------------------------------ -I'm not claiming that rewriting history is impossible. People are +I'm not claiming that rewriting history is impossible. People are successfully +doing for years. However they all need to work around this unstability: Rewriting all at once `````````````````````````` +The simplest way to avoid unstability is to ensure rewritting operation always +ends in a stable situation. This is achieve by rewriting all impacted changeset +at the same time. + +rewritting all descendants at the same time that the rewritting of a changeset. + +:: + + Schema! + +Several Mercurial command follow this idea: rebase, collapse, histedit. +Mercurial also refuse to amend changeset with descendant. The git brnach design enforce such approach in git too. -stable situation to stable situation +However, DVCS are **Distributed**. This means that you do not control what +happen outside your repository. Once a changeset have been exchanged *outside*, +you can't be sure of it's descendant. Therefore** if you rewritte changeset that +exists elsewere, you can't erradicate the risk of unstability.** -Distributed means that you do not control what happen outside your repository: - +Do not rewrite exchanged changeset +``````````````````````````````````` -* phase. -* overwrite. +To work around this issue mercurial introduced phases that prevent you to +rewrite exchanged changeset and ensure other can't pull certain changeset from +you. But this is a very frustrating limitation that prevent you to +efficiently share, review and collaborate on mutable changeset. - -Boiler Plate +Git world use another approach to prevent unstability. +By convention only a single developper works on a changeset contained in a named +branch. But once again this is a huge blocker for collaborating and clueless people +**will** mess up social convention soon or later. Loose the DAG robustness ```````````````````````````` -The other approach is +The other approach use 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. -mq -- quilt +This allow much more flexible workflow two major feature are lost in the +process: -Conflict too much conflict + * Graceful merge. MQ use plain-patch to store changeset content and patch have + trouble to apply in changing context. applying you queu can because very + painful if context changeset. -Linear + * easy branching. A quilt queue is by definition a linear queue. +It is possible to collaborate over versionned mq! But you are going ahead a lot +of trouble. -Deny a lot of option -```````````````````````````` - - - -[] rewrite - -[] exchange - -[] collaborate - +.. Ignore conflicts +.. ``````````````````````````````````` +.. +.. Another ignored issue is conflicting rewritting of the same changeset. If a +.. changeset is rewritten two times we have two newer version, duplicated history +.. complicate to merge. +.. +.. Mercurial work around by +.. +.. The "One set of mutable changset == One developper" mantra is also a way to work +.. around conflicting rewritting of changeset. If two different people are able to +.. +.. The git branch model allow to overwrite changeset version by another one. But it +.. does not care about divergent version. It is the equilent of "common ftp" source +.. management for changeset. Facing The Danger Once And For All ------------------------------------------------ The more effort you put to avoid instability, the more option you deny. And even most restrictive work flow can't garantee 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 developing a new feature for -mercurial called "Obsolete marker". +mercurial called "Obsolete marker". Obsolete marker have two key property: * Any changeset is we want to get ride of is **explicitly** marked as "obsolete" - by history rewritting operation.. + by history rewritting operation. + + By explicitly marking the obsolete part of the history, we will be able to + easily detect appearance of unstability. * Relations between old and new version of changesets are tracked by Obsolete markers. -By explicitly marking the obsolete part of the history, we will be able to -easily detect appearance of unstability. By Storing a meta-history of changeset -evolution we are able to easily resolve instability and edition conflict. + By Storing a meta-history of changeset evolution we are able to easily resolve + instability and edition conflict [#]_ . + +.. [#] edition conflict is another major obstable to collaboration. See the + section dedicated to obsolete marker for details. + +Improving robusness improves simplicity +```````````````````````````````````````````````` + +This proposal should **first** be seen as a safety measure. + +It allow to detect unstability as soon as possible + +:: + $ hg pull + added 3 changeset + +2 unstable changeset + (do you want "hg stabilize" ?) + working directory parent is obsolete! + $ hg push + outgoing unstable changesets + (use "hg stabilize" or force the push) + +And should not not encourage people to create unstability + +:: + $ 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 +```````````````````````````````````````````````` + +* "kill" 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 confortable + with unstability and obsolete marker offer all the tool to safely create and + handle unstability locally. - - -No instability is still a bad situation. -No instability is still a bad situation that should be avoided.