Mercurial > evolve
comparison docs/instability.rst @ 243:2f68c708e10b
fix typo in file name
author | Pierre-Yves.David@ens-lyon.org |
---|---|
date | Fri, 11 May 2012 11:52:15 +0200 |
parents | docs/unstability.rst@ab9ee2eba21e |
children | b398e9c2dbd1 |
comparison
equal
deleted
inserted
replaced
242:1fc4299ca8e2 | 243:2f68c708e10b |
---|---|
1 | |
2 ----------------------------------- | |
3 The instability Principle | |
4 ----------------------------------- | |
5 | |
6 | |
7 | |
8 An intrinsic contradiction | |
9 ----------------------------------- | |
10 | |
11 XXX starts by talking about getting ride of changeset. | |
12 | |
13 DVCS bring two new major concepts to the Version Control Scene: | |
14 | |
15 * History is organized as a robust DAG, | |
16 * History can be rewritten. | |
17 | |
18 | |
19 However, the two concepts are in contradiction: | |
20 | |
21 To achieve a robust history, three key elements are gathered in *changeset*: | |
22 | |
23 * Full snapshot of the versioned content, | |
24 * 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. | |
26 | |
27 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. | |
29 | |
30 This is a very useful property because Changing B parent means changing B | |
31 content too. This require the creation of **another** changeset which is a good | |
32 semantic. | |
33 | |
34 :: | |
35 | |
36 Schema base, A, B and B' | |
37 | |
38 To avoid duplication, the older changeset is usually discarded from accessible | |
39 history. I'm calling them *obsolete* changesets. | |
40 | |
41 | |
42 But rewriting a changeset with children does not changes children parent! And | |
43 because children of the rewritten changeset still **depends** on the older | |
44 "dead" version of the changeset with can not get ride of this dead version. | |
45 | |
46 :: | |
47 | |
48 Schema base, A and A' and B. | |
49 | |
50 I'm calling those children **unstable** because they are based one a dead | |
51 changeset and prevent people to get ride of it. | |
52 | |
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 | |
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.. | |
57 | |
58 | |
59 Everybody is working around the issue | |
60 ------------------------------------------------ | |
61 | |
62 I'm not claiming that rewriting history is impossible. People are successfully | |
63 doing for years. However they all need to work around *instability*. Several | |
64 work around strategy exists. | |
65 | |
66 | |
67 Rewriting all at once | |
68 `````````````````````````` | |
69 | |
70 The simplest way to avoid instability is to ensure rewriting operation always | |
71 ends in a stable situation. This is achieve by rewriting all impacted changeset | |
72 at the same time. | |
73 | |
74 Rewriting all descendants at the same time than the rewritted of a changeset. | |
75 | |
76 :: | |
77 | |
78 Schema! | |
79 | |
80 Several Mercurial commands apply it: rebase, collapse, histedit. Mercurial also | |
81 refuse to amend changeset with descendant. The git branch design enforce such | |
82 approach in git too. | |
83 | |
84 | |
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*, | |
87 there is no way to be sure it does not have descendants somewhere else. | |
88 Therefore **if you rewrite changeset that exists elsewhere, you can't eradicate | |
89 the risk of instability.** | |
90 | |
91 Do not rewrite exchanged changeset | |
92 ``````````````````````````````````` | |
93 | |
94 To work around the issue above, mercurial introduced phases that prevent you to | |
95 rewrite shared changeset and ensure other can't pull certain changeset from you. | |
96 But this is a very frustrating limitation that prevent you to efficiently share, | |
97 review and collaborate on mutable changeset. | |
98 | |
99 Git world use another approach to prevent instability. By convention only a | |
100 single developper works on a changeset contained in a named branch. But once | |
101 again this is a huge blocker for collaborating. Moreover clueless people | |
102 **will** mess up social convention soon or later. | |
103 | |
104 | |
105 Loose the DAG robustness | |
106 ```````````````````````````` | |
107 | |
108 The other approach use in Mercurial is to keep the mutable part of the history | |
109 outside the DVCS constraint. This is the MQ approach of sticking a quilt queue | |
110 over Mercurial. | |
111 | |
112 This allow much more flexible workflow but two major feature are lost in the | |
113 process: | |
114 | |
115 :Graceful merge: MQ use plain-patch to store changeset content and patch have | |
116 trouble to apply in changing context. Applying your queue | |
117 becomes very painful when context changes. | |
118 | |
119 :easy branching: A quilt queue is by definition a linear queue. Increasing risk | |
120 of conflict | |
121 | |
122 It is possible to collaborate over versioned mq! But you are going ahead a lot | |
123 of troubles. | |
124 | |
125 .. Ignore conflicts | |
126 .. ``````````````````````````````````` | |
127 .. | |
128 .. Another ignored issue is conflicting rewritting of the same changeset. If a | |
129 .. changeset is rewritten two times we have two newer version, duplicated history | |
130 .. complicate to merge. | |
131 .. | |
132 .. Mercurial work around by | |
133 .. | |
134 .. The "One set of mutable changset == One developper" mantra is also a way to work | |
135 .. around conflicting rewritting of changeset. If two different people are able to | |
136 .. | |
137 .. The git branch model allow to overwrite changeset version by another one. But it | |
138 .. does not care about divergent version. It is the equilent of "common ftp" source | |
139 .. management for changeset. | |
140 | |
141 Facing The Danger Once And For All | |
142 ------------------------------------------------ | |
143 | |
144 Above we saw that, the more effort you put to avoid instability, the more option | |
145 you deny. And even most restrictive work flow can't guarantee that instability | |
146 will never show up! | |
147 | |
148 Obsolete marker can handle the job | |
149 ``````````````````````````````````` | |
150 | |
151 It is time to provide a full featured solution to deal with instability and to | |
152 stop working around the issue! This is why I developing a new feature for | |
153 mercurial called "Obsolete markers". Obsolete markers have two key properties: | |
154 | |
155 | |
156 * Any "old" changeset we want to get ride of is **explicitly** marked as "obsolete" | |
157 by history rewriting operation. | |
158 | |
159 By explicitly marking the obsolete part of the history, we will be able to | |
160 easily detect instability situation. | |
161 | |
162 * Relations between old and new version of changesets are tracked by obsolete | |
163 markers. | |
164 | |
165 By Storing a meta-history of changeset evolution we are able to easily resolve | |
166 instability and edition conflict [#]_ . | |
167 | |
168 .. [#] edition conflict is another major obstable to collaboration. See the | |
169 section dedicated to obsolete marker for details. | |
170 | |
171 Improves robustness == improves simplicity | |
172 ```````````````````````````````````````````````` | |
173 | |
174 This proposal should **first** be seen as a safety measure. | |
175 | |
176 It allow to detect instability as soon as possible | |
177 | |
178 :: | |
179 | |
180 $ hg pull | |
181 added 3 changeset | |
182 +2 unstable changeset | |
183 (do you want "hg stabilize" ?) | |
184 working directory parent is obsolete! | |
185 $ hg push | |
186 outgoing unstable changesets | |
187 (use "hg stabilize" or force the push) | |
188 | |
189 And should not not encourage people to create unstability | |
190 | |
191 :: | |
192 | |
193 $ hg up 42 | |
194 $ hg commit --amend | |
195 changeset have descendant. | |
196 $ hg commit --amend -f | |
197 +5 unstable changeset | |
198 | |
199 $ hg rebase -D --rev 40::44 | |
200 rebasing already obsolete changeset 42:AAA will conflict with newer version 48:BBB | |
201 | |
202 While allowing powerful feature | |
203 ```````````````````````````````````````````````` | |
204 | |
205 | |
206 * Help to automatically solve instability. | |
207 | |
208 * "kill" changeset remotely. | |
209 | |
210 * track resulting changeset when submitting patch//pull request. | |
211 | |
212 * Focus on what you do: | |
213 | |
214 I do not like the "all at once" model of history rewriting. I'm comfortable | |
215 with unstability and obsolete marker offer all the tool to safely create and | |
216 handle unstability locally. | |
217 | |
218 |