git opinions

This blog post is in more raw form than previous blog posts. I wrote very few posts this year so far and I wanted to get it out before I lose steam.

There's been a lot of chatter about git on the internet lately. Starting with Julia Evans' excellent articles:

Then Mozilla's announcement that next year Firefox development will move from Mercurial to Git exclusively came out: Firefox Development Is Moving From Mercurial To Git.

So shortly after this morning's breakfast coffee I had opinions on the internet:

Lots of talk about git (and mercurial) on my timeline.

So some opinions:

  • git rebase is ok
  • git push --force on a PR is acceptable
  • github pull requests make reviews harder than necessary
  • using git-absorb and git-revise makes my life easier
  • git-cinnabar is an excellent hack

Let's look into those.

git rebase is ok

I regularly have multiple branches on a single repository for different work items. Some are separate but dependent work streams and might require to land in order, some are touching different parts of the code base and can land independently. Sometimes someone else lands patches that I will need to make my code work.

In all those cases a git checkout main && git pull --rebase && git checkout - && git rebase -i main gets me those changes, rebases my work and gets me a clean history with it. What I see locally is what I will end up pushing and what will end up in a pull request on GitHub.

This works surprisingly often without issues. There are edge cases and sometimes merge/rebase conflicts, but that will happen on a merge too.

git push --force on a PR is acceptable

(This is in the context of GitHub's Pull Request model)

Yes, force-pushing on a PR is ok. GitHub shows that something was force-pushed and shows you both the old and new commit, thus allowing you to locally diff those for what actually changed (but see below).

Though maybe don't force-push while a review is still being done and you're addressing review comments one-by-one. Add those as new commits and wait until the end of review to review your commits.

Often enough I structure my changes into several commits, each of which addresses a certain subset of the full changes with important notes in the commit message. Those should be preserved in what finally lands. Fixup commits and a force-push before merge gets me that.

github pull requests make reviews harder than necessary

GitHub pull requests force a very particular model on code review: It's single-threaded, it de-emphasizes individual commits and it refuses to show larger diffs by default. I see that as a huge downside for larger projects with potentially bigger and frequent changes.

It also gets some things right:

But other things I don't like:

At Mozilla we use Phabricator (Phorge is the active community fork) and while it's far from perfect it gets a couple of things right in my opinion:

1 revision = 1 commit (technically it could be multiple commits I think), but locally you can add additional commits, reorder them, rebase them, squash them, then push them up for further review. This fits my workflow much better.

It also falls flat on other things:

using git-absorb and git-revise makes my life easier

See TIL: git helpers. Two little tools that make fixup commits and rebasing easier to manage.

git-cinnabar is an excellent hack

git-cinnabar is a "remote helper to interact with mercurial repositories". It's the solution to contribute to the Firefox repository ("mozilla-central") using git. It allows to translate between git and mercurial commits, and gives me git branches for mercurial bookmarks (and branches). All that thanks to the tireless work of glandium. Because it existed I never really switched to Mercurial.