git rebasejust doesn't cut it for this. A while back I wrote
git rebase-treethat would rebase a whole branched tree from one root to another (bringing all the branches along with), but it had a black eye in conflict handling, requiring a prompt for "continue/skip/abort". So I would need to open up a second terminal to
git statusand resolve the conflict, etc (or more typically, run
git conflictsin emacs). I had been meaning to redo
git rebase-treewith its own
--continueflag, but my experience with another custom function (
git diff-mail, which I use at work to prevent the changelist mailer from counting all the earlier changes that were already counted in a previous changelist) taught me that this can cause problems, as I often needed to
git rebase --continue; diff-mail --continue, plus
--abortoften got confusing and sometimes actually clobbered my real changes (fortunately they've been easy to reconstruct so far). But it occurred to me that
git rebasealready has a queue, and with some clever manipulation, I can make it do what I want.
This function takes a list of branches, a commit to rebase them onto, and optionally a commit to rebase them from (in case they're already on top of the destination). It sets up an interactive rebase session but completely ignores the plan
gitprepares, instead using its own plan that includes a few additional commands in the rebase plan.
# Extended Commands: # !, exec! = mandatory command (the rest of the line), reinserted on failure # b, branch = sets the named branch to the current commit # (, push = pushes the current commit onto the stack # ), pop = pops the current commit from the stackThe initial plan is effectively equivalent to
git rebase-tree(though slightly more permissive). But with some quick edits (adding or removing parentheses, for instance) a tree of single-commit branches all off the same base can be instantly converted into a chain of dependent branches, and vice versa.
Once the initial plan is complete, it's ordinary
git rebasethe rest of the way, so when conflicts arise, it's back to the normal
git rebase --continue(or
--abort) workflow to handle them! Aborting happens for free. Moreover, no branches are moved until all commits have been successful rebased, so aborting before that brings everything exactly back to where it started. Finally, if you don't want it to be interactive, just call it with
::(which I alias to