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