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 tools 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 it comes to **sharing** some work in progress and |
7 **collaborate** on such work in progress. |
7 **collaborating** 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 a new version of a changeset they actually create a |
10 ride of the original changeset. Difficultis to collaborate mostly came from the |
10 new changeset and get rid of the original changeset. Difficultis to |
11 way old content are *removed* from repository. |
11 collaborate mostly came from the way old content is *removed* from |
|
12 a repository. |
12 |
13 |
13 Mercurial Approach: Strip |
14 Mercurial Approach: Strip |
14 ----------------------------------------------------- |
15 ----------------------------------------------------- |
15 |
16 |
16 With current version of mercurial, every changesets that exist in your |
17 With the current version of mercurial, every changeset that exists in |
17 repository are *visible* and *meaningful*. To get ride of old changeset you |
18 your repository is *visible* and *meaningful*. To delete old |
18 rewrote mercurial remove them from the repository storage. with an operation |
19 (rewritten) changesets, mercurial removes them from the repository |
19 called *strip*. After the *strip* the repository looks like if the changeset |
20 storage with an operation called *strip*. After the *stripping*, the |
20 never existed. |
21 repository looks like if the changeset never existed. |
21 |
22 |
22 This approach is simple and effective but have a very big drawnback: You can |
23 This approach is simple and effective except there is a very big |
23 remove changesets from **your repository only**. If strip exists in other |
24 drawback: you can remove changesets from **your repository only**. If |
24 repositories it will show of again and again. This only cure for this is to |
25 a stripped changeset exists in another repository it touches, it will |
25 strip the offending changeset from all repository. And operation at best |
26 show up again. This is because a shared changeset becomes |
26 impractical and in most case impossible! |
27 part of a shared global history. Stripping a changeset from all |
27 |
28 repositories is at best impractical and in most case impossible! |
28 |
29 |
29 As consequence, **you can not rewrite something once you exchange it with |
30 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 [#]_. |
31 others**. The old version will still exist along side the new one [#]_. |
31 |
32 |
32 Moreover backup are create stripped changeset in most case. This allow |
33 However backups are created while stripping a changeset in most |
33 restoration of old changeset but the process is painful. |
34 cases. This allow restoration of an old changeset but the process is |
34 |
35 painful. |
35 Finally, as the repository format is not optimized for deletion. stripping a |
36 |
36 changeset may be slow in some situation. |
37 Finally, as the repository format is not optimized for deletion, |
37 |
38 stripping a changeset may be slow in some situation. |
38 |
39 |
39 To sum up, the strip approach is very simple but does not handle interaction |
40 To sum up, the strip approach is very simple but does not handle |
40 with the outer world. Which is unfortunate for a *Distributed* VCS. |
41 interaction with the outer world, which is very unfortunate for a |
41 |
42 *Distributed* VCS. |
42 .. [#] various work around exists but they are work around with their own flow. |
43 |
|
44 .. [#] various workarounds exist but they are workarounds with their own flow. |
43 |
45 |
44 Git Approach: Overwrite Reference |
46 Git Approach: Overwrite Reference |
45 ----------------------------------------------------- |
47 ----------------------------------------------------- |
46 |
48 |
47 Git approach for repository is a bit more complex: They can be any amount of |
49 The Git approach to repository structure is a bit more complex: there |
48 changeset can exist in a repository. but **only changesets referenced by a git |
50 can be any amount of unrelated changesets in a repository, and **only |
49 branch** are *visible* and *meaningful*. |
51 changesets referenced by a git branch** are *visible* and |
|
52 *meaningful*. |
50 |
53 |
51 |
54 |
52 .. warning:: add a schema:: |
55 .. warning:: add a schema:: |
53 |
56 |
54 C |
57 C |
57 | |
60 | |
58 A |
61 A |
59 |
62 |
60 Only B and A are visible. |
63 Only B and A are visible. |
61 |
64 |
62 This ease the process of getting ride of old changeset. You can just leave them |
65 This ease the process of getting rid of old changesets. You can just |
63 in place and move the reference on the new one. You can then propagate those |
66 leave them in place and move the reference on the new one. You can |
64 change by moving the git-branch on remote host, newer version overwritting the |
67 then propagate those changes by moving the git-branch on remote host, |
65 older one. |
68 the newer versions overwritting the older ones. |
66 |
69 |
67 This approach goes a bit further but still have major drawback: |
70 This approach goes a bit further but still have a major drawback: |
68 |
71 |
69 |
72 Because you **overwrite** git-branch you have no conflit resolution. The last |
70 Because you **overwrite** git-branch you have no conflit resolution. The last |
73 to speak wins. This makes collaboration on multiple changesets difficult because |
71 to spoke win. This make collaboration on multiple changeset difficult because |
74 you can't merge concurent updates on a changeset. |
72 you can't merge concurent update on changeset. |
75 |
73 |
76 Every overwrite is a forced operation where the operator says "Yes I |
74 Every overwrite is forced operation where the operator say "Yes I want this to |
77 want this to replace that". On a higly distributed environment, a user may |
75 replace that. On higly distributed environment user may end with conflicting |
78 end with conflicting references and with no proper way to choose. |
76 reference with and no proper way to choose. |
79 |
77 |
80 Because of this way to visualize a repository, git-branches are a very |
78 Because of this way to visualize a repository, git-branches are a very core |
81 core part of git. This makes the user interface more complicated and |
79 part of git. This make user interface more complicated and move through history |
82 moving through history more constrained. |
80 more constrainted. |
83 |
81 |
84 Finally, even if all older changesets still exist in the repository, accesing them |
82 Finally, even if all older changeset still exist in the repository acces to them |
|
83 is still painful. |
85 is still painful. |
84 |
86 |
85 |
87 |
86 ----------------------------------------------------- |
88 ----------------------------------------------------- |
87 The Obsolete Marker Concept |
89 The Obsolete Marker Concept |
88 ----------------------------------------------------- |
90 ----------------------------------------------------- |
89 |
91 |
90 |
92 |
91 |
93 As none of these concepts were powerful enough to embrace the need to |
92 |
94 safely share rewritten history we needed another one. |
93 |
|
94 As None of the concept was powerful enough to embrace the need to safely rewrite |
|
95 history, easily share and collaborate on mutable history we needed another one. |
|
96 |
|
97 |
|
98 |
95 |
99 Basic concept |
96 Basic concept |
100 ----------------------------------------------------- |
97 ----------------------------------------------------- |
101 |
98 |
102 |
99 |
103 Every history rewriting operation stores the information that old rewritten |
100 Every history rewriting operation stores the information that old rewritten |
104 changesets has newer version available in a set of changeset. |
101 changesets has a newer version available in a set of changesets. |
105 |
102 |
106 All basic history rewriting operation can create a appropriate obsolete marker. |
103 All basic history rewriting operation can create a appropriate obsolete marker. |
107 |
104 |
108 |
105 |
109 .. figure:: ./figures/example-1-update.* |
106 .. figure:: ./figures/example-1-update.* |
152 Obsolete markers create a perpendicular history: **a versionned version of the |
149 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 |
150 changeset graph**. This means that we can have the same feature we have for |
154 versioned files but applied to changeset: |
151 versioned files but applied to changeset: |
155 |
152 |
156 First: we can display a **coherent view** of the history graph with only a |
153 First: we can display a **coherent view** of the history graph with only a |
157 single version of your changeset are displayed by the UI. |
154 single version of your changeset displayed by the UI. |
158 |
155 |
159 Second, because obsolete changeset content are still **available**. You can |
156 Second, because obsolete changeset contents are still **available**, |
160 |
157 you can |
161 * **browse** the content of your obsolete commit, |
158 |
162 |
159 * **browse** the contents of your obsolete commits, |
163 * **compare** newer and older version of a changeset, |
160 |
164 |
161 * **compare** newer and older versions of a changeset, |
165 * **restore** content of previously obsolete changeset. |
162 |
166 |
163 * **restore** contents of previously obsolete changesets. |
167 Finally, obsolete marker can be **exchanged between repositories**. You are able to |
164 |
168 share the result on your history rewriting operation with other and **collaborate |
165 Finally, the obsolete marker can be **exchanged between |
169 on mutable part of the history**. |
166 repositories**. You are able to share the result on your history |
170 |
167 rewriting operations with other prople and **collaborate on the |
171 Conflicting history rewriting operation can be detected and **resolved** as easily |
168 mutable part of the history**. |
172 as conflicting changes on file. |
169 |
173 |
170 Conflicting history rewriting operation can be detected and |
174 |
171 **resolved** as easily as conflicting changes on a file. |
175 Detecting and solving tricky situation |
172 |
176 ----------------------------------------------------- |
173 |
177 |
174 Detecting and solving tricky situations |
178 History rewriting can lead to complex situation. Obsolete marker introduce a |
175 ----------------------------------------------------- |
179 simple representation this complex reality. But people using complex workflow |
176 |
180 will one day or another you have to face the intrinsics complexity of some |
177 History rewriting can lead to complex situations. The obsolete marker |
181 situation. |
178 introduces a simple representation for this complex reality. But |
182 |
179 people using complex workflows will one day or another have to face |
183 This section describe possible situations, define precise set of changesets |
180 the intrinsic complexity of some real-world situation. |
184 involved in such situation and explains how error case can we automatically |
181 |
185 resolved using available information. |
182 This section describes possible situations, define precise sets of |
186 |
183 changesets involved in such situations and explains how the error |
187 |
184 cases can be automatically resolved using available information. |
188 obsolete changesets |
185 |
|
186 |
|
187 Obsolete changesets |
189 ```````````````````` |
188 ```````````````````` |
190 |
189 |
191 Old changesets left behind by obsolete operation are said **obsolete**. |
190 Old changesets left behind by obsolete operation are said **obsolete**. |
192 |
191 |
193 With current version of mercurial, this *obsolete* part is stripped from the |
192 With the current version of mercurial, this *obsolete* part is |
194 repository before the end of every rewritting operation. |
193 stripped from the repository before the end of every rewritting |
|
194 operation. |
195 |
195 |
196 .. figure:: ./figures/error-obsolete.* |
196 .. figure:: ./figures/error-obsolete.* |
197 |
197 |
198 Rebasing `B` and `C` on `A` (as `B'`, `C'`) |
198 Rebasing `B` and `C` on `A` (as `B'`, `C'`) |
199 |
199 |
200 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 |
201 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 |
202 history. |
202 history. |
203 |
203 |
204 In most case the obsolete set will be fully hidden to both UI and discovery so |
204 In most cases the obsolete set will be fully hidden to both the UI and |
205 user do not have to care about them unless he wants to audit history rewriting |
205 discovery, hence users do not have to care about them unless they want to |
206 operation. |
206 audit history rewriting operations. |
207 |
207 |
208 Unstable changesets |
208 Unstable changesets |
209 ``````````````````` |
209 ``````````````````` |
210 |
210 |
211 While exploring obsolete marker possibility a bit further you way end up with |
211 While exploring the obsolete marker possibility a bit further you may |
212 *obsolete* changeset with *non-obsolete* children. There is two common ways to |
212 end up with *obsolete* changeset with *non-obsolete* children. There |
213 achieve this: |
213 are two common ways to achieve this: |
214 |
214 |
215 * Pull a changeset based of an old version of a changeset [#]_. |
215 * Pull a changeset based of an old version of a changeset [#]_. |
216 |
216 |
217 * 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 |
218 childrens. |
218 childrens. |
228 its parent `A` is *obsolete*. In addition, we have enough data to |
228 its parent `A` is *obsolete*. In addition, we have enough data to |
229 automatically resolve this instability: we know that the new version of `B` |
229 automatically resolve this instability: we know that the new version of `B` |
230 parent (`A`) is `A'`, We can deduce that we should rebase `B` on `A'` to get |
230 parent (`A`) is `A'`, We can deduce that we should rebase `B` on `A'` to get |
231 a stable history again. |
231 a stable history again. |
232 |
232 |
233 Proper warning should be issued when part of the history become unstable. UI |
233 Proper warnings should be issued when part of the history becomes |
234 will be able to use the obsolete marker to automatically suggest resolution to |
234 unstable. The UI will be able to use the obsolete marker to |
235 the user of even carry them out for him. |
235 automatically suggest a resolution to the user of even carry them out |
|
236 for him. |
236 |
237 |
237 |
238 |
238 XXX details automatic resolution for |
239 XXX details automatic resolution for |
239 |
240 |
240 * movement |
241 * movement |
275 |
276 |
276 Conflicting rewriting |
277 Conflicting rewriting |
277 `````````````````````` |
278 `````````````````````` |
278 |
279 |
279 If people start to concurrently edit the same part of the history they will |
280 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 |
281 likely meet conflicting situations when a changeset have been rewritten in two |
281 different versions. |
282 different versions. |
282 |
283 |
283 |
284 |
284 .. figure:: ./figures/error-conflicting.* |
285 .. figure:: ./figures/error-conflicting.* |
285 |
286 |
286 Conflicting rewriting of `A` into `A'` and `A''` |
287 Conflicting rewriting of `A` into `A'` and `A''` |
287 |
288 |
288 This kind of conflict is easy to detect with obsolete marker because an obsolete |
289 This kind of conflict is easy to detect with an obsolete marker |
289 changeset have more than one new version. It may be seen as the multiple heads |
290 because an obsolete changeset can have more than one new version. It |
290 case Mercurial warn you about on pull. It is resolved the same way by a merge of |
291 may be seen as the multiple heads case. Mercurial warns you about this |
291 A' and A'' that will keep the same parent than `A'` and `A''` with two obsolete |
292 on pull. It is resolved the same way by a merge of A' and A'' that |
|
293 will keep the same parent than `A'` and `A''` with two obsolete |
292 markers pointing to both `A` and `A'` |
294 markers pointing to both `A` and `A'` |
293 |
295 |
294 .. warning:: TODO: Add a schema of the resolution. (merge A' and A'' with A as |
296 .. warning:: TODO: Add a schema of the resolution. (merge A' and A'' with A as |
295 ancestor and graft the result of A^) |
297 ancestor and graft the result of A^) |
296 |
298 |
297 Allowing multiple new changesets to obsolete a single one allow to distinct a |
299 Allowing multiple new changesets to obsolete a single one allows to |
298 splitted changeset from history rewriting conflict. |
300 distinguish a split changeset from an history rewriting conflict. |
299 |
301 |
300 Reliable history |
302 Reliable history |
301 `````````````````````` |
303 `````````````````````` |
302 |
304 |
303 Obsolete marker really help to smooth rewriting operation process. However they |
305 Obsolete marker really help to smooth rewriting operation process. However they |
305 history**. The phase concept enforce this rules by explicitly defining a |
307 history**. The phase concept enforce this rules by explicitly defining a |
306 public immutable set of changeset. Rewriting operation refuse to work on |
308 public immutable set of changeset. Rewriting operation refuse to work on |
307 public changeset, but they is still some corner case where changesets |
309 public changeset, but they is still some corner case where changesets |
308 rewritten in the past are made public. |
310 rewritten in the past are made public. |
309 |
311 |
310 Special rules apply for obsolete marker pointing to public changeset |
312 Special rules apply for obsolete marker pointing to public changeset: |
311 |
313 |
312 * Public changesets are excluded from the obsolete set (public changeset are |
314 * Public changesets are excluded from the obsolete set (public |
313 never hidden or candidate to garbage collection) |
315 changesets are never hidden or candidate to garbage collection) |
314 |
316 |
315 * *newer* version of public changeset are said **latecomer** and highlighted as |
317 * *newer* version of a public changeset are said **latecomer** and highlighted as |
316 error case. |
318 an error case. |
317 |
319 |
318 |
320 Solving such an error is easy. Because we know what changeset a |
319 Solving such error is easy. Because we know what changeset a *latecomer* try to |
321 *latecomer* tries to rewrite, we can easily compute a smaller |
320 rewrite, we can easily compute a smaller changeset containing only the change |
322 changeset containing only the change from the old *public* to the new |
321 from the old *public* to the new *latecomer*. |
323 *latecomer*. |
322 |
|
323 |
324 |
324 .. warning:: add a schema |
325 .. warning:: add a schema |
325 |
326 |
326 |
327 |
327 Conclusion |
328 Conclusion |
328 ---------------- |
329 ---------------- |
329 |
330 |
330 Obsolete marker is a powerful concept that allow mercurial to safely handle |
331 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 |
332 history rewriting operations. It is a new type of relation between Mercurial |
332 changesets that track the result of history rewriting operations. |
333 changesets that track the result of history rewriting operations. |
333 |
334 |
334 This concept is simple to define and provides a very solid base to: |
335 This concept is simple to define and provides a very solid base to: |
335 |
336 |