What version control taught me about teams
A personal history of version control - from CVS to SVN to Git - and what each shift actually changed about the way teams work.
I made my first commit in CVS sometime around 2008. I had just landed a real programming job and had already been told to set up my own workstation, install Linux, and figure it out by myself. Nobody explained version control to me. I typed cvs commit, and a career somehow followed.
I am still committing code twenty years later, and the tools look nothing like they did back then. But the core problem they solve hasn’t changed at all: version control is still about coordinating people as much as code.
CVS: version control as an act of faith
By the time I encountered CVS, it was already old. It had been around since the 1980s, and most of the industry had moved on. I have no idea why we were still using it. I was a junior PHP dev and used what I was told to. The company was an old-school media company throwing “digital” at the wall to see what would stick.
CVS thought about your code as a set of files, not as a project or a snapshot. Each file had its own history, and there was no concept of an atomic commit. If you changed ten files and lost your network connection in the middle, you would end up with a repository in a state that was truly difficult to fix.
Branching existed on paper. Nobody used it. Merging required you to keep a lot of context in your head, trust that the tool understood it the way you did, and then hope. Most teams didn’t bother. Everyone worked on trunk slowly, trying not to step on each other.
What CVS accidentally taught me was to commit small and commit often. Not because the tool made it easy, but because the alternative was a Friday afternoon debugging a state that technically existed in no version of reality. That lesson was really about managing risk, not managing files.
SVN: better, but still centralised
Subversion was a proper rethink. Atomic commits: the whole changeset lands or none of it does. One revision number for the repository instead of per-file chaos. Branching that worked well enough that some teams actually used it.
The mental model shift mattered more than the features. You stopped thinking about files and started thinking about changesets. A commit became a unit of work, something you could describe, point to, and revert. That sounds basic because it is basic. It was not the default before Subversion made it so.
svn blame was underrated. Knowing not just what changed but who changed it and when gave code review a different texture. You could ask “why is this like this” and actually trace it. Code started to feel like a shared thing rather than a pile of contributions with no memory.
The ceiling Subversion hit was the centralised model, and it never got past it. The server was the source of truth. Everything went through it. No network meant no commits. Branching was technically possible, but it meant copying the whole repository to a different directory, and merging it back was enough of an ordeal that most teams avoided it. So you would have trunk and maybe a couple of release branches. That was it.
The knock-on effect was that everyone was always in the same place at the same time. Conflicts were constant, or you had conversations like: “don’t go near the payments module, I’m in there.” Continuous integration existed as a concept, but trunk was everyone’s problem at once, which made it hard to run in practice.
Git: a different mental model
Git came out in 2005. Linus Torvalds built it to solve his own problem with the Linux kernel and was pretty upfront that it was a side project. By the time I started using it around 2010 or 2011, it was clearly going to win.
The shift from SVN to Git was not really about features. It was about what the tool assumed.
In SVN, the server held the truth and you were a client checking things in and out. In Git, you have the whole history locally. Commit, branch, rebase, all of it offline. The remote is just another copy, not the authority.
That one change made branching trivial. A branch in Git is a pointer to a commit. Creating one costs nothing. That is what made feature branches, pull requests, and trunk-based development with short-lived branches possible as standard practice. On SVN, none of it was practical without significant pain. On Git, it is just how you work.
Git also gave us a draft phase. git rebase, git commit --amend, interactive rebase: you can make a mess locally and clean it up before anyone else sees it. In SVN, every commit was immediately public and permanent. Git lets you keep the thinking separate from the sharing. That is a bigger deal than it first sounds.
Worth noting: rewriting history that has already been shared is still a mistake. It creates the kind of confusion that makes people grumpy at standup. Most teams learn this once and then build norms around it.
What actually changed
Looking back across all three, each one lowered the friction of collaboration. CVS made it painful. SVN made it workable. Git made it cheap.
But the coordination problem never went away. It just moved. In CVS, the friction was in the tooling. In SVN, it was in the branching model. In Git, it lives in the team’s norms: when to merge, how to write a commit message, what belongs in a PR description, how long a branch should stay open before it lands.
The teams I have seen struggle with Git usually are not struggling because of Git. They adopted the tool and skipped the practices. Git does not care if you commit wip forty times in a row. It will happily let you merge a branch that has been open for three months and gone completely cold. That is the team’s problem to solve, and the tool will not solve it for them.
The tool makes it possible. What you do with it is up to the team.
2008 to now
The thing I find most interesting looking back is not the improvement in tooling, even though that improvement is real. It is how much the culture changed alongside it.
In 2008, the team I knew operated under a gatekeeper model. A few senior people understood version control well enough to manage it. Everyone else tried to stay out of trouble. Branching was something you asked someone more experienced to handle. Merging was something you dreaded.
Now engineers and agents create and merge branches dozens of times a day without thinking about it. Code review, which was informal at best in a lot of the companies I knew in the late 2000s, is now a standard part of how software gets written.
Git made that possible, not by inventing code review or collaborative branching, but by making them cheap enough to become habits.
Not bad for a tool that started as someone’s personal itch.