Mercurial > evolve
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 |