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 tools to forge a series of flawless changeset on your own. |
5 Current DVCSes are great tools for forging a series of flawless |
6 But they perform poorly when it comes to **sharing** some work in progress and |
6 changesets on your own. But they perform poorly when it comes to |
7 **collaborating** on such work in progress. |
7 **sharing** some work in progress and **collaborating** on such work |
|
8 in progress. |
8 |
9 |
9 When people forge a new version of a changeset they actually create a |
10 When people forge a new version of a changeset they actually create a |
10 new changeset and get rid of the original changeset. Difficulties to |
11 new changeset and get rid of the original changeset. Difficulties to |
11 collaborate mostly came from the way old content is *removed* from |
12 collaborate mostly came from the way old content is *removed* from |
12 a repository. |
13 a repository. |
16 |
17 |
17 With the current version of mercurial, every changeset that exists in |
18 With the current version of mercurial, every changeset that exists in |
18 your repository is *visible* and *meaningful*. To delete old |
19 your repository is *visible* and *meaningful*. To delete old |
19 (rewritten) changesets, mercurial removes them from the repository |
20 (rewritten) changesets, mercurial removes them from the repository |
20 storage with an operation called *strip*. After the *stripping*, the |
21 storage with an operation called *strip*. After the *stripping*, the |
21 repository looks like if the changeset never existed. |
22 repository looks as if the changeset never existed. |
22 |
23 |
23 This approach is simple and effective except for one big |
24 This approach is simple and effective except for one big |
24 drawback: you can remove changesets from **your repository only**. If |
25 drawback: you can remove changesets from **your repository only**. If |
25 a stripped changeset exists in another repository it touches, it will |
26 a stripped changeset exists in another repository it touches, it will |
26 show up again. This is because a shared changeset becomes |
27 show up again. This is because a shared changeset becomes |
27 part of a shared global history. Stripping a changeset from all |
28 part of a shared global history. Stripping a changeset from all |
28 repositories is at best impractical and in most case impossible! |
29 repositories is at best impractical and in most case impossible. |
29 |
30 |
30 As consequence, **you can not rewrite something once you exchange it with |
31 As consequence, **you can not rewrite something once you exchange it with |
31 others**. The old version will still exist along side the new one [#]_. |
32 others**. The old version will still exist along side the new one [#]_. |
32 |
33 |
33 Moreover stripping changesets creates backup bundles. This allows |
34 Moreover stripping changesets creates backup bundles. This allows |
38 |
39 |
39 To sum up, the strip approach is very simple but does not handle |
40 To sum up, the strip approach is very simple but does not handle |
40 interaction with the outer world, which is very unfortunate for a |
41 interaction with the outer world, which is very unfortunate for a |
41 *Distributed* VCS. |
42 *Distributed* VCS. |
42 |
43 |
43 .. [#] various work around exists but they require their own workflows which are distinct from the very elegant basic workflow of Mercurial. |
44 .. [#] various work around exists but they require their own workflows |
|
45 which are distinct from the very elegant basic workflow of |
|
46 Mercurial. |
44 |
47 |
45 Git Approach: Overwrite Reference |
48 Git Approach: Overwrite Reference |
46 ----------------------------------------------------- |
49 ----------------------------------------------------- |
47 |
50 |
48 The Git approach to repository structure is a bit more complex: there |
51 The Git approach to repository structure is a bit more complex: there |
66 can then propagate this change by moving the git-branch on remote host |
69 can then propagate this change by moving the git-branch on remote host |
67 with the newer version of the marker overwriting the older one. |
70 with the newer version of the marker overwriting the older one. |
68 |
71 |
69 This approach goes a bit further but still has a major drawback: |
72 This approach goes a bit further but still has a major drawback: |
70 |
73 |
71 Because you **overwrite** the git-branch, you have no conflict resolution. The last |
74 Because you **overwrite** the git-branch, you have no conflict |
72 to act wins. This makes collaboration on multiple changesets difficult because |
75 resolution. The last to act wins. This makes collaboration on multiple |
73 you can't merge concurrent updates on a changeset. |
76 changesets difficult because you can't merge concurrent updates on a |
74 |
77 changeset. |
75 Every overwrite is a forced operation where the operator says "Yes I want this to |
78 |
76 replace that. In highly distributed environments, a user may end up with conflicting |
79 Every overwrite is a forced operation where the operator says, "yes I |
77 references and no proper way to choose. |
80 want this to replace that". In highly distributed environments, a user |
|
81 may end up with conflicting references and no proper way to choose. |
78 |
82 |
79 Because of this way to visualize a repository, git-branches are a core |
83 Because of this way to visualize a repository, git-branches are a core |
80 part of git, which makes the user interface more complicated and |
84 part of git, which makes the user interface more complicated and |
81 constrains moving through history. |
85 constrains moving through history. |
82 |
86 |
83 Finally, even if all older changesets still exist in the repository, accesing them |
87 Finally, even if all older changesets still exist in the repository, |
84 is still painful. |
88 accesing them is still painful. |
85 |
89 |
86 |
90 |
87 ----------------------------------------------------- |
91 ----------------------------------------------------- |
88 The Obsolete Marker Concept |
92 The Obsolete Marker Concept |
89 ----------------------------------------------------- |
93 ----------------------------------------------------- |
90 |
94 |
91 |
95 |
92 As None of the concepts was powerful enough to fulfill the need of safely |
96 As none of the concepts was powerful enough to fulfill the need of |
93 rewriting history, including easy sharing and collaborating on mutable history, |
97 safely rewriting history, including easy sharing and collaboration on |
94 we needed another one. |
98 mutable history, we needed another one. |
95 |
99 |
96 Basic concept |
100 Basic concept |
97 ----------------------------------------------------- |
101 ----------------------------------------------------- |
98 |
102 |
99 |
103 |
144 changesets to **1** old changeset. |
148 changesets to **1** old changeset. |
145 |
149 |
146 Basic Usage |
150 Basic Usage |
147 ----------------------------------------------------- |
151 ----------------------------------------------------- |
148 |
152 |
149 Obsolete markers create a perpendicular history: **a versioned changeset graph**. This means that offers the same features we have for |
153 Obsolete markers create a perpendicular history: **a versioned |
150 versioned files but applied to changeset: |
154 changeset graph**. This means that offers the same features we have |
|
155 for versioned files but applied to changeset: |
151 |
156 |
152 First: we can display a **coherent view** of the history graph in which only a |
157 First: we can display a **coherent view** of the history graph in which only a |
153 single version of your changesets is displayed by the UI. |
158 single version of your changesets is displayed by the UI. |
154 |
159 |
155 Second, because obsolete changeset content is still **available**. You can |
160 Second, because obsolete changeset content is still **available**. You can |
193 |
198 |
194 .. figure:: ./figures/error-obsolete.* |
199 .. figure:: ./figures/error-obsolete.* |
195 |
200 |
196 Rebasing `B` and `C` on `A` (as `B'`, `C'`) |
201 Rebasing `B` and `C` on `A` (as `B'`, `C'`) |
197 |
202 |
198 This rebase operation added two obsolete markers from new changesets to old |
203 This rebase operation added two obsolete markers from new |
199 changesets. These two old changesets are now part of the *obsolete* part of the |
204 changesets to old changesets. These two old changesets are now |
200 history. |
205 part of the *obsolete* part of the history. |
201 |
206 |
202 In most cases, the obsolete set will be fully hidden to both the UI and |
207 In most cases, the obsolete set will be fully hidden to both the UI and |
203 discovery, hence users do not have to care about them unless they want to |
208 discovery, hence users do not have to care about them unless they want to |
204 audit history rewriting operations. |
209 audit history rewriting operations. |
205 |
210 |
206 Unstable changesets |
211 Unstable changesets |
207 ``````````````````` |
212 ``````````````````` |
208 |
213 |
209 While exploring the possibilities of the obsolete marker a bit further, you may end up with |
214 While exploring the possibilities of the obsolete marker a bit |
210 *obsolete* changesets which have *non-obsolete* children. There is two common ways to |
215 further, you may end up with *obsolete* changesets which have |
211 achieve this: |
216 *non-obsolete* children. There is two common ways to achieve this: |
212 |
217 |
213 * Pull a changeset based of an old version of a changeset [#]_. |
218 * Pull a changeset based of an old version of a changeset [#]_. |
214 |
219 |
215 * Use a partial rewriting operation. For example amend on a changeset with |
220 * Use a partial rewriting operation. For example amend on a changeset with |
216 children. |
221 children. |
219 |
224 |
220 .. figure:: ./figures/error-unstable.* |
225 .. figure:: ./figures/error-unstable.* |
221 |
226 |
222 Amend `A` into `A'` leaving `B` behind. |
227 Amend `A` into `A'` leaving `B` behind. |
223 |
228 |
224 In this situation we can not consider `B` as *obsolete*. But we have all |
229 In this situation we cannot consider `B` as *obsolete*. But we |
225 necessary data to detect `B` as an *unstable* branch of the history because |
230 have all the necessary data to detect `B` as an *unstable* branch |
226 its parent `A` is *obsolete*. In addition, we have enough data to |
231 of the history because its parent `A` is *obsolete*. In addition, |
227 automatically resolve this instability: we know that the new version of `B` |
232 we have enough data to automatically resolve this instability: we |
228 parent (`A`) is `A'`, We can deduce that we should rebase `B` on `A'` to get |
233 know that the new version of `B` parent (`A`) is `A'`. We can |
229 a stable history again. |
234 deduce that we should rebase `B` on `A'` to get a stable history |
|
235 again. |
230 |
236 |
231 Proper warnings should be issued when part of the history becomes |
237 Proper warnings should be issued when part of the history becomes |
232 unstable. The UI will be able to use the obsolete marker to |
238 unstable. The UI will be able to use the obsolete marker to |
233 automatically suggest a resolution to the user of even carry them out |
239 automatically suggest a resolution to the user of even carry them out |
234 for him. |
240 for them. |
235 |
241 |
236 |
242 |
237 XXX details on automatic resolution for |
243 XXX details on automatic resolution for |
238 |
244 |
239 * movement |
245 * movement |
264 In this example we have two *obsolete* changesets: `C` with no *unstable* |
270 In this example we have two *obsolete* changesets: `C` with no *unstable* |
265 children is *extinct*. `A` with *unstable* descendant (`B`) is *suspended*. |
271 children is *extinct*. `A` with *unstable* descendant (`B`) is *suspended*. |
266 `B` is *unstable* as before. |
272 `B` is *unstable* as before. |
267 |
273 |
268 |
274 |
269 Because nothing outside the obsolete set default on *extinct* changesets, they |
275 Because nothing outside the obsolete set default on *extinct* |
270 can be safely hidden in the UI and even garbage collected. *Suspended* changesets |
276 changesets, they can be safely hidden in the UI and even garbage |
271 have to stay visible and available until their unstable descendant are rewritten |
277 collected. *Suspended* changesets have to stay visible and available |
272 into stable version. |
278 until their unstable descendant are rewritten into stable version. |
273 |
279 |
274 |
280 |
275 Conflicting rewrites |
281 Conflicting rewrites |
276 ```````````````````` |
282 ```````````````````` |
277 |
283 |
298 distinguish a split changeset from a history rewriting conflict. |
304 distinguish a split changeset from a history rewriting conflict. |
299 |
305 |
300 Reliable history |
306 Reliable history |
301 `````````````````````` |
307 `````````````````````` |
302 |
308 |
303 Obsolete marker help to smooth rewriting operation process. However they |
309 Obsolete markers help to smooth rewriting operation process. However |
304 do not change the fact that **you should only rewrite the mutable part of the |
310 they do not change the fact that **you should only rewrite the mutable |
305 history**. The phase concept enforces this rule by explicitly defining a |
311 part of the history**. The phase concept enforces this rule by |
306 public immutable set of changesets. Rewriting operations refuse to work on |
312 explicitly defining a public immutable set of changesets. Rewriting |
307 public changesets, but there are still some corner cases where previously rewritten changesets |
313 operations refuse to work on public changesets, but there are still |
308 are made public. |
314 some corner cases where previously rewritten changesets are made |
|
315 public. |
309 |
316 |
310 Special rules apply for obsolete markers pointing to public changesets: |
317 Special rules apply for obsolete markers pointing to public changesets: |
311 |
318 |
312 * Public changesets are excluded from the obsolete set (public |
319 * Public changesets are excluded from the obsolete set (public |
313 changesets are never hidden or candidate to garbage collection) |
320 changesets are never hidden or candidate to garbage collection) |
314 |
321 |
315 * *newer* version of a public changeset are called **latecomer** and highlighted as |
322 * *newer* version of a public changeset are called **latecomer** and |
316 an error case. |
323 highlighted as an error case. |
317 |
324 |
318 Solving such an error is easy. Because we know what changeset a |
325 Solving such an error is easy. Because we know what changeset a |
319 *latecomer* tries to rewrite, we can easily compute a smaller |
326 *latecomer* tries to rewrite, we can easily compute a smaller |
320 changeset containing only the change from the old *public* to the new |
327 changeset containing only the change from the old *public* to the new |
321 *latecomer*. |
328 *latecomer*. |