54 |
58 |
55 |
59 |
56 Everybody is working around the issue |
60 Everybody is working around the issue |
57 ------------------------------------------------ |
61 ------------------------------------------------ |
58 |
62 |
59 I'm not claiming that rewriting history is impossible. People are |
63 I'm not claiming that rewriting history is impossible. People are successfully |
|
64 doing for years. However they all need to work around this unstability: |
60 |
65 |
61 |
66 |
62 |
67 |
63 Rewriting all at once |
68 Rewriting all at once |
64 `````````````````````````` |
69 `````````````````````````` |
65 |
70 |
66 |
71 The simplest way to avoid unstability is to ensure rewritting operation always |
67 |
72 ends in a stable situation. This is achieve by rewriting all impacted changeset |
68 stable situation to stable situation |
73 at the same time. |
69 |
74 |
70 Distributed means that you do not control what happen outside your repository: |
75 rewritting all descendants at the same time that the rewritting of a changeset. |
71 |
76 |
72 |
77 :: |
73 * phase. |
78 |
74 * overwrite. |
79 Schema! |
75 |
80 |
76 |
81 Several Mercurial command follow this idea: rebase, collapse, histedit. |
77 Boiler Plate |
82 Mercurial also refuse to amend changeset with descendant. The git brnach design enforce such 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 you can't be sure of it's descendant. Therefore** if you rewritte changeset that |
|
88 exists elsewere, you can't erradicate the risk of unstability.** |
|
89 |
|
90 Do not rewrite exchanged changeset |
|
91 ``````````````````````````````````` |
|
92 |
|
93 To work around this issue mercurial introduced phases that prevent you to |
|
94 rewrite exchanged changeset and ensure other can't pull certain changeset from |
|
95 you. But this is a very frustrating limitation that prevent you to |
|
96 efficiently share, review and collaborate on mutable changeset. |
|
97 |
|
98 Git world use another approach to prevent unstability. |
|
99 By convention only a single developper works on a changeset contained in a named |
|
100 branch. But once again this is a huge blocker for collaborating and clueless people |
|
101 **will** mess up social convention soon or later. |
78 |
102 |
79 |
103 |
80 Loose the DAG robustness |
104 Loose the DAG robustness |
81 ```````````````````````````` |
105 ```````````````````````````` |
82 |
106 |
83 The other approach is |
107 The other approach use in Mercurial is to keep the mutable part of the history |
84 |
108 outside the DVCS constraint. This is the MQ approach of sticking a quilt queue |
85 mq -- quilt |
109 over Mercurial. |
86 |
110 |
87 Conflict too much conflict |
111 This allow much more flexible workflow two major feature are lost in the |
88 |
112 process: |
89 Linear |
113 |
90 |
114 * Graceful merge. MQ use plain-patch to store changeset content and patch have |
91 |
115 trouble to apply in changing context. applying you queu can because very |
92 Deny a lot of option |
116 painful if context changeset. |
93 ```````````````````````````` |
117 |
94 |
118 * easy branching. A quilt queue is by definition a linear queue. |
95 |
119 |
96 |
120 It is possible to collaborate over versionned mq! But you are going ahead a lot |
97 [] rewrite |
121 of trouble. |
98 |
122 |
99 [] exchange |
123 .. Ignore conflicts |
100 |
124 .. ``````````````````````````````````` |
101 [] collaborate |
125 .. |
102 |
126 .. Another ignored issue is conflicting rewritting of the same changeset. If a |
|
127 .. changeset is rewritten two times we have two newer version, duplicated history |
|
128 .. complicate to merge. |
|
129 .. |
|
130 .. Mercurial work around by |
|
131 .. |
|
132 .. The "One set of mutable changset == One developper" mantra is also a way to work |
|
133 .. around conflicting rewritting of changeset. If two different people are able to |
|
134 .. |
|
135 .. The git branch model allow to overwrite changeset version by another one. But it |
|
136 .. does not care about divergent version. It is the equilent of "common ftp" source |
|
137 .. management for changeset. |
103 |
138 |
104 Facing The Danger Once And For All |
139 Facing The Danger Once And For All |
105 ------------------------------------------------ |
140 ------------------------------------------------ |
106 The more effort you put to avoid instability, the more option you deny. And even |
141 The more effort you put to avoid instability, the more option you deny. And even |
107 most restrictive work flow can't garantee that instability will never show up! |
142 most restrictive work flow can't garantee that instability will never show up! |
108 |
143 |
|
144 Obsolete marker can handle the job |
|
145 ``````````````````````````````````` |
|
146 |
109 It is time to provide a full featured solution to deal with instability and to |
147 It is time to provide a full featured solution to deal with instability and to |
110 stop working around the issue! This is why I developing a new feature for |
148 stop working around the issue! This is why I developing a new feature for |
111 mercurial called "Obsolete marker". |
149 mercurial called "Obsolete marker". Obsolete marker have two key property: |
112 |
150 |
113 |
151 |
114 * Any changeset is we want to get ride of is **explicitly** marked as "obsolete" |
152 * Any changeset is we want to get ride of is **explicitly** marked as "obsolete" |
115 by history rewritting operation.. |
153 by history rewritting operation. |
|
154 |
|
155 By explicitly marking the obsolete part of the history, we will be able to |
|
156 easily detect appearance of unstability. |
116 |
157 |
117 * Relations between old and new version of changesets are tracked by Obsolete |
158 * Relations between old and new version of changesets are tracked by Obsolete |
118 markers. |
159 markers. |
119 |
160 |
120 By explicitly marking the obsolete part of the history, we will be able to |
161 By Storing a meta-history of changeset evolution we are able to easily resolve |
121 easily detect appearance of unstability. By Storing a meta-history of changeset |
162 instability and edition conflict [#]_ . |
122 evolution we are able to easily resolve instability and edition conflict. |
163 |
123 |
164 .. [#] edition conflict is another major obstable to collaboration. See the |
124 |
165 section dedicated to obsolete marker for details. |
125 |
166 |
126 |
167 Improving robusness improves simplicity |
127 No instability is still a bad situation. |
168 ```````````````````````````````````````````````` |
128 No instability is still a bad situation that should be avoided. |
169 |
|
170 This proposal should **first** be seen as a safety measure. |
|
171 |
|
172 It allow to detect unstability as soon as possible |
|
173 |
|
174 :: |
|
175 $ hg pull |
|
176 added 3 changeset |
|
177 +2 unstable changeset |
|
178 (do you want "hg stabilize" ?) |
|
179 working directory parent is obsolete! |
|
180 $ hg push |
|
181 outgoing unstable changesets |
|
182 (use "hg stabilize" or force the push) |
|
183 |
|
184 And should not not encourage people to create unstability |
|
185 |
|
186 :: |
|
187 $ hg up 42 |
|
188 $ hg commit --amend |
|
189 changeset have descendant. |
|
190 $ hg commit --amend -f |
|
191 +5 unstable changeset |
|
192 |
|
193 $ hg rebase -D --rev 40::44 |
|
194 rebasing already obsolete changeset 42:AAA will conflict with newer version 48:BBB |
|
195 |
|
196 While allowing powerful feature |
|
197 ```````````````````````````````````````````````` |
|
198 |
|
199 * "kill" changeset remotely. |
|
200 |
|
201 * track resulting changeset when submitting patch//pull request. |
|
202 |
|
203 * Focus on what you do: |
|
204 |
|
205 I do not like the "all at once" model of history rewriting. I'm confortable |
|
206 with unstability and obsolete marker offer all the tool to safely create and |
|
207 handle unstability locally. |
|
208 |
|
209 |