# # 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-ffqrebase finish # git-ffqrebase status [BRANCH] # # refs/ffqrebase-prev/BRANCH BRANCH may be refs/...; if not it means # refs/ffqrebase-base/BRANCH refs/heads/BRANCH # zero, one, or both of these may exist # # 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] 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) 2. git-debrebase stitch [--noop-ok] 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/ffrebase/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..HEAD: 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.