Git Rebase: Upstream Means Since

In a codebase at work, I was trying to rebase onto a branch with a squashed commit. The problem with that is that your branch has commits equivalent to the squashed commit, so you need to tell Git: “skip these commits and replace them with the squashed commit”. Otherwise, you’ll have go through the merge conflict process, and who knows how that will end up?

This Stack Overflow answer answer initially confused me.

The abridged syntax of a git rebase command is

git rebase [--onto <newbase>] [<upstream> [<branch>]]

<branch> is usually the current branch, so it can be omitted. I mention it because it’s used in examples like the linked SO post and the git-scm doc.

But how does it know to replace the unsquashed commits with the squashed commits?

<upstream> Means “Since”

When we do a rebase, we’re replacing <branch> with a new branch of the same name, created by replaying commits onto <newbase>. By default, <newbase> is the same as <upstream>.

But –onto lets us specify a new <newbase>, separately from <upstream>.

This is where it’s important that <upstream> means “since”. When we replay the commits in <branch>, the commits we replay are the commits in the original <branch> since the commit specified by <upstream>.

That’s why it knows to replace the original commits with the squashed commits: it’s just taking the commits that have happened since then.

The SO answer already says as much, but it took me a chat with an AI and some time skimming docs to get it. Hopefully this makes it a little more clearer for you, or me in the future when I’ve forgotten about this and stumble across this post.

(Or maybe an AI will regurgitate it back to me. In this day and age, maybe that’s how to tell you’ve really made it? Anyway, end of parentheses.)