I finally get it
For years when asked about this flag, I would respond that I didn’t really understand it, that it seemed unnecessary. But I finally ran into a situation where I needed its functionality and had to discover how to use it.
There’s a useful section about this flag in the Rebase docs, but I’ll explain in detail here.
rebase --onto is used when you want to specify where the rebase should start, instead of letting Git figure that out for itself.
# traditional rebase syntax:git rebase <newbase> [end]
# syntax with --onto:git rebase --onto <newbase> <start> [<end>]As you can see, the benefit of the flag is that it lets you specify a <start> commit.
<newbase>: where the commits get replayed<start>: the commit after which the replay begins (exclusive)<end>: the last commit to replay (inclusive). Omit this and Git uses the branch you’re currently on
Say you’re here
topic was built on top of next, and you want to move topic over to main (say next had been squash merged, so its functionality was already in main).
The traditional move, git rebase main topic, would take all commits in both topic and next and replay them on top of main; which could be messy because all the functionality in next is already in main, just squashed down.
In order to move only topic’s commits, use --onto
# git rebase --onto <newbase> <start> [<end>] git rebase --onto main next topicWhich reads as: “take the commits after next, up to and including topic, and replay them onto main.”
Notice that next didn’t move an inch. The <start> argument is only used to decide which commits get copied; the rebase doesn’t touch it.
Because --onto gives you control exactly where the replay starts, you can also use it to surgically remove commits from the middle of a branch:
git rebase --onto B DThere’s no <end> argument here, so it defaults to the current branch. This says “replay everything after D onto B” — which conveniently leaves C and D behind.
You just rewrote history, so like every other time, be sure to run the standard post-rebase checks: look at the graph to confirm the new shape is what you intended, then git diff the old tip against the new one to make sure nothing came along that you didn’t invite.