summaryrefslogtreecommitdiff
path: root/NOTES.git-debrebase
blob: 32f9b494869a6665d66d6aa9601d6f908e4e1ac0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
#
#    git-ffqrebase start [BASE]
#                # records previous HEAD so it can be overwritten
#                # records base for future git-ffqrebase
#    git-ffqrebase set-base BASE
#    git-ffqrebase <git-rebase options>
#    git-ffqrebase finish
#    git-ffqrebase status [BRANCH]
#
#  refs/ffq-prev/REF    relates to refs/REF
#
# git-debrebase without start, if already started, is willing
# to strip pseudomerges provided that they overwrite exactly
# the previous HEAD
#  xxxx is this right ?  what matters is have we pushed
#    I think in fact the right answer is:
#       git-debrebase always strips out pseudomerges from its branch
#       a pseudomerge is put in at the time we want to push
#       at that time, we make a pseudomerge of the remote tracking
#           branch (if raw git) or the dgit view (if dgit)
#       for raw git git-ffqrebase, do want preciseley to record
#           value of remote tracking branch or our branch, on start, so we
#           overwrite only things we intend to
#  the previous pseudomerge    check for tags and remote branches ?


=========

special commit tags
overall format
  [git-debrebase[ COMMIT-TYPE [ ARGS...]]: PROSE, MORE PROSE]

[git-debrebase: split mixed commit, debian part]
[git-debrebase: split mixed commit, upstream-part]
[git-debrebase: convert dgit import, debian changes]
[git-debrebase breakwater: convert dgit import, upstream changes]

[git-debrebase upstream-combine . PIECE[ PIECE...]: new upstream]
[git-debrebase breakwater: new upstream NEW-UPSTREAM-VERSION, merge]
[git-debrebase: new upstream NEW-UPSTREAM-VERSION, changelog]

[git-debrebase: gbp2debrebase, drop patches]
[git-debrebase breakwater: declare upstream]
[git-debrebase pseudomerge: stitch]

m{^\[git-debrebase (?:\w*-)?upstream combine \.((?: $extra_orig_namepart_re)+)\]}

Every breakwater commit must be a merge.  In principle, this is not
necessary.  After all, we are relying on the
    [git-debrebase breakwater: ...]
commit message annotation in "declare" breakwater merges (which
do not have any upstream changes), to distinguish those breakwater
merges from ordinary pseudomerges (which we might just try to strip).

However, the user is going to be doing git-rebase a lot.  We really
don't want them to rewrite a breakwater base commit.  git-rebase
trips up on merges, so that is a useful safety catch.


=========

workflow

  git-debrebase blah [implies start]       strips pseudomerge(s)

  commit / git-debrebase / etc.

  dgit --damp-run push
      hook: call git-debrebase prep-push   adds new pm ? passes --overwrite ?
                                           dgit push does not update remote

  commit / git-debrebase / etc.            strips pm(s) including last one

  dgit push
      hook: call git-debrebase prep-push   adds new pm ? passes --overwrite ?
                                           dgit push DOES update remote

  commit / git-debrebase / etc.            strips last pm, but arranges
                                           that remade pm will incorporate it

Aha!

When we strip a pm, we need to maybe record it (or something) as the
new start point.

We do this if the pm is contained within the output branch.

Actually this is not special to PMs.

We need to record a new to-be-overwritten commit
   merge-base( our branch tip, relevant remote )

If this is not a descendant of the relevant remote, then we are going
to have a problem when we push so issue a warning or fail.



How about

  git-debrebase start or git-debrebase [continue]

    with no recorded will-overwrite

        putative will-overwrite is 
            one model:
                our current tip
                obviously it is safe to say we will overwrite this
                we do not need to worry about whether this will
                    overwrite not-included changes in the remote
                    because either the will-overwrite is not
                    ff from the remote (in which case later failure,
                    see below); or the will-overwrite _is_ ff
                    from the remote ie our tip is later than the
                    remote and includes all of its changes

                this model tends to keep ad-hoc commits made on our
                tip branch before we did rebase start, in the
                `interchange view' and also in the rebase stack.

            other model:
                merge-base( current remote, current tip )

                it is safe to overwrite current tip, by the
                argument above

                it is always safe to rewind will-overwrite: all
                that does is overwrite _less_ stuff

                this is the earliest overwrite we can make that
                    will be pushable to the remote

                in practical terms this can only be ff from the
                current remote if it is equal to the current remote;
                so what we are actually checking below is that our tip
                is ff from the remote.  This ought to be true before
                the first of our rebases.

                this model tends to rewind and rebase ad-hoc commits
                made on our tip branch before we did rebase start,
                this is better

        in any case putative will-overwrite must be ff from remote.
        Otherwise when we push it will not be ff, even though we have
        made pseudomerge to overwrite will-overwrite.  So if we spot
        this, report an error.

    with a recorded will-overwrite

        we may need to advance will-overwrite, to allow us to generate
        future pseudomerges that will be pushable

        advancing will-overwrite is dangerous, since it might
        effectively cancel the commits that will-ovewrite is advanced
        over.

        we advance it to merge-base( current remote, current tip )
        if possible (see above), - ie to current remote, subject
        to the condition that that is an ancestor of current tip

In each case we can strip pseudomerges freely, as needed.  We do not
want to record what pseudomerges we strip, because whether we need to
keep them depends (only) on whether they have been pushed.

Is that actually true ?  What if the user actually _wanted_ to keep
the pseudomerge despite not having pushed it ?

In that case we need to advance will-overwrite past it.  We could
provide an explicit command to do this: it would advance
will-overwrite to the current tip (see rules above, which show that
this is OK).  Or maybe to the last pseudomerge on the current tip,
so that the overall result will be series of pseudomerges.

========================================

So, pm handling specifics:

strategy is to avoid making needless pseudomerges
pseudomerges that exist will be preserved
(by being included in will-overwrite)

This is good because the presence of a pseudomerge means we know we
want to keep it; and that allows explicit control over history detail
level.

It does mean we must avoid making the pseudomerges unnecessarily.
They should be made just before (ideally, part of) dgit push.

1. git-debrebase [-i etc.]

     should:
        check for will-overwrite
        if is already a will-overwrite, fine, do no more
        if not:

        check our origin branch exists and we are ff from it
        if not fail

        check our other might-be-pushed to branches
        check we are ff from them
        if not fail

        set will-overwrite to something which is ff from
          all above branches

        we use our tip, as discussed above
        (optionally, can use some other commit which is ff
         from all of the above, eg one of them)

N. git-debrebase [--noop-ok] record-ffq-prev

     does what is described above

2. git-debrebase [--noop-ok] stitch

    makes pseudomerge with will-overwrite
    deletes will-overwrite

    we will teach dgit to do
       git-debrebase stitch

3. git-debrebase push

    like git push only does stitch first
    ??? command line parsing!

4. git-debrebase release

    stiches, finalises changelog, signs tags, pushes everything
    for the future, when there is some automatic builder

will-overwrite for each ref
    refs/heads/FOO
is
    refs/ffq-prev/FOO

========================================

import from gbp

[ all this is done now:
 inputs:
   current HEAD (patches-unapplied),
     this is going to be the base of the old breakwater
   nominated upstream

 checks:
   HEAD:<upstream> = upstream:<upstream>
   upstream..HEAD:<upstream> is empty (overrideable)
   upstremm:debian is empty (overrideable)

 procedure:
   construct
     run gbp pq import to generate pq branch
     new breakwater is
       old HEAD
       commit to remove d/patches
       breakwater pseudomerge with upstream
       "rebase" of pq branch, each commit with d/patches stripped
]

what about dgit view branch ?
ideally, would make pseudomerge over dgit view
would need to check that dgit view is actually dgit view of
  ond of our ancestors
failing that first push will need --overwrite

should this be called import or gbp2debrebase as it is now ?
gbp uses "import" oddly but I'm tempted to use it normally here.