docs/instability.rst
changeset 243 2f68c708e10b
parent 240 ab9ee2eba21e
child 357 b398e9c2dbd1
equal deleted inserted replaced
242:1fc4299ca8e2 243:2f68c708e10b
       
     1 
       
     2 -----------------------------------
       
     3 The instability Principle
       
     4 -----------------------------------
       
     5 
       
     6 
       
     7 
       
     8 An intrinsic contradiction
       
     9 -----------------------------------
       
    10 
       
    11 XXX starts by talking about getting ride of changeset.
       
    12 
       
    13 DVCS bring two new major concepts to the Version Control Scene:
       
    14 
       
    15     * History is organized as a robust DAG,
       
    16     * History can be rewritten.
       
    17 
       
    18 
       
    19 However, the two concepts are in contradiction:
       
    20 
       
    21 To achieve a robust history, three key elements are gathered in *changeset*:
       
    22 
       
    23     * Full snapshot of the versioned content,
       
    24     * Reference to the previous full snapshot used to build the new one,
       
    25     * A description of the change who lead from the old content to the new old.
       
    26 
       
    27 All three elements are to compute a *unique* hash that identify the changeset
       
    28 (with various other metadata). This identification is a key part of DVCS design.
       
    29 
       
    30 This is a very useful property because Changing B parent means changing B
       
    31 content too.  This require the creation of **another** changeset which is a good
       
    32 semantic.
       
    33 
       
    34 ::
       
    35 
       
    36   Schema base,  A, B and B'
       
    37 
       
    38 To avoid duplication, the older changeset is usually discarded from accessible
       
    39 history. I'm calling them *obsolete* changesets.
       
    40 
       
    41 
       
    42 But rewriting a changeset with children does not changes children parent! And
       
    43 because children of the rewritten changeset still **depends** on the older
       
    44 "dead" version of the changeset with can not get ride of this dead version.
       
    45 
       
    46 ::
       
    47 
       
    48   Schema base,  A and A' and B.
       
    49 
       
    50 I'm calling those children **unstable** because they are based one a dead
       
    51 changeset and prevent people to get ride of it.
       
    52 
       
    53 This instability is an **unavoidable consequence** of the strict dependency of
       
    54 changeset.  History Rewriting history alway  need to take it in account and
       
    55 provide a way to rewrite the descendant on the new changeset to avoid
       
    56 coexistence of the old and new version of a rewritten changeset..
       
    57 
       
    58 
       
    59 Everybody is working around the issue
       
    60 ------------------------------------------------
       
    61 
       
    62 I'm not claiming that rewriting history is impossible. People are successfully
       
    63 doing for years. However they all need to work around *instability*. Several
       
    64 work around strategy exists.
       
    65 
       
    66 
       
    67 Rewriting all at once
       
    68 ``````````````````````````
       
    69 
       
    70 The simplest way to avoid instability is to ensure rewriting operation always
       
    71 ends in a stable situation. This is achieve by rewriting all impacted changeset
       
    72 at the same time.
       
    73 
       
    74 Rewriting all descendants at the same time than the rewritted of a changeset.
       
    75 
       
    76 ::
       
    77 
       
    78   Schema!
       
    79 
       
    80 Several Mercurial commands apply it: rebase, collapse, histedit.  Mercurial also
       
    81 refuse to amend changeset with descendant.  The git branch design enforce such
       
    82 approach in git too.
       
    83 
       
    84 
       
    85 However, DVCS are **Distributed**. This means that you do not control what
       
    86 happen outside your repository. Once a changeset have been exchanged *outside*,
       
    87 there is no way to be sure it does not have descendants somewhere else.
       
    88 Therefore **if you rewrite changeset that exists elsewhere, you can't eradicate
       
    89 the risk of instability.**
       
    90 
       
    91 Do not rewrite exchanged changeset
       
    92 ```````````````````````````````````
       
    93 
       
    94 To work around the issue above, mercurial introduced phases that prevent you to
       
    95 rewrite shared changeset and ensure other can't pull certain changeset from you.
       
    96 But this is a very frustrating limitation that prevent you to efficiently share,
       
    97 review and collaborate on mutable changeset.
       
    98 
       
    99 Git world use another approach to prevent instability.  By convention only a
       
   100 single developper works on a changeset contained in a named branch. But once
       
   101 again this is a huge blocker for collaborating. Moreover clueless people
       
   102 **will** mess up social convention soon or later.
       
   103 
       
   104 
       
   105 Loose the DAG robustness
       
   106 ````````````````````````````
       
   107 
       
   108 The other approach use in Mercurial is to keep the mutable part of the history
       
   109 outside the DVCS constraint. This is the MQ approach of sticking a quilt queue
       
   110 over Mercurial.
       
   111 
       
   112 This allow much more flexible workflow but two major feature are lost in the
       
   113 process:
       
   114 
       
   115 :Graceful merge: MQ use plain-patch to store changeset content and patch have
       
   116                  trouble to apply in changing context. Applying your queue
       
   117                  becomes very painful when context changes.
       
   118 
       
   119 :easy branching: A quilt queue is by definition a linear queue. Increasing risk
       
   120                  of conflict
       
   121 
       
   122 It is possible to collaborate over versioned mq! But you are going ahead a lot
       
   123 of troubles.
       
   124 
       
   125 .. Ignore conflicts
       
   126 .. ```````````````````````````````````
       
   127 .. 
       
   128 .. Another ignored issue is conflicting rewritting of the same changeset. If a
       
   129 .. changeset is rewritten two times we have two newer version, duplicated history
       
   130 .. complicate to merge.
       
   131 .. 
       
   132 .. Mercurial work around by
       
   133 .. 
       
   134 .. The "One set of mutable changset == One developper" mantra is also a way to work
       
   135 .. around conflicting rewritting of changeset. If two different people are able to
       
   136 .. 
       
   137 .. The git branch model allow to overwrite changeset version by another one. But it
       
   138 .. does not care about divergent version. It is the equilent of "common ftp" source
       
   139 .. management for changeset.
       
   140 
       
   141 Facing The Danger Once And For All
       
   142 ------------------------------------------------
       
   143 
       
   144 Above we saw that, the more effort you put to avoid instability, the more option
       
   145 you deny. And even most restrictive work flow can't guarantee that instability
       
   146 will never show up!
       
   147 
       
   148 Obsolete marker can handle the job
       
   149 ```````````````````````````````````
       
   150 
       
   151 It is time to provide a full featured solution to deal with instability and to
       
   152 stop working around the issue! This is why I developing a new feature for
       
   153 mercurial called "Obsolete markers". Obsolete markers have two key properties:
       
   154 
       
   155 
       
   156 * Any "old" changeset we want to get ride of is **explicitly** marked as "obsolete"
       
   157   by history rewriting operation.
       
   158 
       
   159   By explicitly marking the obsolete part of the history, we will be able to
       
   160   easily detect instability situation.
       
   161 
       
   162 * Relations between old and new version of changesets are tracked by obsolete
       
   163   markers.
       
   164 
       
   165   By Storing a meta-history of changeset evolution we are able to easily resolve
       
   166   instability and edition conflict [#]_ .
       
   167 
       
   168 .. [#] edition conflict is another major obstable to collaboration. See the
       
   169        section dedicated to obsolete marker for details.
       
   170 
       
   171 Improves robustness == improves simplicity
       
   172 ````````````````````````````````````````````````
       
   173 
       
   174 This proposal should **first** be seen as a safety measure.
       
   175 
       
   176 It allow to detect instability as soon as possible
       
   177 
       
   178 ::
       
   179 
       
   180     $ hg pull
       
   181     added 3 changeset
       
   182     +2 unstable changeset
       
   183     (do you want "hg stabilize" ?)
       
   184     working directory parent is obsolete!
       
   185     $ hg push
       
   186     outgoing unstable changesets
       
   187     (use "hg stabilize" or force the push)
       
   188 
       
   189 And should not not encourage people to create unstability
       
   190 
       
   191 ::
       
   192 
       
   193     $ hg up 42
       
   194     $ hg commit --amend
       
   195     changeset have descendant.
       
   196     $ hg commit --amend -f
       
   197     +5 unstable changeset
       
   198 
       
   199     $ hg rebase -D --rev 40::44
       
   200     rebasing already obsolete changeset 42:AAA will conflict with newer version 48:BBB
       
   201 
       
   202 While allowing powerful feature
       
   203 ````````````````````````````````````````````````
       
   204 
       
   205 
       
   206 * Help to automatically solve instability.
       
   207 
       
   208 * "kill" changeset remotely.
       
   209 
       
   210 * track resulting changeset when submitting patch//pull request.
       
   211 
       
   212 * Focus on what you do:
       
   213 
       
   214   I do not like the "all at once" model of history rewriting. I'm comfortable
       
   215   with unstability and obsolete marker offer all the tool to safely create and
       
   216   handle unstability locally.
       
   217 
       
   218