docs/obs-concept.rst
changeset 161 4e3f25ba5401
child 163 92b073d13f2d
equal deleted inserted replaced
160:24346b78cd99 161:4e3f25ba5401
       
     1 -------------------------
       
     2 Obsolete Marker Concept
       
     3 -------------------------
       
     4 
       
     5 
       
     6 Obsolete marker is a powerful concept that allow mercurial to safely handle
       
     7 history rewriting operations. It is a new type of relation between Mercurial
       
     8 changesets that track the result of history rewriting operations.
       
     9 
       
    10 This concept is simple to define and provides a very solid base to:
       
    11 
       
    12 
       
    13 - Very fast history rewriting operations,
       
    14 
       
    15 - auditable and reversible history rewritting process,
       
    16 
       
    17 - clean final history,
       
    18 
       
    19 - share and collaborate on mutable part of the history,
       
    20 
       
    21 - gracefully handle history rewriting conflict,
       
    22 
       
    23 - allows various history rewriting UI to collaborate with a underlying common API.
       
    24 
       
    25 
       
    26 Basic concept
       
    27 -----------------------------------------------------
       
    28 
       
    29 
       
    30 Every history rewriting operation  stores the information that old rewritten
       
    31 changesets has newer version available in a set of changeset.
       
    32 
       
    33 This simple rules allows to express any possible history rewriting operation:
       
    34 
       
    35 
       
    36 
       
    37 
       
    38 .. figure:: ./figures/example-1-update.png
       
    39 
       
    40     *Updating* a changeset
       
    41 
       
    42     Create one obsolete marker: ``([A'] obsolete A)``
       
    43 
       
    44 
       
    45 
       
    46 .. figure:: ./figures/example-2-split.png
       
    47 
       
    48     *Splitting* a changeset in multiple one
       
    49 
       
    50     Create one obsolete marker ``([B1, B2] obsolete B)]``
       
    51 
       
    52 
       
    53 .. figure:: ./figures/example-3-merge.png
       
    54 
       
    55     *Merging* multiple changeset in a single one
       
    56 
       
    57     Create two obsolete markers ``([C] obsolete A), ([C] obsolete B)``
       
    58 
       
    59 .. figure:: ./figures/example-4-reorder.png
       
    60 
       
    61     *Moving* changeset around
       
    62 
       
    63     Reordering those two changesets need two obsolete markers:
       
    64     ``([A'] obsolete A), ([B'] obsolete B)``
       
    65 
       
    66 
       
    67 
       
    68 .. figure:: ./figures/example-5-delete.png
       
    69 
       
    70     *Removing* a changeset:
       
    71 
       
    72     One obselete marker ``([] obsolete B)``
       
    73 
       
    74 
       
    75 To conclude, a single obsolete marker express a relation from **0..n** new
       
    76 changesets to **1** old changeset.
       
    77 
       
    78 Basic Usage
       
    79 -----------------------------------------------------
       
    80 
       
    81 Obsolete markers create a perpendicular history: **a versionned version of the
       
    82 changeset graph**. This means that we can have the same feature we have for
       
    83 versioned files but applied to changeset:
       
    84 
       
    85 First: we can display a **coherent view** of the history graph with only a
       
    86 single version of your changeset are displayed by the UI.
       
    87 
       
    88 Second, because obsolete changeset content are still **available**. You can 
       
    89 
       
    90     * **browse** the content of your obsolete commit,
       
    91 
       
    92     * **compare** newer and older version of a changeset,
       
    93 
       
    94     * **restore** content of previously obsolete changeset.
       
    95 
       
    96 Finally, obsolete marker can be **exchanged between repositories**. You are able to
       
    97 share the result on your history rewriting operation with other and **collaborate
       
    98 on mutable part of the history**.
       
    99 
       
   100 Conflicting history rewriting operation can be detected and **resolved** as easily
       
   101 as conflicting changes on file.
       
   102 
       
   103 
       
   104 Detecting and solving tricky situation
       
   105 -----------------------------------------------------
       
   106 
       
   107 History rewriting can lead to complex situation. Obsolete marker introduce a
       
   108 simple representation this complex reality. But people using complex workflow
       
   109 will one day or another you have to face the intrinsics complexity of some
       
   110 situation.
       
   111 
       
   112 This section describe possible situations, define precise set of changesets
       
   113 involved in such situation and explains how error case can we automatically
       
   114 resolved using available information.
       
   115 
       
   116 
       
   117 obsolete changesets
       
   118 ````````````````````
       
   119 
       
   120 Old changesets left behind by obsolete operation are said **obsolete**.
       
   121 
       
   122 With current version of mercurial, this *obsolete* part is stripped from the
       
   123 repository before the end of every rewritting operation.
       
   124 
       
   125 .. figure:: ./figures/error-obsolete.png
       
   126 
       
   127     Rebasing `B` and `C` on `A` (as `B'`, `C'`)
       
   128 
       
   129     This rebase operation added two obsolete markers from new changesets to old
       
   130     changesets. These Two old changesets are now part of the *obsolete* part of the
       
   131     history.
       
   132 
       
   133 In most case the obsolete set will be fully hidden to both UI and discovery so
       
   134 user do not have to care about them unless he wants to audit history rewriting
       
   135 operation.
       
   136 
       
   137 Unstable changesets
       
   138 ```````````````````
       
   139 
       
   140 While exploring obsolete marker possibility a bit further you way end up with
       
   141 *obsolete* changeset with *non-obsolete* children. There is two common ways to
       
   142 achieve this:
       
   143 
       
   144 * Pull a changeset based of an old version of a changeset [#]_.
       
   145 
       
   146 * Use a partial rewriting operation. For example amend on a changeset with
       
   147   childrens.
       
   148 
       
   149 *Non-obsolete* changeset based on *obsolete* one are said **unstable**
       
   150 
       
   151 .. figure:: ./figures/error-unstable.png
       
   152 
       
   153     Amend `A` into `A'` leaving `B` behind.
       
   154 
       
   155     In this situation we can not consider `B` as *obsolete*.  But we have all
       
   156     necessary data to detect `B` as an *unstable* branch of the history because
       
   157     its parent `A` is *obsolete*. In addition, we have enough data to
       
   158     automatically resolve this instability: we know that the new version of `B`
       
   159     parent (`A`) is `A'`, We can deduce that we should rebase `B` on `A'` to get
       
   160     a stable history again.
       
   161 
       
   162 Proper warning should be issued when part of the history become unstable. UI
       
   163 will be able to use the obsolete marker to automatically suggest resolution to
       
   164 the user of even carry them out for him.
       
   165 
       
   166 
       
   167 XXX details automatic resolution for
       
   168 
       
   169 * movement
       
   170 
       
   171 * handling deletion
       
   172 
       
   173 * handling split on multiple head
       
   174 
       
   175 
       
   176 .. [#] For this to happen one needs to explicitly enable exchange of draft
       
   177        changeset. See phase help for details.
       
   178 
       
   179 The two part of the obsolete set
       
   180 ``````````````````````````````````````
       
   181 
       
   182 The previous section show that it could be two kinds of *obsolete* changeset:
       
   183 
       
   184 
       
   185 * *obsolete* changeset with no or *obsolete* only descendants, said **extinct**.
       
   186 
       
   187 * *obsolete* changeset with *unstable* descendants, said **suspended**.
       
   188 
       
   189 
       
   190 .. figure:: ./figures/error-extinct.png
       
   191 
       
   192     Amend `A` and `C` leaving `B` behind.
       
   193 
       
   194     In this example we have two *obsolete* changesets: `C` with no *unstable*
       
   195     children is *extinct*. `A` with *unstable* descendant (`B`) is *suspended*.
       
   196     `B` is *unstable* as before.
       
   197 
       
   198 
       
   199 Because nothing outside the obsolete set default on *extinct* changesets, they
       
   200 can be safely hidden in the UI and even garbage collected. *Suspended* changeset
       
   201 have to stay visible and available until they unstable descendant are rewritten
       
   202 in stable version.
       
   203 
       
   204 
       
   205 Conflicting rewriting
       
   206 ``````````````````````
       
   207 
       
   208 If people start to concurrently edit the same part of the history they will
       
   209 likely meet conflicting situation when a changeset have been rewritten in two
       
   210 different versions.
       
   211 
       
   212 
       
   213 .. figure:: ./figures/error-conflicting.png
       
   214 
       
   215     Conflicting rewriting of `A` into `A'` and `A''`
       
   216 
       
   217 This kind of conflict is easy to detect with obsolete marker because an obsolete
       
   218 changeset have more than one new version. It may be seen as the multiple heads
       
   219 case Mercurial warn you about on pull. It is resolved the same way by a merge of
       
   220 A' and A'' that will keep the same parent than `A'` and `A''` with two obsolete
       
   221 markers pointing to both `A` and `A'`
       
   222 
       
   223 .. warning::  TODO: Add a schema of the resolution. (merge A' and A'' with A as
       
   224               ancestor and graft the result of A^)
       
   225 
       
   226 Allowing multiple new changesets to obsolete a single one allow to distinct a
       
   227 splitted changeset from history rewriting conflict.
       
   228 
       
   229 Reliable history
       
   230 ``````````````````````
       
   231 
       
   232 Obsolete marker really help to smooth rewriting operation process. However they
       
   233 do not change the fact that **you should only rewrite the mutable part of the
       
   234 history**. The phase concept enforce this rules by explicitly defining a
       
   235 public immutable set of changeset. Rewriting operation refuse to work on
       
   236 public changeset, but they is still some corner case where changesets
       
   237 rewritten in the past are made public.
       
   238 
       
   239 Special rules apply for obsolete marker pointing to public changeset
       
   240 
       
   241 * Public changesets are excluded from the obsolete set (public changeset are
       
   242   never hidden or candidate to garbage collection)
       
   243 
       
   244 * *newer* version of public changeset are said **latecomer** and highlighted as
       
   245   error case.
       
   246 
       
   247 
       
   248 Solving such error is easy. Because we know what changeset a *latecomer* try to
       
   249 rewrite, we can easily compute a smaller changeset containing only the change
       
   250 from the old *public* to the new *latecomer*.
       
   251 
       
   252 
       
   253 .. warning:: add a schema
       
   254