The New Git Option For Rebasing Multiple Branches At Once
A version of this article appeared on viget.com
In version Git v2.38 (released Oct 3 2022),
git-rebase learned a new
--update-refs option. With
--update-refs, rebasing will “Automatically force-update any branches that point to commits that are being rebased” (docs).
A standard rebase results in up to one branch pointing at a different commit than it did before
B — for example with
—or the convenient form
git rebase main feature— results in
Not much room for improvement there. But what if there are intermediate branches between the specified branch’s fork point (
A in the above example) and the branch you’re rebasing?
Here’s what happens in a multi-branch situation with a standard rebase:
git-rebase will also update all branches which start out pointing to commits that then get rebased. Here’s the difference:
I’m excited about this enhancement because of two scenarios I run into:
The first real-life scenario is during development. I sometimes build several branches upon each other. Maybe they are for dependent features; maybe it’s one large feature, and I’m splitting it up to make code review more feasible.
(I’m keeping each branch to only one commit for legibility.)
I’m working at
third-requires-second and make a change that belongs in
first. I’m at
and want to be to
Before Git v2.38 my solution was
which would result in
Git surgery is required to point
B' and to point
C'. You probably have your workflow. Maybe
git-log or a Git graph UI to figure what
C' are relative to
third-requires-second, or to look up their IDs, and then some
git reset --hards or
git branch -fs.
With Git v2.38, my solution is
which results in
The second real-life scenario is during the review/approval phase. Say I put these branches up for review at the same time (this isn’t a standard practice on my team, but our process is okay with it and it comes up from time to time).
- Pull request 1: main ← first
- Pull request 2: first ← second-requires-first
- Pull request 3: second-requires-first ← third-requires-second
Say a colleague requests a change in the first pull request. In the past, I might have added a commit to that branch
which would leave me at
To get to the goal
we could run
or my preference before
git rebase --update-refs,
git rebase --fork-point:
followed by pushing
first and force pushing (
git rebase --update-refs we can instead run one command
git rebase --onto first first~ third-requires-second. Shorter… but requires more knowledge of the context.)
The “during development” scenario doesn’t only happen during development, and the “during review” scenario doesn’t only happen during review. But without
git rebase --update-refs it is reasonable to think of them as closely related but distinct problems. But with
git rebase --update-refs the solutions are identical 👀 By adopting
git rebase --update-refs you reduce the set of branch management problems you need to have solutions for.
You can use
git rebase --update-refs today. If you’re locked into an outdated version because you’re using a copy of Git that ships with your OS, you’ll need to switch to a copy you manage yourself (for example, Homebrew users can
brew install git).
--update-refs is smart about squashed commits! Say you want to make a fix to the first of several stacked branches
followed by pushes.
git commit that could be
git commit --fixup=first. And with
rebase.autoSquash set to true, Git will move the fixup commit to immediately following its target for you. More efficiency… but that’s beyond the scope of this article.
checkout 🥁 the links!