chiark / gitweb /
git-debrebase: bomb on totally ambiguous pseudomerges
[dgit.git] / NOTES.git-debrebase
1 TODO
2    more tests, see "todo" in gdr-editw
3    reference docs
4       git-debrebase(5)   data model
5       git-debrebase(1)   command line
6    tutorial
7       dgit-maint-debrebase(7)
8       someone should set branch.<name>.mergeOptions to include --ff-only ?
9
10    clean up remains of NOTES and README
11
12    arrange for dgit to automatically stitch on push
13
14 #    git-ffqrebase start [BASE]
15 #                # records previous HEAD so it can be overwritten
16 #                # records base for future git-ffqrebase
17 #    git-ffqrebase set-base BASE
18 #    git-ffqrebase <git-rebase options>
19 #    git-ffqrebase finish
20 #    git-ffqrebase status [BRANCH]
21 #
22 #  refs/ffq-prev/REF    relates to refs/REF
23 #
24 # git-debrebase without start, if already started, is willing
25 # to strip pseudomerges provided that they overwrite exactly
26 # the previous HEAD
27 #  xxxx is this right ?  what matters is have we pushed
28 #    I think in fact the right answer is:
29 #       git-debrebase always strips out pseudomerges from its branch
30 #       a pseudomerge is put in at the time we want to push
31 #       at that time, we make a pseudomerge of the remote tracking
32 #           branch (if raw git) or the dgit view (if dgit)
33 #       for raw git git-ffqrebase, do want preciseley to record
34 #           value of remote tracking branch or our branch, on start, so we
35 #           overwrite only things we intend to
36 #  the previous pseudomerge    check for tags and remote branches ?
37
38
39 =========
40
41 special commit tags
42 overall format
43   [git-debrebase[ COMMIT-TYPE [ ARGS...]]: PROSE, MORE PROSE]
44
45 [git-debrebase: split mixed commit, debian part]
46 [git-debrebase: split mixed commit, upstream-part]
47 [git-debrebase: convert dgit import, debian changes]
48 [git-debrebase breakwater: convert dgit import, upstream changes]
49
50 [git-debrebase upstream-combine . PIECE[ PIECE...]: new upstream]
51 [git-debrebase breakwater: new upstream NEW-UPSTREAM-VERSION, merge]
52 [git-debrebase: new upstream NEW-UPSTREAM-VERSION, changelog]
53
54 [git-debrebase convert-from-gbp: drop patches]
55 [git-debrebase breakwater: declare upstream]
56 [git-debrebase pseudomerge: stitch]
57
58 [git-debrebase convert-to-gbp: commit patches]
59
60 m{^\[git-debrebase (?:\w*-)?upstream combine \.((?: $extra_orig_namepart_re)+)\]}
61
62 Every breakwater commit must be a merge.  In principle, this is not
63 necessary.  After all, we are relying on the
64     [git-debrebase breakwater: ...]
65 commit message annotation in "declare" breakwater merges (which
66 do not have any upstream changes), to distinguish those breakwater
67 merges from ordinary pseudomerges (which we might just try to strip).
68
69 However, the user is going to be doing git-rebase a lot.  We really
70 don't want them to rewrite a breakwater base commit.  git-rebase
71 trips up on merges, so that is a useful safety catch.
72
73
74 =========
75
76 workflow
77
78   git-debrebase blah [implies start]       strips pseudomerge(s)
79
80   commit / git-debrebase / etc.
81
82   dgit --damp-run push
83       hook: call git-debrebase prep-push   adds new pm ? passes --overwrite ?
84                                            dgit push does not update remote
85
86   commit / git-debrebase / etc.            strips pm(s) including last one
87
88   dgit push
89       hook: call git-debrebase prep-push   adds new pm ? passes --overwrite ?
90                                            dgit push DOES update remote
91
92   commit / git-debrebase / etc.            strips last pm, but arranges
93                                            that remade pm will incorporate it
94
95 Aha!
96
97 When we strip a pm, we need to maybe record it (or something) as the
98 new start point.
99
100 We do this if the pm is contained within the output branch.
101
102 Actually this is not special to PMs.
103
104 We need to record a new to-be-overwritten commit
105    merge-base( our branch tip, relevant remote )
106
107 If this is not a descendant of the relevant remote, then we are going
108 to have a problem when we push so issue a warning or fail.
109
110
111
112 How about
113
114   git-debrebase start or git-debrebase [continue]
115
116     with no recorded will-overwrite
117
118         putative will-overwrite is 
119             one model:
120                 our current tip
121                 obviously it is safe to say we will overwrite this
122                 we do not need to worry about whether this will
123                     overwrite not-included changes in the remote
124                     because either the will-overwrite is not
125                     ff from the remote (in which case later failure,
126                     see below); or the will-overwrite _is_ ff
127                     from the remote ie our tip is later than the
128                     remote and includes all of its changes
129
130                 this model tends to keep ad-hoc commits made on our
131                 tip branch before we did rebase start, in the
132                 `interchange view' and also in the rebase stack.
133
134             other model:
135                 merge-base( current remote, current tip )
136
137                 it is safe to overwrite current tip, by the
138                 argument above
139
140                 it is always safe to rewind will-overwrite: all
141                 that does is overwrite _less_ stuff
142
143                 this is the earliest overwrite we can make that
144                     will be pushable to the remote
145
146                 in practical terms this can only be ff from the
147                 current remote if it is equal to the current remote;
148                 so what we are actually checking below is that our tip
149                 is ff from the remote.  This ought to be true before
150                 the first of our rebases.
151
152                 this model tends to rewind and rebase ad-hoc commits
153                 made on our tip branch before we did rebase start,
154                 this is better
155
156         in any case putative will-overwrite must be ff from remote.
157         Otherwise when we push it will not be ff, even though we have
158         made pseudomerge to overwrite will-overwrite.  So if we spot
159         this, report an error.
160
161     with a recorded will-overwrite
162
163         we may need to advance will-overwrite, to allow us to generate
164         future pseudomerges that will be pushable
165
166         advancing will-overwrite is dangerous, since it might
167         effectively cancel the commits that will-ovewrite is advanced
168         over.
169
170         we advance it to merge-base( current remote, current tip )
171         if possible (see above), - ie to current remote, subject
172         to the condition that that is an ancestor of current tip
173
174 In each case we can strip pseudomerges freely, as needed.  We do not
175 want to record what pseudomerges we strip, because whether we need to
176 keep them depends (only) on whether they have been pushed.
177
178 Is that actually true ?  What if the user actually _wanted_ to keep
179 the pseudomerge despite not having pushed it ?
180
181 In that case we need to advance will-overwrite past it.  We could
182 provide an explicit command to do this: it would advance
183 will-overwrite to the current tip (see rules above, which show that
184 this is OK).  Or maybe to the last pseudomerge on the current tip,
185 so that the overall result will be series of pseudomerges.
186
187 ========================================
188
189 So, pm handling specifics:
190
191 strategy is to avoid making needless pseudomerges
192 pseudomerges that exist will be preserved
193 (by being included in will-overwrite)
194
195 This is good because the presence of a pseudomerge means we know we
196 want to keep it; and that allows explicit control over history detail
197 level.
198
199 It does mean we must avoid making the pseudomerges unnecessarily.
200 They should be made just before (ideally, part of) dgit push.
201
202 1. git-debrebase [-i etc.]
203
204      should:
205         check for will-overwrite
206         if is already a will-overwrite, fine, do no more
207         if not:
208
209         check our origin branch exists and we are ff from it
210         if not fail
211
212         check our other might-be-pushed to branches
213         check we are ff from them
214         if not fail
215
216         set will-overwrite to something which is ff from
217           all above branches
218
219         we use our tip, as discussed above
220         (optionally, can use some other commit which is ff
221          from all of the above, eg one of them)
222
223 N. git-debrebase [--noop-ok] record-ffq-prev
224
225      does what is described above
226
227 2. git-debrebase [--noop-ok] stitch
228
229     makes pseudomerge with will-overwrite
230     deletes will-overwrite
231
232     we will teach dgit to do
233        git-debrebase stitch
234
235 3. git-debrebase push
236
237     like git push only does stitch first
238     ??? command line parsing!
239
240 4. git-debrebase release
241
242     stiches, finalises changelog, signs tags, pushes everything
243     for the future, when there is some automatic builder
244
245 will-overwrite for each ref
246     refs/heads/FOO
247 is
248     refs/ffq-prev/FOO
249
250 ========================================
251
252 import from gbp
253
254 [ all this is done now:
255  inputs:
256    current HEAD (patches-unapplied),
257      this is going to be the base of the old breakwater
258    nominated upstream
259
260  checks:
261    HEAD:<upstream> = upstream:<upstream>
262    upstream..HEAD:<upstream> is empty (overrideable)
263    upstremm:debian is empty (overrideable)
264
265  procedure:
266    construct
267      run gbp pq import to generate pq branch
268      new breakwater is
269        old HEAD
270        commit to remove d/patches
271        breakwater pseudomerge with upstream
272        "rebase" of pq branch, each commit with d/patches stripped
273 ]
274
275 what about dgit view branch ?
276 ideally, would make pseudomerge over dgit view
277 would need to check that dgit view is actually dgit view of
278   ond of our ancestors
279 failing that first push will need --overwrite
280
281 ========================================
282
283 divergence, merges:
284
285 same problem
286  if merge, look at branches before merge
287  generate new combined branch
288  pseudomerge to overwrite merge
289
290 current avaiable strategies:
291
292  maybe launder foreign branch
293
294  if foreign branch is nmuish, can rebase it onto ours
295
296  could merge breakwaters (use analyse to find them)
297  merge breakwaters (assuming same upstream)
298  manually construct new patch queue by inspection of
299   the other two patch queues
300
301  instead of manually constructing patch queue, could use
302   gbp pq export and git merge the patch queues
303   (ie work with interdiffs)
304
305  if upstreams are different and one is ahead
306   simply treat that as "ours" and
307   do the work to import changes from the other
308
309  if upstreams have diverged, can
310   resolve somehow to make new upstream
311   do new-upstream on each branch separately
312   now reduced to previously "solved" problem
313
314  in future, auto patch queue merge algorithm
315   determine next patch to apply
316   there are three versions o..O, l..L, r..R
317   we have already constructed m (previous patch or merged breakwater)
318   try using vector calculus in the implied cube and compute
319    multiple ways to check consistency ?