Image 01

Transneptune

beyond the Kuiper Belt, over the sea

The Historiography of Git, or How I learned to stop caring and love writing history

November 30th, 2015 by Kit

This post was occasioned by hearing about the experience of pairing with Nvie, and then talking with Owen about how he does similar things.

Git is notorious for allowing you to rewrite history, which rubs some people the wrong way, but which I and some others think is actually pretty neat and useful, if you don’t abuse it. From what I hear, when Nvie is busy coding, his commit messages are just about “foo” or “wip” or whatever, and it’s only after he reaches a good stopping point that he goes back, rewrites history to say something meaningful, and commits. As Owen said to me when we were talking about this, he does something similar, but has had a hard time explaining what utility he gets from it to others. So I promised I would try to explain it.

I don’t think the utility of this became clear to me until I started working on Hexes (which is dormant until I figure out a good way to write a testing framework for it—ideas welcome!). Every time I would take it out to work on it, I would bring it to a stable point, then commit. When I wanted to work on a new feature, I would necessarily break things that were working, for a while, and having good version control practices let me move forward with confidence, knowing I could roll back if I had to. (At some level, obviously, this is the or a purpose of version control, but the realization hit me deeply on that project.)

But the next step was to be able to roll back not to just the last stable version before I started work on this feature, but to the quasi-stable points between the last and the next fully stable points, where I had expressed an idea but not worked out all the kinks in it. And so, clearly, that’s what other commits are for. So why not make them “real” commits?

Because real commits take too much time and energy. They pull you out of the thought process you are not yet done with and demand you shift from “writer” mode to “editor” mode. You just need a quick hand-hold to let yourself move forward, not a full belay anchor. (NB: I do not rock climb and have no idea what I’m talking about there.) You should be keeping your attention on the code and the architecture, and not the individual anchor points. On the flow.

But why do you then go back through and clean up your commits? Isn’t that a lot of work? Yes! But it also has a lot of value. It’s a communication tool, and even if you’re on a team of one, you will eventually be communicating with yourself in the future. If you don’t ever review your git history, and don’t think you ever will, well, I hope you’re wrong. And if you’re not on a team of one, know that anyone who looks at your PRs will probably step through each commit and try to see what you intended to do there. Leaving your commit history as a series of WIPs is like a craftsperson who keeps their bench an utter mess—it shows that you haven’t yet learned how to work on a team, and that you probably don’t understand the cost you incur yourself that way because you’ve become accustomed to it.

This is actually writing history, not rewriting it. History is not a series of events, but the interpretation you impose on it after the fact. Imagine what a disaster it would be if “history” books were just enormous piles of primary sources with no analysis, synthesis, cross-referencing, or organization. To put it another way, when you rewrite your commit history, you are doing the job of a historian, making sense of and imposing structure on the events that happened in a given period.

Of course, before you do any of this, get real comfortable with git. Worrying about losing work is not worth the value this gives, but if you’re worrying about losing work with git, you are, and I say this with love, still using it at a novice level. You should never have a tool as central to your work as a version control tool make you worry about loss. Understand it more, that’s your next task.

Maybe this’ll at least make you pause and think for a moment about the value this approach can offer. I’m not at all sure it’s convincing, but I tried.

Thanks to Ben Warren and Owen Jacobson for input on this post, and Jonathan Chu for the initial inspiration. Ben says, of arguments about git:

I don’t understand most people when it comes to git. It is a time-travel system, the end. Quibbling over the rightness of time travel when you are using a time machine seems like missing the point.

  • Jeff Kaufman

    Another reason to squash incomplete commits is so that every commit in the final change builds and passes tests. As someone who did a bisection yesterday and successfully found the culprit commit, in very glad my team does this.

  • Yes yes and more yes. So very totally yes. I did the same with some of my own work today.