docs/instability.rst
branchstable
changeset 662 40854e956315
parent 655 dd5765ae91c3
equal deleted inserted replaced
648:f727ebe6ffd5 662:40854e956315
    10 An intrinsic contradiction
    10 An intrinsic contradiction
    11 -----------------------------------
    11 -----------------------------------
    12 
    12 
    13 XXX starts by talking about getting ride of changeset.
    13 XXX starts by talking about getting ride of changeset.
    14 
    14 
    15 DVCSes bring two new major concepts to the Version Control Scene:
    15 DVCSes bring two new major concepts to the version control scene:
    16 
    16 
    17     * History is organized as a robust DAG,
    17     * History is organized as a robust DAG,
    18     * History can be rewritten.
    18     * History can be rewritten.
    19 
    19 
    20 However, the two concepts are in contradiction:
    20 However, the two concepts are in contradiction:
    21 
    21 
    22 To achieve a robust history, three key elements are gathered in *changesets*:
    22 To achieve a robust history, three key elements are gathered in *changesets*:
    23 
    23 
    24     * Full snapshot of the versioned content,
    24     * Full snapshot of the versioned content,
    25     * Reference to the previous full snapshot used to build the new one,
    25     * Reference to the previous full snapshot used to build the new one,
    26     * A description of the change who lead from the old content to the new old.
    26     * A description of the change which leads from the old content to the new content.
    27 
    27 
    28 All three elements are to compute a *unique* hash that identify the changeset
    28 All three elements are used to compute a *unique* hash that identifies the changeset
    29 (with various other metadata). This identification is a key part of DVCS design.
    29 (with various other metadata). This identification is a key part of DVCS design.
    30 
    30 
    31 This is a very useful property because Changing B parent means
    31 This is a very useful property because changing B's parent means
    32 changing B content too. This requires the creation of **another**
    32 changing B's content too. This requires the creation of **another**
    33 changeset, which is semantically good.
    33 changeset, which is semantically good.
    34 
    34 
    35 .. figure:: ./figures/edit-is-rewrite-step2.svg
    35 .. figure:: ./figures/edit-is-rewrite-step2.svg
    36 
    36 
    37 
    37 
    38 To avoid duplication, the older changeset is usually discarded from accessible
    38 To avoid duplication, the older changeset is usually discarded from accessible
    39 history. I'm calling them *obsolete* changesets.
    39 history. I'm calling them *obsolete* changesets.
    40 
    40 
    41 
    41 
    42 But rewriting a changeset with children does not change these
    42 But rewriting a changeset with children does not change the
    43 children's parent! And because children of the rewritten changeset
    43 children's parents! And because children of the rewritten changeset
    44 still **depend** on the older "dead" version of the changeset with
    44 still **depend** on the older "dead" version of the changeset, we
    45 can not get rid of this dead version.
    45 cannot get rid of this dead version.
    46 
    46 
    47 ::
    47 ::
    48 
    48 
    49   Schema base,  A and A' and B.
    49   Schema base,  A and A' and B.
    50 
    50 
    51 I'm calling these children **unstable** because they are based on a
    51 I'm calling these children **unstable** because they are based on a
    52 dead changeset and prevent people to get rid of it.
    52 dead changeset and prevent people from getting rid of it.
    53 
    53 
    54 This instability is an **unavoidable consequence** of the strict dependency of
    54 This instability is an **unavoidable consequence** of the strict dependency of
    55 changeset.  History Rewriting history alway  need to take it in account and
    55 changesets.  Rewriting history always needs to take it into account and
    56 provide a way to rewrite the descendant on the new changeset to avoid
    56 provide a way to rewrite the descendants of the new changeset to avoid
    57 coexistence of the old and new version of a rewritten changeset.
    57 coexistence of the old and new versions of a rewritten changeset.
    58 
    58 
    59 
    59 
    60 Everybody is working around the issue
    60 Everybody is working around the issue
    61 ------------------------------------------------
    61 ------------------------------------------------
    62 
    62 
    63 I'm not claiming that rewriting history is impossible. People are successfully
    63 I'm not claiming that rewriting history is impossible. People have been successfully
    64 doing for years. However they all need to work around *instability*. Several
    64 doing it for years. However they all need to work around *instability*. Several
    65 work around strategy exists.
    65 workaround strategies exist.
    66 
    66 
    67 
    67 
    68 Rewriting all at once
    68 Rewriting all at once
    69 ``````````````````````````
    69 ``````````````````````````
    70 
    70 
    77 ::
    77 ::
    78 
    78 
    79   Schema!
    79   Schema!
    80 
    80 
    81 Several Mercurial commands apply it: rebase, collapse, histedit.
    81 Several Mercurial commands apply it: rebase, collapse, histedit.
    82 Mercurial also refuses to amend changeset with descendant. The git
    82 Mercurial also refuses to amend changesets with descendants. The git
    83 branch design enforces such approach in git too.
    83 branch design enforces this approach in git too.
    84 
    84 
    85 
    85 
    86 However, DVCS are **Distributed**. This means that you do not control what
    86 However, DVCS are **distributed**. This means that you do not control what
    87 happen outside your repository. Once a changeset have been exchanged *outside*,
    87 happens outside your repository. Once a changeset has been exchanged *outside*,
    88 there is no way to be sure it does not have descendants somewhere else.
    88 there is no way to be sure it does not have descendants somewhere else.
    89 Therefore **if you rewrite changeset that exists elsewhere, you can't eradicate
    89 Therefore **if you rewrite changeset that exists elsewhere, you can't eradicate
    90 the risk of instability.**
    90 the risk of instability.**
    91 
    91 
    92 Do not rewrite exchanged changeset
    92 Do not rewrite exchanged changesets
    93 ```````````````````````````````````
    93 ```````````````````````````````````
    94 
    94 
    95 To work around the issue above, Mercurial introduced phases, which
    95 To work around the issue above, Mercurial introduced phases, which
    96 prevent you from rewriting shared changesets and ensure others can't
    96 prevent you from rewriting shared changesets and ensure others can't
    97 pull certain changesets from you. But this is a very frustrating
    97 pull certain changesets from you. But this is a very frustrating
    98 limitation that prevents you to efficiently sharing, reviewing and
    98 limitation that prevents you to efficiently sharing, reviewing and
    99 collaborating on mutable changesets.
    99 collaborating on mutable changesets.
   100 
   100 
   101 In the Git world, they use another approach to prevent instability. By
   101 In the Git world, they use another approach to prevent instability. By
   102 convention only a single developper works on a changeset contained in
   102 convention only a single developer works on a changeset contained in
   103 a named branch. But once again this is a huge blocker for
   103 a named branch. But once again this is a huge blocker for
   104 collaborating. Moreover clueless people **will** mess up social
   104 collaborating. Moreover clueless people **will** mess up social
   105 convention soon or later.
   105 convention soon or later.
   106 
   106 
   107 
   107 
   108 Loose the DAG robustness
   108 Lose the DAG robustness
   109 ````````````````````````````
   109 ````````````````````````````
   110 
   110 
   111 The other approach in Mercurial is to keep the mutable part of the
   111 The other approach in Mercurial is to keep the mutable part of the
   112 history outside the DVCS constraint. This is the MQ approach of
   112 history outside the DVCS constraint. This is the MQ approach of
   113 sticking a quilt queue over Mercurial.
   113 sticking a quilt queue over Mercurial.
   114 
   114 
   115 This allow much more flexible workflow but two major feature are lost in the
   115 This allow much more flexible workflow but two major feature are lost in the
   116 process:
   116 process:
   117 
   117 
   118 :graceful merge: MQ use plain-patch to store changeset content and patch have
   118 :graceful merge: MQ uses plain patch to store changeset contents, which has
   119                  trouble to apply in changing context. Applying your queue
   119                  problems in changing context. Applying your queue
   120                  becomes very painful when context changes.
   120                  becomes very painful when context changes.
   121 
   121 
   122 :easy branching: A quilt queue is by definition a linear queue. Increasing risk
   122 :easy branching: A quilt queue is by definition a linear queue, increasing risk
   123                  of conflict
   123                  of conflict.
   124 
   124 
   125 It is possible to collaborate over versioned mq! But you are going to
   125 It is possible to collaborate over versioned MQ! But you are going to
   126 have a lot of troubles.
   126 have a lot of trouble.
   127 
   127 
   128 Ignore conflicts
   128 Ignore conflicts
   129 ```````````````````````````````````
   129 ```````````````````````````````````
   130  
   130  
   131 Another ignored issue is a conflicting rewrite of the same changeset.
   131 Another ignored issue is a conflicting rewrite of the same changeset.
   135 Mercurial work around by
   135 Mercurial work around by
   136 
   136 
   137 The "One set of mutable changset == One developer" mantra is also a way to work
   137 The "One set of mutable changset == One developer" mantra is also a way to work
   138 around conflicting rewriting of changeset. If two different people are able to
   138 around conflicting rewriting of changeset. If two different people are able to
   139 
   139 
   140 The git branch model allow to overwrite changeset version by another
   140 The git branch model allows overwriting changeset version by another
   141 one, but it does not care about divergent version. It is the equivalent
   141 one, but it does not care about divergent version. It is the equivalent
   142 of "common ftp" source management for changesets.
   142 of "common ftp" source management for changesets.
   143 
   143 
   144 Facing The Danger Once And For All
   144 Facing The Danger Once And For All
   145 ------------------------------------------------
   145 ------------------------------------------------
   146 
   146 
   147 Above we saw that, the more effort you put to avoid instability, the more option
   147 Above we saw that the more effort you put to avoid instability, the more options
   148 you deny. And even most restrictive work flow can't guarantee that instability
   148 you deny. And even the most restrictive workflow can't guarantee that instability
   149 will never show up!
   149 will never show up!
   150 
   150 
   151 Obsolete marker can handle the job
   151 Obsolete marker can handle the job
   152 ```````````````````````````````````
   152 ```````````````````````````````````
   153 
   153 
   154 It is time to provide a full featured solution to deal with
   154 It is time to provide a full-featured solution to deal with
   155 instability and to stop working around the issue! This is why I
   155 instability and to stop working around the issue! This is why I
   156 developing a new feature for mercurial called "Obsolete markers".
   156 am developing a new feature for Mercurial called "Obsolete markers".
   157 Obsolete markers have two key properties:
   157 Obsolete markers have two key properties:
   158 
   158 
   159 
   159 
   160 * Any "old" changeset we want to get ride of is **explicitly** marked
   160 * Any "old" changeset we want to get rid of is **explicitly** marked
   161   as "obsolete" by history rewriting operation.
   161   as "obsolete" by history rewriting operations.
   162 
   162 
   163   By explicitly marking the obsolete part of the history, we will be able to
   163   By explicitly marking the obsolete part of the history, we will be able to
   164   easily detect instability situation.
   164   easily detect instability situation.
   165 
   165 
   166 * Relations between old and new version of changesets are tracked by obsolete
   166 * Relations between old and new version of changesets are tracked by obsolete
   167   markers.
   167   markers.
   168 
   168 
   169   By Storing a meta-history of changeset evolution we are able to easily resolve
   169   By storing a meta-history of changeset evolution we are able to easily resolve
   170   instability and edition conflict [#]_ .
   170   instability and edit conflicts [#]_ .
   171 
   171 
   172 .. [#] edition conflict is another major obstable to collaboration. See the
   172 .. [#] Edit conflicts is another major obstable to collaboration. See the
   173        section dedicated to obsolete marker for details.
   173        section dedicated to obsolete marker for details.
   174 
   174 
   175 Improves robustness == improves simplicity
   175 Improved robustness == improved simplicity
   176 ````````````````````````````````````````````````
   176 ````````````````````````````````````````````````
   177 
   177 
   178 This proposal should **first** be seen as a safety measure.
   178 This proposal should **first** be seen as a safety measure.
   179 
   179 
   180 It allow to detect instability as soon as possible
   180 It allows detecting instability as soon as possible.
   181 
   181 
   182 ::
   182 ::
   183 
   183 
   184     $ hg pull
   184     $ hg pull
   185     added 3 changeset
   185     added 3 changeset
   188     working directory parent is obsolete!
   188     working directory parent is obsolete!
   189     $ hg push
   189     $ hg push
   190     outgoing unstable changesets
   190     outgoing unstable changesets
   191     (use "hg evolve" or force the push)
   191     (use "hg evolve" or force the push)
   192 
   192 
   193 And should not not encourage people to create instability
   193 And it should not not encourage people to create instability.
   194 
   194 
   195 ::
   195 ::
   196 
   196 
   197     $ hg up 42
   197     $ hg up 42
   198     $ hg commit --amend
   198     $ hg commit --amend