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