💾 Archived View for idiomdrottning.org › merging-vs-rebasing captured on 2024-05-12 at 15:21:03. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-12-28)

-=-=-=-=-=-=-

Merging vs Rebasing

OK, first of all, if you’re not the project lead, and the project lead has opinions, those are gonna be more important than what some rando Gemini capsule like this has to say. When in Rome, merge or rebase like the Romans do.

So the whole point of git compared to 90s style VCs like cvs or svn is that every copy of a repo is in one sense “the hub”, every copy of a repo, and even every branch of every copy, is the center of its own development and can have patches and commits applied to it. And that’s awesome.

That said, some of the time it’s helpful to still think of a git repo as being in one of three modes. Being at the “center”, or being at the outer end of a “spoke”, or being, in some sense, “both” (which can happen if you're a "lieutenant" on a larger project, or if upstream is late in accepting your patches and other people latch on to your version).

End of a spoke

By “end of a spoke”, I mean if you’ve git cloned from somewhere, hacked a bit, and now you have local changes. Not even your fancy published “pull my feature branches from here, please” repo, I’m talking about the dirty workspace repo on your local dev machine. No one else is gonna refer to your repo as if it were the canonical version, it’s just your temp copy for hacking.

For those kinds of repos, I’ve belatedly realized that rebasing is the best. It just is. Even reordering things so that your hyperlocal changes (like renamed paths and such) are kept at the very top, and then patches you still hope upstream or someone else will find useful in between, and then under there is where you rebase new developments from upstream.

git log
abcd1234 (HEAD -> hyperlocal) Your hyperlocal changes that no-one else will ever want
deadbeef (main) Another one of your patches that you sent a while ago and are still waiting for a reply on
cafe4520 The patch you sent most recently
2907bad2 (origin/main) The upstream's boring stuff goes here
3000e1e5 More upstream boring things

You can maintain this with patch stacking tools (like magit, jujutsu, or git-branchless) or you can just use branches; rebasing your “dev” branch (which I’d just call “main”) on top of upstream and then rebasing your “hyperlocal” branch on top of your dev branch.

git checkout main
git pull --rebase
git checkout hyperlocal
git rebase main
# then do compiling and stuff here from hyperlocal, and then switching back to main to hack

Now, in practice I’m such a slob that I don’t even bother with separating stuff out into a “hyperlocal” branch, I just keep my local stuff at the top of main and when I send patches I’m just a li’l more finicky with what commit range I’m sending.

The awesome thing about rebasing for a “spoke” repo is that rebasing magically removes commits that have changes that already exists below them! So it automatically “clears away” patches that upstream have accepted via send-email or pull requests.

Now, upstream, don’t be a credit-stealing jerk about this.

Repos that are more central

Here is where merging can be really fun because you get to see the commit history with all the cute merge commits. Now, a lot of project leads will have rebasing here too if they prefer a linear history over an accurate history, if they think the linear history is easier to work with. The send-email workflow can work either way (apply patches on top of main, or in new branches that you merge in). I don’t really have strong opinions one way or another for these kinds of repos that need to be more canonical and referred to, and can’t easily rewrite their commit history since that’ll cause conflicts downstream.

Even though I don’t use that much merging in practice in my own projects, I have sort of a nostalgia for it since it feels like such a gittish feature that really celebrates the decentralized nature of git.

And also on the “central” repo, don’t rebase it on top of other changes. Instead, rebase other changes on top of it, that’s fine, but then you might as well merge.

For “spoke” type repos, rebasing your stuff on top of upstream just simplifies so much, but it’s not appropriate to rebase & history-rewrite away stuff that’s already been published.

Branching & Patching

The kernel project’s insightful advice on why they merge so much