Version Control

Concept

A system that records who changed what and why, so that several people can edit the same code and have their edits combined safely.

Why it exists

There was a time when protecting code meant copying folders. Before starting a large change, a developer would duplicate the whole project directory and stamp a date on it. Those names piled up — final, final2, really_final, final_revised — and two months later nobody could say with confidence which one matched what was actually running on the server.

With more than one person, the problem changes shape. Everyone edits files on their own machine and uploads them to the server, and uploading means overwriting. If Theo uploads a fix in the morning and another developer uploads their copy of the same file in the afternoon, the morning's work disappears without a trace. The person whose work vanished doesn't notice right away. Three or four days later someone asks why a feature reverted to its old behavior, and only then does anyone realize something was overwritten.

Having no way back was the bigger problem. In Pagedeck's early days Theo would edit a file on Friday evening, push it to the server, check that the page loaded, and go home. Monday morning Sofia arrived with a customer report that payments were failing. The first thing anyone needed was a list of what had changed last week, and the only record was the memory of whoever made the change. Getting back to yesterday's working state required yesterday's copy, and whether that copy existed depended on how someone happened to feel that day.

Version control solved this by moving the unit of management from the file to the change. Instead of storing whole snapshots of a file, it stacks up one record per modification describing what was changed and how. Each record carries who made it, when, and why, so reading backward through the history explains how a given line came to look the way it does, and any past state can be reconstructed on demand.

The way work gets combined changed too. Early tools let one person lock a file so nobody else could touch it while they worked. That stopped overwrites, but people who needed the same file had to queue, and if the person holding the lock went home, so did everyone else's afternoon. Today's tools go the other way. Everyone edits freely, and at the moment of combining, the machine compares the two sets of edits and stitches them together on its own. Different lines join without help; only the same line edited two different ways gets handed back to a person.

How this field breaks down

The terms under version control fall into seven groups. What you do it with is the tool, what it operates on is the unit, what you do with it is the operation, what you trip over is the problem, how you do it together is collaboration, how the whole team runs branches is strategy, and how changes get announced to the outside is convention.

The tool is where the field starts. Git is the de facto standard for tracking change history, and most of the vocabulary below is really Git's vocabulary. Being distributed is its defining trait. The history doesn't live only on a central server — every machine holds a complete copy — so you can search the history and record new work on a plane with no network.

The unit group divides by what the system operates on. Three terms, in order of size.

  1. Repository — the space holding the code and all of its history. Usually one product or one service gets one repository.
  2. Commit — a point where a set of changes is recorded as a single lump, with a message saying what changed and why. It is the smallest thing you can revert or trace, so packing ten unrelated fixes into one commit means you can never pull just one of them back out later.
  3. Branch — a line of work split off from the main line. It lets you experiment without touching the main line, so a half-built payment feature doesn't block anyone else's release.

Operations are what pull the split lines back into one. There are two. A merge combines the changes from two lines and records the act of combining as its own entry. A rebase lifts your records onto the tip of the current main line, as if you had worked there from the start. The resulting code is the same; the shape of the history is not. The first leaves the fork and the join visible, the second flattens everything into one straight line. Teams pick one in advance, because mixing them means everyone reads the history by a different rule.

Problems cover the situations the machine can't settle on its own. A merge conflict happens when two people edit the same line of the same file in different ways. The machine can't judge which side is right, so it shows both versions next to each other and asks a person to choose. Opening a conflicted file shows both edits sitting next to each other with markers around them — your version on top, the other person's below, a divider between them — and the fix is to keep one, or rewrite the two into a single line, then delete the markers. It sounds alarming and usually takes a few minutes. What makes it grow is age: merge after a day and two or three lines overlap, merge after three weeks and ten whole files are out of alignment.

Collaboration is about putting a human step in front of the combine. Two terms work as a pair.

  1. Pull request — a request to merge your branch into the main line. It carries an explanation of what changed and why, and opens a view where every changed line is visible at once.
  2. Code review — the process where a colleague reads that request and leaves comments. Catching bugs is the stated purpose, but the larger effect in practice is that two people now know how that code works.

Once these two are in place, merging shifts from an individual decision to a team decision. The usual setting blocks anything from entering the main line without an approval, and with that in place features stop getting quietly overwritten.

Strategy is the team-wide agreement on how branches are run. Three terms sit here. Trunk-based development merges into the main line several times a day and keeps no branch alive longer than two days. It forces conflicts to surface while they are still small, which only holds up with dense automated checks underneath. Git flow goes the other way, keeping separate development, release, and hotfix branches and moving work along fixed paths. It suits products that ship bundled versions on set dates, at the cost of long-lived branches that are expensive to merge. Monorepo is a choice about repositories rather than branches: several projects live in one repository, so a change to shared code can update every dependent project at once, at the cost of a heavier repository.

Conventions govern how a finished result is announced to the outside. Semantic versioning writes a version as three numbers, like 2.4.1, and fixes a meaning for each position. A bump in the first means the old way of using it no longer works, the second means features were added while existing usage still holds, and the third means only bug fixes went in. When you publish a library or an application programming interface (API) that other people build on, this rule lets them decide from the numbers alone whether an upgrade is safe. On the receiving end, moving from 2.4.1 to 2.4.2 is something you can do without reading the notes, while moving to 3.0.0 means checking what breaks and changing your own code alongside it.

The seven groups run as one sequence. The tool creates the repository, commits accumulate inside it and branches split off, combining those branches produces conflicts, review sits in front of the combine, strategy decides when and how review and merging happen, and convention puts a number on the result that goes out.

How it sounds at work

"Let me revert just this one commit. The state right before yesterday afternoon's deploy is fine."

The change that caused the problem has been pinned down, so everything else stays and only that one entry comes out.

"You branched three weeks ago, right? Pull the main line in first, or the conflict is going to be enormous."

Delayed merging has piled up overlapping edits, so line them up now rather than later.

"Address those two review comments and I'll approve it."

There is no disagreement about the feature itself; fixing the noted spots is enough to merge.

At Pagedeck, Theo picks up a task to change how the document list is sorted. He splits a branch off the main line and stacks up five commits over two days — changing the sort key, handling the empty list, and adding tests are each their own commit. When the work is done he opens a pull request, and a colleague reading the changed lines asks what happens when the sort field is empty. Theo answers with one more commit, the approval lands, and the branch goes into the main line.

A week later a report comes in that the list is showing up in a strange order. When Mia asks since when, Theo opens the history and narrows it to the four commits that touched that file. Reading the messages and the changed lines, finding the one that caused it takes twenty minutes, and reverting that single commit puts out the fire. Nothing else that shipped this week is affected. This is the point where the work diverges from those Friday evenings spent patching lines from memory.

What people get wrong

The most common mistake is treating version control as backup. Both let you return to an earlier state, so the confusion is natural. But a backup stores a whole file as it stood at some moment, while version control stacks individual changes in order with a reason attached to each. The most a backup can tell you is that three days ago it looked like this. A history tells you that this line changed last month to fix a payment error. Someone who misses that difference uses the tool like a backup — one commit at the end of each day, every message reading "fixes." The smallest revertable unit becomes a day-sized lump, and pulling out the one thing that broke is impossible again. The tool is in place and the thing it was adopted for is still missing.

The other common belief is that solo work doesn't need it. With nobody to merge with there are no conflicts, so it looks unnecessary. Merging is only one of the jobs this system does. What a solo user reaches for more often is the revert point and the recorded reason. You six months ago are effectively a stranger, and in front of code you can't remember writing, the history is the only explanation left. The larger loss is that without a history you stop experimenting. A safe point to return to is what makes a big structural change worth trying; when breaking it means it stays broken, even the parts worth fixing get left alone.

Where to go next

  • Engineering

    see where version control sits in the wider field. It owns the combining stage on the path from a line of code to a user's screen, and that page shows how automated checks and deployment follow behind it

  • Git

    most of the vocabulary on this page is really this tool's, so reading it next makes the rest easier. It also shows concretely why being distributed changed the way people work

Sub-terms

Last updated 2026-09-16