Posted At: 4/19/2026
Author: Sandesh Bhandari
sandesh/shitty-first-commit
I suppose programmers of genuine talent may well have existed at some point in the history of computing, but I strongly doubt that one has ever pushed to main with the serene confidence and intellectual composure of the engineers I have read about in books. Reading the GitHub profiles of the truly great, one cannot help but be struck by the overwhelming cleanliness of their commit histories. Think of the abstractions, the test coverage, the variable names springing from these voracious readers of documentation, who are nimble with the type system, savvy in the ways of memory management, and full-time of the pull request. I know some very great programmers, engineers whose code you'd read and feel embarrassed by your own, and not one of them sits down routinely feeling wildly enthusiastic and confident. Not one of them writes elegant first commits. Very few of them really know what they are building until they've built it. For me and most of the other programmers I know, coding is not some beautiful thing. In fact, the only way I can get anything built at all is to write really, really shitty first commits.
If one of the voices in your head wants to hardcode everything and name your variable something, you let her. No one is watching. And if you want to name your files thing, thing2, theThing, actualThing, temp, newTemp, temp2, data, theData, actualData, result, result2, finalResult, finalResultActual, you let her too. I don't even remember what I used to call mine. You let yourself get into really sloppy, embarrassing, copy pasted territory and just get it down on screen because there may be something in that terrible nested loop, in that function you'd never show anyone, that you would never have gotten to by more careful, rational design. Something in the very last line of the very last function that is so clarifying or strange that you now know what you are actually building, more or less, or in what direction it needs to go. There is no way to get there without first getting through the mess. You want to skip it. You can't.
in early days. In fact one particularly bad commit did cause a couple of outages, not helped by my stuffing logic into a single function the size of a short story. My commits always took two days. First I'd sit down at my desk with issue and stare at it. Like if I looked long enough, the solution would just surface. It never did. I'd try typing a couple of dreadful lines, delete them, try again, and feel despair and worry settle on my chest. I'd think to myself, calmly: I'm not going to be able to figure this out. I don't understand the codebase. Maybe, I'd think, I can find a library that does this for me. Probably not. I'd get up and stare at the ceiling, remember to breathe, make a few Slack messages, close them without sending. Eventually I'd go back and sit down at my desk. Finally I would pick up my one inch picture frame and every time the answer would come: all I had to do was write a shitty first commit of, say, the one core function. And nothing more.
So I'd start writing without reining myself in, just making my fingers move. And the code would come out in one long function that was forty lines long even though it should have been five, and then I'd start building out logic branch by branch, and the variable names would be insane. They'd be pretending to handle edge cases, failing at every one, no matter how hard I tried to rein it down, no matter how conscious I was of what a mess it was. The whole thing would be so long and incoherent and hideous that for the rest of the day I'd obsess about getting hit by a car before I could write a decent second draft. I'd worry that people would read what I'd written and believe that the accident had really been a suicide, that I had panicked because my talent was waning and my mind was shot.
It was a Tuesday night somewhere in the valley between version 0.1 and something that actually runs, and I was in 'oh shit, this happened!!' moment. Monster and my head blinking, likely because I slept at 4am yesterday too. I promised it would stop at 2am every time. Six hours. Six hours for one function. And it still didn't compile. But so what? I thought. This is how it works. This is how it has always worked.
The next day, I'd sit down, go through it all with fresh eyes, take out everything I possibly could, find the logic buried somewhere in the middle, figure out a clean place to end it, and write a second draft. It always turned out fine. I'd go over it one more time and open a pull request. Almost all good code begins with terrible first efforts. You need to start somewhere. You think writing shitty first commits means you are bad at this. It doesn't. It means you are doing it. The ones who never ship are the ones waiting to feel ready. You can't win against yourself by waiting. You just have to open the file and start. Even if what comes out is ugly. Even if it doesn't resemble anything you meant to make. You get it down first. Everything else comes after.
A year ago I was assigned a ticket in the great project management system of a software startup of some local reputation, to work alongside Mr. Senior Engineer and Mr. Tech Lead on a feature described only as the onboarding flow, a phrase so broad as to constitute not a specification but a philosophical position. I felt at the time that I possessed one considerable advantage over others, and that was: enthusiasm. My first real feature ticket, and it was this good opportunity, a chance to demonstrate to my senior engineer, a woman of formidable patience and narrowing goodwill, that I was the kind of programmer who wrote clean, deliberate, already knowing where it was going code. If this codebase had any idea how thoroughly I was about to violate its architecture, it had another think coming. My goal in life was elegant software, and I would frankly rather have been debugging a kernel panic or a race condition, except those problems never presented themselves, while this ticket, which had been sitting in the backlog for six weeks and was described only as "fix", not only required my attention but had somehow been assigned to me personally.
I thought I should burst with indignation. I had been working with a four hundred and twelve line function called handleOnboarding whose internal logic had the narrative structure of a fever dream.
I opened my editor and the blinking let me in. The function is structured in a single file architecture, with inline comments on the walls of the logic. And so I started.
The next morning the reviewer had added only this:
SIGNIFICANT. Mr. Sandesh, it will be observed, is suggestively silent about the two hundred and forty line function.
During the remainder of the sprint, this reviewer never referred to me in any other way than as the infamous Sandesh, author of the function. Next came a Slack message, with this:
WANTED TO KNOW. Will the junior developer deign to explain to certain of his fellow engineers the small matter of his last three commits being pushed directly to main at two in the morning, without so much as a branch, a review, or apparently any familiarity whatsoever with the concept of version control? Mr. Sandesh has been reached for comment. He said, and we quote directly: "oh no."
Could anything be more deliberately malicious. I had been trying to move fast. Nobody had told me about the branch policy explicitly. There had been a wiki page, yes, but nobody reads the wiki.
I can lay my hand upon the keyboard and swear that I had genuinely believed the answer had a positive score and therefore could be trusted absolutely.
// Here it is, buckle the fuck up, because I'm about to unleash the straight, brutal, no nonsense version, the raw, unfiltered core of exactly what you need and nothing else is still in the commit git history
Then came the accusation that I had been writing my commit messages in the past tense when the convention, clearly stated in the contributing guide that I had not read, was present tense imperative. This drove me to the verge of distraction.
After the review, the senior engineer told me how instructive the experience had been for the team and that of all the junior developers she had encountered, I was the one who had most expanded her understanding of what was possible in a single commit.
I once had a commit that caused three separate incidents, a postmortem, and a new section in the team's engineering handbook titled Considerations Before Merging. The section did not mention me by name. It did not need to. Everyone knew. The commit message had said should be fine and nothing about that sentence was accurate, because you cannot write software without believing, at least briefly, that it should be fine.
I suppose programmers of genuine technical elegance may well exist somewhere in the industry, but I have not met them, and I have been coding long enough that their continued absence from my life has begun to feel less like coincidence and more like a verdict. I have met many programmers. I have reviewed their code and they have reviewed mine and in these exchanges I have learned that every codebase, no matter how clean its surface, has a room you are not supposed to open and a commit you are not supposed to read.
The shitty first commit has not been edited in the direction of anyone. It is written by a person who has temporarily forgotten that other people exist, which is a condition usually associated with very early childhood and certain meditative states and 3am on a Wednesday when the deadline is Thursday and you have stopped caring what anyone thinks because you have a more pressing problem which is the function that will not compile. In this state I have produced code that is wrong in extremely interesting ways. But now there is the layer of the person I am now, who names things correctly and structures things logically and leaves comments that illuminate. Below that is the layer of the person I was six months ago.
I will not apologize for it. I have tried. I am constitutionally unable. The shitty first commit is the most honest work I have ever done and the cleanest second draft I have ever written was built entirely on top of it. You get it down first. Everything else is just what you do to make it presentable. Which is also necessary. Which is also good. But the first thing, that was the truest version. And I keep it. I keep it the way you keep the photographs you never post. Not to show anyone. Just so that something somewhere knows it happened.
The log keeps it. The timestamp is permanent. The duplicate onboarding is there. The four hundred and twelve line function is there, and my additions to it, and the evidence of exactly how lost I was and exactly how I found my way through.
I gave it up.
I myself in the peculiar condition of wanting to be free. Not in the temporary, Tuesday-afternoon sense. No. I mean in the absolute, almost theological sense: free from review, from mortgage, from the subscription I forgot to cancel, from the performance improvement plan. Free, in short, from everything that makes modern life feel like an arrangement.
I want to be free. Not partially free, not free within reason, not free in the manageable and socially acceptable sense. Free from the responsibility that follows a person through every room he has ever entered, from sleep, from hunger, from the body itself, from time, from death, which is the final and most insulting of all the things that I never agreed to.
I came to discover that the longing for freedom is perhaps the most democratically distributed affliction of our age.
Love and livelihood are fundamentally in opposition, in that to commercialize love is to corrupt it. You don't love a soulless arrangement.
Freedom, in the sense, is not the abolition of obligation, and probably should not be desired, since it is the obligations we have freely chosen that give our days their weight and meaning.
It requires, above all, a tolerance for the fundamental discomfort of being a free agent in a world that would very much prefer you were predictable.
And if that is not quite what it is, I have come to think that this is precisely what makes it freedom. Genuinely yours, assembled from the materials of your actual life, from everything you choose to give meaning.
I was not equal to the requirements of a production codebase in the state of this startup, and so I opened a new branch, named it sandesh/shitty-first-commit, and pushed my terrible, embarrassing, wonderful first draft, which I had been trying to hide for two weeks, and submitted it for review. It was, in the end, fine. The senior engineer said as much, in her way, which was to approve it without comment and move on.
// Truly yours, once a man of quiet dignity, but now
// SANDESH B., author of the two hundred and forty line function :(