8 An intrinsic contradiction |
8 An intrinsic contradiction |
9 ----------------------------------- |
9 ----------------------------------- |
10 |
10 |
11 XXX starts by talking about getting ride of changeset. |
11 XXX starts by talking about getting ride of changeset. |
12 |
12 |
13 DVCS bring two new major concepts to the Version Control Scene: |
13 DVCSes bring two new major concepts to the Version Control Scene: |
14 |
14 |
15 * History is organized as a robust DAG, |
15 * History is organized as a robust DAG, |
16 * History can be rewritten. |
16 * History can be rewritten. |
17 |
17 |
18 |
|
19 However, the two concepts are in contradiction: |
18 However, the two concepts are in contradiction: |
20 |
19 |
21 To achieve a robust history, three key elements are gathered in *changeset*: |
20 To achieve a robust history, three key elements are gathered in *changesets*: |
22 |
21 |
23 * Full snapshot of the versioned content, |
22 * Full snapshot of the versioned content, |
24 * Reference to the previous full snapshot used to build the new one, |
23 * Reference to the previous full snapshot used to build the new one, |
25 * A description of the change who lead from the old content to the new old. |
24 * A description of the change who lead from the old content to the new old. |
26 |
25 |
27 All three elements are to compute a *unique* hash that identify the changeset |
26 All three elements are to compute a *unique* hash that identify the changeset |
28 (with various other metadata). This identification is a key part of DVCS design. |
27 (with various other metadata). This identification is a key part of DVCS design. |
29 |
28 |
30 This is a very useful property because Changing B parent means changing B |
29 This is a very useful property because Changing B parent means |
31 content too. This require the creation of **another** changeset which is a good |
30 changing B content too. This requires the creation of **another** |
32 semantic. |
31 changeset, which is semantically good. |
33 |
32 |
34 :: |
33 :: |
35 |
34 |
36 Schema base, A, B and B' |
35 Schema base, A, B and B' |
37 |
36 |
38 To avoid duplication, the older changeset is usually discarded from accessible |
37 To avoid duplication, the older changeset is usually discarded from accessible |
39 history. I'm calling them *obsolete* changesets. |
38 history. I'm calling them *obsolete* changesets. |
40 |
39 |
41 |
40 |
42 But rewriting a changeset with children does not changes children parent! And |
41 But rewriting a changeset with children does not change these |
43 because children of the rewritten changeset still **depends** on the older |
42 children's parent! And because children of the rewritten changeset |
44 "dead" version of the changeset with can not get ride of this dead version. |
43 still **depend** on the older "dead" version of the changeset with |
|
44 can not get rid of this dead version. |
45 |
45 |
46 :: |
46 :: |
47 |
47 |
48 Schema base, A and A' and B. |
48 Schema base, A and A' and B. |
49 |
49 |
50 I'm calling those children **unstable** because they are based one a dead |
50 I'm calling these children **unstable** because they are based on a |
51 changeset and prevent people to get ride of it. |
51 dead changeset and prevent people to get rid of it. |
52 |
52 |
53 This instability is an **unavoidable consequence** of the strict dependency of |
53 This instability is an **unavoidable consequence** of the strict dependency of |
54 changeset. History Rewriting history alway need to take it in account and |
54 changeset. History Rewriting history alway need to take it in account and |
55 provide a way to rewrite the descendant on the new changeset to avoid |
55 provide a way to rewrite the descendant on the new changeset to avoid |
56 coexistence of the old and new version of a rewritten changeset.. |
56 coexistence of the old and new version of a rewritten changeset. |
57 |
57 |
58 |
58 |
59 Everybody is working around the issue |
59 Everybody is working around the issue |
60 ------------------------------------------------ |
60 ------------------------------------------------ |
61 |
61 |
65 |
65 |
66 |
66 |
67 Rewriting all at once |
67 Rewriting all at once |
68 `````````````````````````` |
68 `````````````````````````` |
69 |
69 |
70 The simplest way to avoid instability is to ensure rewriting operation always |
70 The simplest way to avoid instability is to ensure rewriting |
71 ends in a stable situation. This is achieve by rewriting all impacted changeset |
71 operations always end in a stable situation. This is achieved by |
72 at the same time. |
72 rewriting all affected changesets at the same time. |
73 |
73 |
74 Rewriting all descendants at the same time than the rewritted of a changeset. |
74 Rewriting all descendants at the same time when rewriting a changeset. |
75 |
75 |
76 :: |
76 :: |
77 |
77 |
78 Schema! |
78 Schema! |
79 |
79 |
80 Several Mercurial commands apply it: rebase, collapse, histedit. Mercurial also |
80 Several Mercurial commands apply it: rebase, collapse, histedit. |
81 refuse to amend changeset with descendant. The git branch design enforce such |
81 Mercurial also refuses to amend changeset with descendant. The git |
82 approach in git too. |
82 branch design enforces such approach in git too. |
83 |
83 |
84 |
84 |
85 However, DVCS are **Distributed**. This means that you do not control what |
85 However, DVCS are **Distributed**. This means that you do not control what |
86 happen outside your repository. Once a changeset have been exchanged *outside*, |
86 happen outside your repository. Once a changeset have been exchanged *outside*, |
87 there is no way to be sure it does not have descendants somewhere else. |
87 there is no way to be sure it does not have descendants somewhere else. |
89 the risk of instability.** |
89 the risk of instability.** |
90 |
90 |
91 Do not rewrite exchanged changeset |
91 Do not rewrite exchanged changeset |
92 ``````````````````````````````````` |
92 ``````````````````````````````````` |
93 |
93 |
94 To work around the issue above, mercurial introduced phases that prevent you to |
94 To work around the issue above, Mercurial introduced phases, which |
95 rewrite shared changeset and ensure other can't pull certain changeset from you. |
95 prevent you from rewriting shared changesets and ensure others can't |
96 But this is a very frustrating limitation that prevent you to efficiently share, |
96 pull certain changesets from you. But this is a very frustrating |
97 review and collaborate on mutable changeset. |
97 limitation that prevents you to efficiently sharing, reviewing and |
98 |
98 collaborating on mutable changesets. |
99 Git world use another approach to prevent instability. By convention only a |
99 |
100 single developper works on a changeset contained in a named branch. But once |
100 In the Git world, they use another approach to prevent instability. By |
101 again this is a huge blocker for collaborating. Moreover clueless people |
101 convention only a single developper works on a changeset contained in |
102 **will** mess up social convention soon or later. |
102 a named branch. But once again this is a huge blocker for |
|
103 collaborating. Moreover clueless people **will** mess up social |
|
104 convention soon or later. |
103 |
105 |
104 |
106 |
105 Loose the DAG robustness |
107 Loose the DAG robustness |
106 ```````````````````````````` |
108 ```````````````````````````` |
107 |
109 |
108 The other approach use in Mercurial is to keep the mutable part of the history |
110 The other approach in Mercurial is to keep the mutable part of the |
109 outside the DVCS constraint. This is the MQ approach of sticking a quilt queue |
111 history outside the DVCS constraint. This is the MQ approach of |
110 over Mercurial. |
112 sticking a quilt queue over Mercurial. |
111 |
113 |
112 This allow much more flexible workflow but two major feature are lost in the |
114 This allow much more flexible workflow but two major feature are lost in the |
113 process: |
115 process: |
114 |
116 |
115 :Graceful merge: MQ use plain-patch to store changeset content and patch have |
117 :Graceful merge: MQ use plain-patch to store changeset content and patch have |
117 becomes very painful when context changes. |
119 becomes very painful when context changes. |
118 |
120 |
119 :easy branching: A quilt queue is by definition a linear queue. Increasing risk |
121 :easy branching: A quilt queue is by definition a linear queue. Increasing risk |
120 of conflict |
122 of conflict |
121 |
123 |
122 It is possible to collaborate over versioned mq! But you are going ahead a lot |
124 It is possible to collaborate over versioned mq! But you are going to |
123 of troubles. |
125 have a lot of troubles. |
124 |
126 |
125 .. Ignore conflicts |
127 Ignore conflicts |
126 .. ``````````````````````````````````` |
128 ``````````````````````````````````` |
127 .. |
129 |
128 .. Another ignored issue is conflicting rewritting of the same changeset. If a |
130 Another ignored issue is a conflicting rewrite of the same changeset. |
129 .. changeset is rewritten two times we have two newer version, duplicated history |
131 If a changeset is rewritten two times we have two newer versions, |
130 .. complicate to merge. |
132 and duplicated history is complicated to merge. |
131 .. |
133 |
132 .. Mercurial work around by |
134 Mercurial work around by |
133 .. |
135 |
134 .. The "One set of mutable changset == One developper" mantra is also a way to work |
136 The "One set of mutable changset == One developer" mantra is also a way to work |
135 .. around conflicting rewritting of changeset. If two different people are able to |
137 around conflicting rewriting of changeset. If two different people are able to |
136 .. |
138 |
137 .. The git branch model allow to overwrite changeset version by another one. But it |
139 The git branch model allow to overwrite changeset version by another |
138 .. does not care about divergent version. It is the equilent of "common ftp" source |
140 one, but it does not care about divergent version. It is the equivalent |
139 .. management for changeset. |
141 of "common ftp" source management for changesets. |
140 |
142 |
141 Facing The Danger Once And For All |
143 Facing The Danger Once And For All |
142 ------------------------------------------------ |
144 ------------------------------------------------ |
143 |
145 |
144 Above we saw that, the more effort you put to avoid instability, the more option |
146 Above we saw that, the more effort you put to avoid instability, the more option |
146 will never show up! |
148 will never show up! |
147 |
149 |
148 Obsolete marker can handle the job |
150 Obsolete marker can handle the job |
149 ``````````````````````````````````` |
151 ``````````````````````````````````` |
150 |
152 |
151 It is time to provide a full featured solution to deal with instability and to |
153 It is time to provide a full featured solution to deal with |
152 stop working around the issue! This is why I developing a new feature for |
154 instability and to stop working around the issue! This is why I |
153 mercurial called "Obsolete markers". Obsolete markers have two key properties: |
155 developing a new feature for mercurial called "Obsolete markers". |
154 |
156 Obsolete markers have two key properties: |
155 |
157 |
156 * Any "old" changeset we want to get ride of is **explicitly** marked as "obsolete" |
158 |
157 by history rewriting operation. |
159 * Any "old" changeset we want to get ride of is **explicitly** marked |
|
160 as "obsolete" by history rewriting operation. |
158 |
161 |
159 By explicitly marking the obsolete part of the history, we will be able to |
162 By explicitly marking the obsolete part of the history, we will be able to |
160 easily detect instability situation. |
163 easily detect instability situation. |
161 |
164 |
162 * Relations between old and new version of changesets are tracked by obsolete |
165 * Relations between old and new version of changesets are tracked by obsolete |