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 when 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. Difficulties to collaborate mostly came from the |
10 new changeset and get rid of the original changeset. Difficulties 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 drawback: You can |
23 This approach is simple and effective except for one 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 stripping changesets creates backup bundles. This allows |
33 Moreover stripping changesets creates backup bundles. This allows |
33 restoration of the deleted changesets, but the process is painful. |
34 restoration of the deleted changesets, but the process is painful. |
34 |
35 |
35 Finally, as the repository format is not optimized for deletion. stripping a |
36 Finally, as the repository format is not optimized for deletion. stripping a |
36 changeset may be slow in some situations. |
37 changeset may be slow in some situations. |
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 |
39 with the outer world. Which is unfortunate for a *Distributed* VCS. |
40 interaction with the outer world, which is very unfortunate for a |
|
41 *Distributed* VCS. |
40 |
42 |
41 .. [#] various work around exists but they require their own workflows which are distinct from the very elegant basic workflow of Mercurial. |
43 .. [#] various work around exists but they require their own workflows which are distinct from the very elegant basic workflow of Mercurial. |
42 |
44 |
43 Git Approach: Overwrite Reference |
45 Git Approach: Overwrite Reference |
44 ================================= |
46 ----------------------------------------------------- |
45 |
47 |
46 Git approach for repository is a bit more complex: Any number of |
48 The Git approach to repository structure is a bit more complex: there |
47 changesets can exist in a repository. but **only changesets referenced by a git |
49 can be any amount of unrelated changesets in a repository, and **only |
48 branch** are *visible* and *meaningful*. |
50 changesets referenced by a git branch** are *visible* and |
|
51 *meaningful*. |
49 |
52 |
50 |
53 |
51 .. warning:: add a schema:: |
54 .. warning:: add a schema:: |
52 |
55 |
53 C |
56 C |
58 |
61 |
59 Only B and A are visible. |
62 Only B and A are visible. |
60 |
63 |
61 This simplifies the process of getting rid of old changesets. You can |
64 This simplifies the process of getting rid of old changesets. You can |
62 just leave them in place and move the reference on the new one. You |
65 just leave them in place and move the reference on the new one. You |
63 can then propagate that change by moving the git-branch on remote host |
66 can then propagate this change by moving the git-branch on remote host |
64 with the newer version of the marker overwriting the older one. |
67 with the newer version of the marker overwriting the older one. |
65 |
68 |
66 This approach goes a bit further but still has a major drawback: |
69 This approach goes a bit further but still has a major drawback: |
67 |
|
68 |
70 |
69 Because you **overwrite** the git-branch, you have no conflict resolution. The last |
71 Because you **overwrite** the git-branch, you have no conflict resolution. The last |
70 to act wins. This makes collaboration on multiple changesets difficult because |
72 to act wins. This makes collaboration on multiple changesets difficult because |
71 you can't merge concurrent updates on a changeset. |
73 you can't merge concurrent updates on a changeset. |
72 |
74 |
73 Every overwrite is a forced operation where the operator say "Yes I want this to |
75 Every overwrite is a forced operation where the operator says "Yes I want this to |
74 replace that. In highly distributed environments, a user may end up with conflicting |
76 replace that. In highly distributed environments, a user may end up with conflicting |
75 references and no proper way to choose. |
77 references and no proper way to choose. |
76 |
78 |
77 Because of this way to visualize a repository, git-branches are a core |
79 Because of this way to visualize a repository, git-branches are a core |
78 part of git, which makes the user interface more complicated and |
80 part of git, which makes the user interface more complicated and |
79 constrains the ways to move through history. |
81 constrains moving through history. |
80 |
82 |
81 Finally, even if all older changeset still exist in the repository, access to them |
83 Finally, even if all older changesets still exist in the repository, accesing them |
82 is still painful. |
84 is still painful. |
83 |
85 |
84 |
86 |
85 ============================= |
87 ----------------------------------------------------- |
86 The Obsolete Marker Concept |
88 The Obsolete Marker Concept |
87 ============================= |
89 ----------------------------------------------------- |
88 |
90 |
89 |
91 |
90 |
92 As None of the concepts was powerful enough to fulfill the need of safely rewriting |
91 |
93 history, including easy sharing and collaborating on mutable history, we needed another one. |
92 |
|
93 As None of the concepts was powerful enough to fulfill the need of safely rewriting |
|
94 history, including easy sharing and collaborating on mutable history, we needed another one. |
|
95 |
|
96 |
|
97 |
94 |
98 Basic concept |
95 Basic concept |
99 ============= |
96 ----------------------------------------------------- |
100 |
97 |
101 |
98 |
102 Every history rewriting operation stores the information that the old rewritten |
99 Every history rewriting operation stores the information that old rewritten |
103 changeset is replaced by newer version in a given set of changeset. |
100 changeset is replaced by newer version in a given set of changesets. |
104 |
101 |
105 All basic history rewriting operation can create an appropriate obsolete marker. |
102 All basic history rewriting operation can create an appropriate obsolete marker. |
106 |
103 |
107 |
104 |
108 .. figure:: ./figures/example-1-update.* |
105 .. figure:: ./figures/example-1-update.* |
144 |
141 |
145 To conclude, a single obsolete marker express a relation from **0..n** new |
142 To conclude, a single obsolete marker express a relation from **0..n** new |
146 changesets to **1** old changeset. |
143 changesets to **1** old changeset. |
147 |
144 |
148 Basic Usage |
145 Basic Usage |
149 =========== |
146 ----------------------------------------------------- |
150 |
147 |
151 Obsolete markers create a perpendicular history: **a versioned changeset graph**. This means that offers the same features we have for |
148 Obsolete markers create a perpendicular history: **a versioned changeset graph**. This means that offers the same features we have for |
152 versioned files but applied to changeset: |
149 versioned files but applied to changeset: |
153 |
150 |
154 First: we can display a **coherent view** of the history graph in which only a |
151 First: we can display a **coherent view** of the history graph in which only a |
155 single version of your changesets are displayed by the UI. |
152 single version of your changesets is displayed by the UI. |
156 |
153 |
157 Second, because obsolete changeset content is still **available**. You can |
154 Second, because obsolete changeset content is still **available**. You can |
158 |
155 you can |
159 * **browse** the content of your obsolete commit, |
156 |
160 |
157 * **browse** the content of your obsolete commits, |
161 * **compare** newer and older version of a changeset, |
158 |
162 |
159 * **compare** newer and older versions of a changeset, |
163 * **restore** content of previously obsolete changeset. |
160 |
164 |
161 * **restore** content of previously obsolete changesets. |
165 Finally, obsolete marker can be **exchanged between repositories**. You are able to |
162 |
166 share the result on your history rewriting operation with other and **collaborate |
163 Finally, the obsolete marker can be **exchanged between |
167 on mutable part of the history**. |
164 repositories**. You are able to share the result on your history |
168 |
165 rewriting operations with other prople and **collaborate on the |
169 Conflicting history rewriting operation can be detected and **resolved** as easily |
166 mutable part of the history**. |
170 as conflicting changes on file. |
167 |
|
168 Conflicting history rewriting operation can be detected and |
|
169 **resolved** as easily as conflicting changes on a file. |
171 |
170 |
172 |
171 |
173 Detecting and solving tricky situations |
172 Detecting and solving tricky situations |
174 ====================================== |
173 ----------------------------------------------------- |
175 |
174 |
176 History rewriting can lead to complex situations. Obsolete marker introduce a |
175 History rewriting can lead to complex situations. The obsolete marker |
177 simple representation of this complex reality. But people using complex workflows |
176 introduces a simple representation for this complex reality. But |
178 will one day or another have to face the intrinsic complexity of some |
177 people using complex workflows will one day or another have to face |
179 situations. |
178 the intrinsic complexity of some real-world situation. |
180 |
179 |
181 This section describes possible situations, defines precise sets of changesets |
180 This section describes possible situations, defines precise sets of |
182 involved in such situations and explains how error cases can automatically be |
181 changesets involved in such situations and explains how the error |
183 resolved using available information. |
182 cases can be resolved automatically using the available information. |
184 |
183 |
185 |
184 |
186 obsolete changesets |
185 Obsolete changesets |
187 ------------------- |
186 ```````````````````` |
188 |
187 |
189 Old changesets left behind by obsolete operation are called **obsolete**. |
188 Old changesets left behind by obsolete operation are called **obsolete**. |
190 |
189 |
191 With the current version of mercurial, this *obsolete* part is stripped from the |
190 With the current version of mercurial, this *obsolete* part is stripped from the |
192 repository before the end of every rewriting operation. |
191 repository before the end of every rewriting operation. |
197 |
196 |
198 This rebase operation added two obsolete markers from new changesets to old |
197 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 |
198 changesets. These two old changesets are now part of the *obsolete* part of the |
200 history. |
199 history. |
201 |
200 |
202 In most cases, the obsolete set will be fully hidden to both UI and discovery so |
201 In most cases, the obsolete set will be fully hidden to both the UI and |
203 the user does not have to care about them unless he wants to audit the history rewriting |
202 discovery, hence users do not have to care about them unless they want to |
204 operation. |
203 audit history rewriting operations. |
205 |
204 |
206 Unstable changesets |
205 Unstable changesets |
207 ------------------- |
206 ``````````````````` |
208 |
207 |
209 While exploring the possibilities of the obsolete a bit further, you may end up with |
208 While exploring the possibilities of the obsolete marker a bit further, you may end up with |
210 *obsolete* changeset which have *non-obsolete* children. There is two common ways to |
209 *obsolete* changesets which have *non-obsolete* children. There is two common ways to |
211 achieve this: |
210 achieve this: |
212 |
211 |
213 * Pull a changeset based of an old version of a changeset [#]_. |
212 * Pull a changeset based of an old version of a changeset [#]_. |
214 |
213 |
215 * Use a partial rewriting operation. For example amend on a changeset with |
214 * Use a partial rewriting operation. For example amend on a changeset with |
216 children . |
215 children. |
217 |
216 |
218 *Non-obsolete* changeset based on *obsolete* one are called **unstable** |
217 *Non-obsolete* changeset based on *obsolete* one are called **unstable** |
219 |
218 |
220 .. figure:: ./figures/error-unstable.* |
219 .. figure:: ./figures/error-unstable.* |
221 |
220 |
226 its parent `A` is *obsolete*. In addition, we have enough data to |
225 its parent `A` is *obsolete*. In addition, we have enough data to |
227 automatically resolve this instability: we know that the new version of `B` |
226 automatically resolve this instability: we know that the new version of `B` |
228 parent (`A`) is `A'`, We can deduce that we should rebase `B` on `A'` to get |
227 parent (`A`) is `A'`, We can deduce that we should rebase `B` on `A'` to get |
229 a stable history again. |
228 a stable history again. |
230 |
229 |
231 Proper warning should be issued when part of the history become unstable. UI |
230 Proper warnings should be issued when part of the history becomes |
232 will be able to use the obsolete marker to automatically suggest resolution to |
231 unstable. The UI will be able to use the obsolete marker to |
233 the user of even carry them out for him. |
232 automatically suggest a resolution to the user of even carry them out |
|
233 for him. |
234 |
234 |
235 |
235 |
236 XXX details on automatic resolution for |
236 XXX details on automatic resolution for |
237 |
237 |
238 * movement |
238 * movement |
270 have to stay visible and available until their unstable descendant are rewritten |
270 have to stay visible and available until their unstable descendant are rewritten |
271 into stable version. |
271 into stable version. |
272 |
272 |
273 |
273 |
274 Conflicting rewrites |
274 Conflicting rewrites |
275 --------------------- |
275 ```````````````````` |
276 |
276 |
277 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 |
278 likely meet conflicting situations when a changeset has been rewritten in two |
278 likely meet conflicting situations when a changeset has been rewritten in two |
279 different ways. |
279 different ways. |
280 |
280 |
281 |
281 |
282 .. figure:: ./figures/error-conflicting.* |
282 .. figure:: ./figures/error-conflicting.* |
283 |
283 |
284 Conflicting rewrite of `A` into `A'` and `A''` |
284 Conflicting rewrite of `A` into `A'` and `A''` |
285 |
285 |
286 This kind of conflict is easy to detect with obsolete markers, because an obsolete |
286 This kind of conflict is easy to detect with an obsolete marker |
287 changeset can have more than one new version. It may be seen as the multiple heads |
287 because an obsolete changeset can have more than one new version. It |
288 case which Mercurial warns you about on pull. It is resolved the same way by a merge of |
288 may be seen as the multiple heads case. Mercurial warns you about this |
289 A' and A'' that will keep the same parent than `A'` and `A''` with two obsolete |
289 on pull. It is resolved the same way by a merge of A' and A'' that |
|
290 will keep the same parent than `A'` and `A''` with two obsolete |
290 markers pointing to both `A` and `A'` |
291 markers pointing to both `A` and `A'` |
291 |
292 |
292 .. warning:: TODO: Add a schema of the resolution. (merge A' and A'' with A as |
293 .. warning:: TODO: Add a schema of the resolution. (merge A' and A'' with A as |
293 ancestor and graft the result of A^) |
294 ancestor and graft the result of A^) |
294 |
295 |
295 Allowing multiple new changesets to obsolete a single one allows to differenciate |
296 Allowing multiple new changesets to obsolete a single one allows to |
296 split changesets from history rewriting conflicts. |
297 distinguish a split changeset from a history rewriting conflict. |
297 |
298 |
298 Reliable history |
299 Reliable history |
299 ---------------- |
300 `````````````````````` |
300 |
301 |
301 Obsolete marker help to smooth rewriting operation process. However they |
302 Obsolete marker help to smooth rewriting operation process. However they |
302 do not change the fact that **you should only rewrite the mutable part of the |
303 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 |
304 history**. The phase concept enforces this rule by explicitly defining a |
304 public immutable set of changesets. Rewriting operations refuse to work on |
305 public immutable set of changesets. Rewriting operations refuse to work on |
305 public changesets, but there are still some corner cases where previously rewritten changesets |
306 public changesets, but there are still some corner cases where previously rewritten changesets |
306 are made public. |
307 are made public. |
307 |
308 |
308 Special rules apply for obsolete markers pointing to public changesets |
309 Special rules apply for obsolete markers pointing to public changesets: |
309 |
310 |
310 * Public changesets are excluded from the obsolete set (public changeset are |
311 * Public changesets are excluded from the obsolete set (public |
311 never hidden or candidate to garbage collection) |
312 changesets are never hidden or candidate to garbage collection) |
312 |
313 |
313 * *newer* version of public changeset are said **latecomer** and highlighted as |
314 * *newer* version of a public changeset are called **latecomer** and highlighted as |
314 error case. |
315 an error case. |
315 |
316 |
316 |
317 Solving such an error is easy. Because we know what changeset a |
317 Solving such error is easy. Because we know what changeset a *latecomer* try to |
318 *latecomer* tries to rewrite, we can easily compute a smaller |
318 rewrite, we can easily compute a smaller changeset containing only the change |
319 changeset containing only the change from the old *public* to the new |
319 from the old *public* to the new *latecomer*. |
320 *latecomer*. |
320 |
|
321 |
321 |
322 .. warning:: add a schema |
322 .. warning:: add a schema |
323 |
323 |
324 |
324 |
325 Conclusion |
325 Conclusion |
326 ========== |
326 ---------------- |
327 |
327 |
328 The obsolete marker is a powerful concept that allows mercurial to safely handle |
328 The obsolete marker is a powerful concept that allows mercurial to safely handle |
329 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 |
330 changesets which tracks the result of history rewriting operations. |
330 changesets which tracks the result of history rewriting operations. |
331 |
331 |