For all those little papers scattered across your desk
Some reflections on a mass of articles taking up space on my phone.
Matklad explains what to me is a novel application of worktrees. Git’s own manual page talks about them like a better stash, but Matklad uses them to organize parallel tasks that want their own sources and builds:
project/
main
: the current main
branch of developmentwork
: active workreview
: PR reviewfuzz
: fuzzing with Zigscratch
: random fixupsWhile I probably wouldn’t personally use a main
worktree just for diffing,
since git diff
can do that already, using it to compare build times and
behavior is smart. My current projects don’t need fuzzing, and I tend to make
“scratch” work by throwing it into my
notepad
wiki
and coming back to it later. Still, I could imagine setting up 3 or 4 tmux
windows per project in different worktrees, or just one and using
pushd
/popd
. Build systems that use last-modified times, like make
, would
probably re-build less stuff in the main worktree than in my chaotic work or
review worktrees, so that could help.
If you know me, you know I don’t agree with the title on principle, but:
technically you can use empty commit messages with --allow-empty-messages
. And
the author smartly uses this for a workflow that includes lots of transient
commits (not dissimilar to one I use myself), where the final commits get a nice
message.
My personal version of this is usually git commit -m.
or git commit -m wip
,
which don’t jar quite as much in git log
and similar output.
I’m not the only one to think GitHub PR reviews have problems: for one, the lack of real threading like in email makes pages with lots of comments abysmally slow, and the diff + comment interface is no better for even reasonably sized PRs! Meanwhile, the underlying Git technology is fast.
Mitchell Hashimoto focuses more on the lifecycle problems with GitHub’s
interface, though: primarily the distinct lack of versioning (again, something
email and git range-diff
support natively) and the problem of working on the
reviews and the responses in parallel. Like many of us, he wishes GitHub could
orient itself around versioned changesets.
Fortunately, this is what SourceHut does, and I keep coming up with new reasons to try it.
Brandon Pugh’s first line of advice is one I’ve oft repeated: make the commit message as useful as possible. As he points out, we talk a lot about regular commits but less about merge commits. I’ve ranted about messages in PR merges, but not explained that
merge.log =
true
to include the 20 most recent commits in the merge commit summary. Similarly
you could use merge.branchdesc
to populate messages with branch descriptions
if your workflow often includes setting those.Pugh also points out there’s often other explanations that can be given in the description, and we should probably do that.
And of course, avoid evil merges.
Wouter’s primer on notes is one of the better ones I’ve seen because it explicitly covers note namespaces and refspecs, making them easier to work with. In fact, I’m now tempted to start putting notes on commits at work and pushing them, just in case someone ever discovers them ;)
Unfortunately, I can’t find any options to make adding the “fetch all notes”
refspec the default when setting up new remotes (or cloning). Although it is
possible to create default refspecs for pushing, that also overrides
push.default
which is useful for making Git DWIM in a triangular workflow.
I haven’t had time to read this yet, but it seems like it could be a good reference on the diff algorithms themselves. They are one aspect of Git I’ve never really explored.
Another Matklad piece: typical projects don’t need a linear history of every
commit passing tests. In such a project, merges are the record of passing tests
(so bisect
with --first-parent
first). Take advantage of this by structuring
commits in branches to split work. Matklad gives several examples.
Matklad also mentions the “merge to main, rebase feature branches” workflow—here, you still rebase feature branches if you need to build on top of later commits, but you create merge commit when bring the branch into main.
Oh, and by the way: stop commenting out dead or broken code1. Delete it. We can recover it with version control (and it’s likely to never be fixed or recovered anyway).
More Matklad: small and trivial changes deserve small, trivial commit messages. And we should try to make more of them.
Bait taken! You know I like a good long commit message, but it’s absolutely true that big commits are a workflow problem often imposed by CI + review turnaround. I’ve worked with plenty of folks who wish they could do differently but who know that they need to squeeze as much as they can out of each PR because turnaround time is long.
Yikes.
I like most of Matklad’s recommendations for fixing the workflow problem here, though of course in some regulated industries merging pre-review is a non-starter.
I will single out one comment:
If a change is really minor, I would say
minor
is an okay commit message!
No, it isn’t: the subject should describe the fix, even if it’s just fix doc
typo
or s/it's/its
. Those still convey the “minor” intent while providing
enough detail to folks fetching new changes to know what’s happening around
them.
Guess I’m reading a lot of Matklad lately.
The “better diff for review” idea is novel to me, and certainly seems like a good one to try building! But I’m rather more interested in fetching PR changes for review and then resetting them so that vim-fugitive can show them to me. I normally review one commit at a time, so this might be a good inter-commit workflow. It also helps provide an overview. Interesting.
In the end, whether by email or web UI, we’re still leaving comments on the diffs, though.
This one reminded me of times where I’ve accepted PRs from newer contributors by fixing up their branches and merging locally—hopefully that provided some lessons for them, but it might not be as teachable as merging followed by fixes (cc’ing them). At least, in prior applications where I didn’t show them the range-diff and walk them through the changes I made, I certainly didn’t actively teach them.
JaneStreet describes an internal review and workflow tool, and I’m jealous.
It did inspire me to add a personal todo item: try building a Vim plugin for reading and writing PR review comments! I’ve explored a little of the prior work, but it’s deep in my personal backlog.
An excellent bit of sarcasm. Well worth the read, especially for new engineers (what not to do) and experienced engineers (who laugh because of their experience).
A tool I’ve been meaning to build (roughly), and it already exists! I actually want to be able to draw a graph shape and have the tool create it, but this is close and might serve as a back-end.
Much to my chagrin, it is a dominant force. GitLab is probably the closest competitor and, if I recall correctly, remains closed-source.
I’m strongly considering alternatives, and I think you should too. SourceHut is the most compelling for me right now, but it’s nice to see that we still live with a thriving Git forge ecosystem that really puts its weight behind “decentralized.”
While I’m jealous of the “rebase all work at once” aspect of this flow, I’m not sure I could handle organizing that much parallel work just in rebase todo lists (partly because I work for a company that, at it’s best, still has some review and merge cycles that take longer than a few days).
It also wouldn’t surprise me if keeping everything together made it easy to accidentally send patches out that depend on previous patches without remembering this fact or mentioning it, which could become very confusing.
To add a bit of nuance to this, I don’t care what you do in your tree. Comment out code, play around, whatever. But in the canonical upstream tree, the main branch? Don’t send me PRs with bodies of commented out code. ↩