comparison docs/obs-concept.rst @ 184:f047cd4f1235

backout obs-concept.rst changes too much conflict with changes in another branch
author Pierre-Yves David <pierre-yves.david@logilab.fr>
date Wed, 28 Mar 2012 11:07:02 +0200
parents 4da5ecfb5d41
children 0698376bb13c 0f1b8119a281
comparison
equal deleted inserted replaced
177:9ca70b3ee42c 184:f047cd4f1235
1 ============================== 1 -----------------------------------------------------------
2 Why Do We Need a New Concept 2 Why Do We Need a New Concept
3 ============================== 3 -----------------------------------------------------------
4 4
5 Current DVCS are great tool to forge a series of flawless changeset on your own. 5 Current DVCS are great tool to forge a series of flawless changeset on your own.
6 But they perform poorly when is comes to **share** work in progress and 6 But they perform poorly whe is comes to **share** work in progress and
7 **collaborate** on such work in progress. 7 **collaborate** on such work in progress.
8 8
9 When people forge new version of a changeset they create a new changeset and get 9 When people forge new version of a changeset they create a new changeset and get
10 ride of the original changeset. Difficulties to collaborate mostly came from the 10 ride of the original changeset. Difficultis to collaborate mostly came from the
11 way old content are *removed* from repository. 11 way old content are *removed* from repository.
12 12
13 Mercurial Approach: Strip 13 Mercurial Approach: Strip
14 ========================= 14 -----------------------------------------------------
15 15
16 With current version of mercurial, every changesets that exist in your 16 With current version of mercurial, every changesets that exist in your
17 repository are *visible* and *meaningful*. To get ride of old changeset you 17 repository are *visible* and *meaningful*. To get ride of old changeset you
18 rewrote mercurial remove them from the repository storage. with an operation 18 rewrote mercurial remove them from the repository storage. with an operation
19 called *strip*. After the *strip* the repository looks like if the changeset 19 called *strip*. After the *strip* the repository looks like if the changeset
20 never existed. 20 never existed.
21 21
22 This approach is simple and effective but have a very big drawback: You can 22 This approach is simple and effective but have a very big drawnback: You can
23 remove changesets from **your repository only**. If strip exists in other 23 remove changesets from **your repository only**. If strip exists in other
24 repositories it will show of again and again. This only cure for this is to 24 repositories it will show of again and again. This only cure for this is to
25 strip the offending changeset from all repository. And operation at best 25 strip the offending changeset from all repository. And operation at best
26 impractical and in most case impossible! 26 impractical and in most case impossible!
27 27
28 28
29 As consequence, **you can not rewrite something once you exchange it with 29 As consequence, **you can not rewrite something once you exchange it with
30 others**. The old version will still exists along side the new one [#]_. 30 others**. The old version will still exists along side the new one [#]_.
31 31
32 Moreover stripping changesets creates backup bundles. This allows 32 Moreover backup are create stripped changeset in most case. This allow
33 restoration of the deleted changesets, but the process is painful. 33 restoration of old changeset but the process is painful.
34 34
35 Finally, as the repository format is not optimized for deletion. stripping a 35 Finally, as the repository format is not optimized for deletion. stripping a
36 changeset may be slow in some situations. 36 changeset may be slow in some situation.
37
37 38
38 To sum up, the strip approach is very simple but does not handle interaction 39 To sum up, the strip approach is very simple but does not handle interaction
39 with the outer world. Which is unfortunate for a *Distributed* VCS. 40 with the outer world. Which is unfortunate for a *Distributed* VCS.
40 41
41 .. [#] various work around exists but they require their own workflows which are distinct from the very elegant basic workflow of Mercurial. 42 .. [#] various work around exists but they are work around with their own flow.
42 43
43 Git Approach: Overwrite Reference 44 Git Approach: Overwrite Reference
44 ================================= 45 -----------------------------------------------------
45 46
46 Git approach for repository is a bit more complex: Any number of 47 Git approach for repository is a bit more complex: They can be any amount of
47 changesets can exist in a repository. but **only changesets referenced by a git 48 changeset can exist in a repository. but **only changesets referenced by a git
48 branch** are *visible* and *meaningful*. 49 branch** are *visible* and *meaningful*.
49 50
50 51
51 .. warning:: add a schema:: 52 .. warning:: add a schema::
52 53
56 | 57 |
57 A 58 A
58 59
59 Only B and A are visible. 60 Only B and A are visible.
60 61
61 This simplifies the process of getting rid of old changesets. You can 62 This ease the process of getting ride of old changeset. You can just leave them
62 just leave them in place and move the reference on the new one. You 63 in place and move the reference on the new one. You can then propagate those
63 can then propagate that change by moving the git-branch on remote host 64 change by moving the git-branch on remote host, newer version overwritting the
64 with the newer version of the marker overwriting the older one. 65 older one.
65 66
66 This approach goes a bit further but still has a major drawback: 67 This approach goes a bit further but still have major drawback:
67 68
68 69
69 Because you **overwrite** the git-branch, you have no conflict resolution. The last 70 Because you **overwrite** git-branch you have no conflit resolution. The last
70 to act wins. This makes collaboration on multiple changesets difficult because 71 to spoke win. This make collaboration on multiple changeset difficult because
71 you can't merge concurrent updates on a changeset. 72 you can't merge concurent update on changeset.
72 73
73 Every overwrite is a forced operation where the operator say "Yes I want this to 74 Every overwrite is forced operation where the operator say "Yes I want this to
74 replace that. In highly distributed environments, a user may end up with conflicting 75 replace that. On higly distributed environment user may end with conflicting
75 references and no proper way to choose. 76 reference with and no proper way to choose.
76 77
77 Because of this way to visualize a repository, git-branches are a core 78 Because of this way to visualize a repository, git-branches are a very core
78 part of git, which makes the user interface more complicated and 79 part of git. This make user interface more complicated and move through history
79 constrains the ways to move through history. 80 more constrainted.
80 81
81 Finally, even if all older changeset still exist in the repository, access to them 82 Finally, even if all older changeset still exist in the repository acces to them
82 is still painful. 83 is still painful.
83 84
84 85
85 ============================= 86 -----------------------------------------------------
86 The Obsolete Marker Concept 87 The Obsolete Marker Concept
87 ============================= 88 -----------------------------------------------------
88 89
89 90
90 91
91 92
92 93
93 As None of the concepts was powerful enough to fulfill the need of safely rewriting 94 As None of the concept was powerful enough to embrace the need to safely rewrite
94 history, including easy sharing and collaborating on mutable history, we needed another one. 95 history, easily share and collaborate on mutable history we needed another one.
95 96
96 97
97 98
98 Basic concept 99 Basic concept
99 ============= 100 -----------------------------------------------------
100 101
101 102
102 Every history rewriting operation stores the information that the old rewritten 103 Every history rewriting operation stores the information that old rewritten
103 changeset is replaced by newer version in a given set of changeset. 104 changesets has newer version available in a set of changeset.
104 105
105 All basic history rewriting operation can create an appropriate obsolete marker. 106 All basic history rewriting operation can create a appropriate obsolete marker.
106 107
107 108
108 .. figure:: ./figures/example-1-update.* 109 .. figure:: ./figures/example-1-update.*
109 110
110 *Updating* a changeset 111 *Updating* a changeset
144 145
145 To conclude, a single obsolete marker express a relation from **0..n** new 146 To conclude, a single obsolete marker express a relation from **0..n** new
146 changesets to **1** old changeset. 147 changesets to **1** old changeset.
147 148
148 Basic Usage 149 Basic Usage
149 =========== 150 -----------------------------------------------------
150 151
151 Obsolete markers create a perpendicular history: **a versioned changeset graph**. This means that offers the same features we have for 152 Obsolete markers create a perpendicular history: **a versionned version of the
153 changeset graph**. This means that we can have the same feature we have for
152 versioned files but applied to changeset: 154 versioned files but applied to changeset:
153 155
154 First: we can display a **coherent view** of the history graph in which only a 156 First: we can display a **coherent view** of the history graph with only a
155 single version of your changesets are displayed by the UI. 157 single version of your changeset are displayed by the UI.
156 158
157 Second, because obsolete changeset content is still **available**. You can 159 Second, because obsolete changeset content are still **available**. You can
158 160
159 * **browse** the content of your obsolete commit, 161 * **browse** the content of your obsolete commit,
160 162
161 * **compare** newer and older version of a changeset, 163 * **compare** newer and older version of a changeset,
162 164
168 170
169 Conflicting history rewriting operation can be detected and **resolved** as easily 171 Conflicting history rewriting operation can be detected and **resolved** as easily
170 as conflicting changes on file. 172 as conflicting changes on file.
171 173
172 174
173 Detecting and solving tricky situations 175 Detecting and solving tricky situation
174 ====================================== 176 -----------------------------------------------------
175 177
176 History rewriting can lead to complex situations. Obsolete marker introduce a 178 History rewriting can lead to complex situation. Obsolete marker introduce a
177 simple representation of this complex reality. But people using complex workflows 179 simple representation this complex reality. But people using complex workflow
178 will one day or another have to face the intrinsic complexity of some 180 will one day or another you have to face the intrinsics complexity of some
179 situations. 181 situation.
180 182
181 This section describes possible situations, defines precise sets of changesets 183 This section describe possible situations, define precise set of changesets
182 involved in such situations and explains how error cases can automatically be 184 involved in such situation and explains how error case can we automatically
183 resolved using available information. 185 resolved using available information.
184 186
185 187
186 obsolete changesets 188 obsolete changesets
187 ------------------- 189 ````````````````````
188 190
189 Old changesets left behind by obsolete operation are called **obsolete**. 191 Old changesets left behind by obsolete operation are said **obsolete**.
190 192
191 With the current version of mercurial, this *obsolete* part is stripped from the 193 With current version of mercurial, this *obsolete* part is stripped from the
192 repository before the end of every rewriting operation. 194 repository before the end of every rewritting operation.
193 195
194 .. figure:: ./figures/error-obsolete.* 196 .. figure:: ./figures/error-obsolete.*
195 197
196 Rebasing `B` and `C` on `A` (as `B'`, `C'`) 198 Rebasing `B` and `C` on `A` (as `B'`, `C'`)
197 199
198 This rebase operation added two obsolete markers from new changesets to old 200 This rebase operation added two obsolete markers from new changesets to old
199 changesets. These two old changesets are now part of the *obsolete* part of the 201 changesets. These Two old changesets are now part of the *obsolete* part of the
200 history. 202 history.
201 203
202 In most cases, the obsolete set will be fully hidden to both UI and discovery so 204 In most case the obsolete set will be fully hidden to both UI and discovery so
203 the user does not have to care about them unless he wants to audit the history rewriting 205 user do not have to care about them unless he wants to audit history rewriting
204 operation. 206 operation.
205 207
206 Unstable changesets 208 Unstable changesets
207 ------------------- 209 ```````````````````
208 210
209 While exploring the possibilities of the obsolete a bit further, you may end up with 211 While exploring obsolete marker possibility a bit further you way end up with
210 *obsolete* changeset which have *non-obsolete* children. There is two common ways to 212 *obsolete* changeset with *non-obsolete* children. There is two common ways to
211 achieve this: 213 achieve this:
212 214
213 * Pull a changeset based of an old version of a changeset [#]_. 215 * Pull a changeset based of an old version of a changeset [#]_.
214 216
215 * Use a partial rewriting operation. For example amend on a changeset with 217 * Use a partial rewriting operation. For example amend on a changeset with
216 children . 218 childrens.
217 219
218 *Non-obsolete* changeset based on *obsolete* one are called **unstable** 220 *Non-obsolete* changeset based on *obsolete* one are said **unstable**
219 221
220 .. figure:: ./figures/error-unstable.* 222 .. figure:: ./figures/error-unstable.*
221 223
222 Amend `A` into `A'` leaving `B` behind. 224 Amend `A` into `A'` leaving `B` behind.
223 225
231 Proper warning should be issued when part of the history become unstable. UI 233 Proper warning should be issued when part of the history become unstable. UI
232 will be able to use the obsolete marker to automatically suggest resolution to 234 will be able to use the obsolete marker to automatically suggest resolution to
233 the user of even carry them out for him. 235 the user of even carry them out for him.
234 236
235 237
236 XXX details on automatic resolution for 238 XXX details automatic resolution for
237 239
238 * movement 240 * movement
239 241
240 * handling deletion 242 * handling deletion
241 243
242 * handling split on multiple head 244 * handling split on multiple head
243 245
244 246
245 .. [#] For this to happen one needs to explicitly enable exchange of draft 247 .. [#] For this to happen one needs to explicitly enable exchange of draft
246 changesets. See phase help for details. 248 changeset. See phase help for details.
247 249
248 The two part of the obsolete set 250 The two part of the obsolete set
249 -------------------------------- 251 ``````````````````````````````````````
250 252
251 The previous section show that there can be two kinds of an *obsolete* changeset: 253 The previous section show that it could be two kinds of *obsolete* changeset:
252 254
253 255
254 * an *obsolete* changeset with no or *obsolete* only descendants is called **extinct**. 256 * *obsolete* changeset with no or *obsolete* only descendants, said **extinct**.
255 257
256 * an *obsolete* changeset with *unstable* descendants is called **suspended**. 258 * *obsolete* changeset with *unstable* descendants, said **suspended**.
257 259
258 260
259 .. figure:: ./figures/error-extinct.* 261 .. figure:: ./figures/error-extinct.*
260 262
261 Amend `A` and `C` leaving `B` behind. 263 Amend `A` and `C` leaving `B` behind.
264 children is *extinct*. `A` with *unstable* descendant (`B`) is *suspended*. 266 children is *extinct*. `A` with *unstable* descendant (`B`) is *suspended*.
265 `B` is *unstable* as before. 267 `B` is *unstable* as before.
266 268
267 269
268 Because nothing outside the obsolete set default on *extinct* changesets, they 270 Because nothing outside the obsolete set default on *extinct* changesets, they
269 can be safely hidden in the UI and even garbage collected. *Suspended* changesets 271 can be safely hidden in the UI and even garbage collected. *Suspended* changeset
270 have to stay visible and available until their unstable descendant are rewritten 272 have to stay visible and available until they unstable descendant are rewritten
271 into stable version. 273 in stable version.
272 274
273 275
274 Conflicting rewrites 276 Conflicting rewriting
275 --------------------- 277 ``````````````````````
276 278
277 If people start to concurrently edit the same part of the history they will 279 If people start to concurrently edit the same part of the history they will
278 likely meet conflicting situations when a changeset has been rewritten in two 280 likely meet conflicting situation when a changeset have been rewritten in two
279 different ways. 281 different versions.
280 282
281 283
282 .. figure:: ./figures/error-conflicting.* 284 .. figure:: ./figures/error-conflicting.*
283 285
284 Conflicting rewrite of `A` into `A'` and `A''` 286 Conflicting rewriting of `A` into `A'` and `A''`
285 287
286 This kind of conflict is easy to detect with obsolete markers, because an obsolete 288 This kind of conflict is easy to detect with obsolete marker because an obsolete
287 changeset can have more than one new version. It may be seen as the multiple heads 289 changeset have more than one new version. It may be seen as the multiple heads
288 case which Mercurial warns you about on pull. It is resolved the same way by a merge of 290 case Mercurial warn you about on pull. It is resolved the same way by a merge of
289 A' and A'' that will keep the same parent than `A'` and `A''` with two obsolete 291 A' and A'' that will keep the same parent than `A'` and `A''` with two obsolete
290 markers pointing to both `A` and `A'` 292 markers pointing to both `A` and `A'`
291 293
292 .. warning:: TODO: Add a schema of the resolution. (merge A' and A'' with A as 294 .. warning:: TODO: Add a schema of the resolution. (merge A' and A'' with A as
293 ancestor and graft the result of A^) 295 ancestor and graft the result of A^)
294 296
295 Allowing multiple new changesets to obsolete a single one allows to differenciate 297 Allowing multiple new changesets to obsolete a single one allow to distinct a
296 split changesets from history rewriting conflicts. 298 splitted changeset from history rewriting conflict.
297 299
298 Reliable history 300 Reliable history
299 ---------------- 301 ``````````````````````
300 302
301 Obsolete marker help to smooth rewriting operation process. However they 303 Obsolete marker really help to smooth rewriting operation process. However they
302 do not change the fact that **you should only rewrite the mutable part of the 304 do not change the fact that **you should only rewrite the mutable part of the
303 history**. The phase concept enforces this rule by explicitly defining a 305 history**. The phase concept enforce this rules by explicitly defining a
304 public immutable set of changesets. Rewriting operations refuse to work on 306 public immutable set of changeset. Rewriting operation refuse to work on
305 public changesets, but there are still some corner cases where previously rewritten changesets 307 public changeset, but they is still some corner case where changesets
306 are made public. 308 rewritten in the past are made public.
307 309
308 Special rules apply for obsolete markers pointing to public changesets 310 Special rules apply for obsolete marker pointing to public changeset
309 311
310 * Public changesets are excluded from the obsolete set (public changeset are 312 * Public changesets are excluded from the obsolete set (public changeset are
311 never hidden or candidate to garbage collection) 313 never hidden or candidate to garbage collection)
312 314
313 * *newer* version of public changeset are said **latecomer** and highlighted as 315 * *newer* version of public changeset are said **latecomer** and highlighted as
321 323
322 .. warning:: add a schema 324 .. warning:: add a schema
323 325
324 326
325 Conclusion 327 Conclusion
326 ========== 328 ----------------
327 329
328 The obsolete marker is a powerful concept that allows mercurial to safely handle 330 Obsolete marker is a powerful concept that allow mercurial to safely handle
329 history rewriting operations. It is a new type of relation between Mercurial 331 history rewriting operations. It is a new type of relation between Mercurial
330 changesets which tracks the result of history rewriting operations. 332 changesets that track the result of history rewriting operations.
331 333
332 This concept is simple to define and provides a very solid base for: 334 This concept is simple to define and provides a very solid base to:
333 335
334 336
335 - Very fast history rewriting operations, 337 - Very fast history rewriting operations,
336 338
337 - auditable and reversible history rewriting process, 339 - auditable and reversible history rewritting process,
338 340
339 - clean final history, 341 - clean final history,
340 342
341 - sharing and collaborating on the mutable part of the history, 343 - share and collaborate on mutable part of the history,
342 344
343 - gracefully handling history rewriting conflicts, 345 - gracefully handle history rewriting conflict,
344 346
345 - various history rewriting UI’s collaborating with an underlying common API. 347 - allows various history rewriting UI to collaborate with a underlying common API.
346 348
347 .. list-table:: Comparison on solution [#]_ 349 .. list-table:: Comparison on solution [#]_
348 :header-rows: 1 350 :header-rows: 1
349 351
350 * - Solution 352 * - Solution