Background

Git, in depth

You don't need any of this to use Git. But if you'd rather not treat it as a black box โ€” and understanding it makes the commands stop feeling arbitrary โ€” here's what's actually happening underneath.

1 ยท Where it came from

Git was written by Linus Torvalds in 2005, and the circumstances explain most of its design.

The Linux kernel had been using a commercial system called BitKeeper under a free-for-open-source licence. That licence was withdrawn, and thousands of developers spread across the world suddenly had no way to collaborate on one of the largest codebases in existence. Nothing else available could cope with the scale.

So Torvalds wrote a replacement in a fortnight, optimising hard for a specific set of problems: it had to be fast, it had to work with no central server, it had to make branching and merging cheap because kernel development is thousands of parallel efforts, and it had to be able to prove nothing had been tampered with.

That last one explains the hashes. Every commit gets a cryptographic fingerprint of its entire contents and its history. Change one byte anywhere in the past and every fingerprint after it changes. That's not a version number โ€” it's a tamper-evident seal, and it's why Git IDs look the way they do.

Git's reputation for being confusing comes from the same place. It was built by kernel developers for kernel developers, and the friendly parts were added later. You're not failing to understand something obvious; the interface genuinely was an afterthought.

2 ยท What "distributed" actually means

Git is a distributed version control system. The systems it replaced โ€” CVS, Subversion, Perforce โ€” are centralised. The difference is not academic.

CentralisedDistributed (Git)
Who has the historyThe server. You have the current files.Everyone. Every clone is a complete copy.
CommittingNeeds the serverLocal. Works on a plane.
Viewing historyNetwork round tripInstant โ€” it's on your disk
Server diesHistory is gone unless backed upEvery clone is a full backup
BranchingOften a full copy โ€” slow, discouragedA pointer. Instant.

When you run git clone, you don't download the current state of the project โ€” you download every version of every file that has ever existed in it, along with every commit message. That's why cloning a large repository takes a moment, and why almost everything afterwards is instant.

A practical consequence: if GitHub goes down, your work doesn't stop. You can commit, branch, merge, read the entire history, and check out any past version. All you lose is the ability to share. More on that on the GitHub page.

3 ยท What a commit really is

People describe a commit as "a change" or "a diff". It isn't. A commit is a complete snapshot of every tracked file at a moment in time, plus a small amount of bookkeeping:

A snapshot
The full state of the project โ€” every file, every directory. Not the changes: the whole thing.
A parent
The commit that came before. This is what strings history together. A merge commit has two parents; the very first commit has none.
Author and committer
Name, email, timestamp. Two fields, because the person who wrote a change isn't always the person who applied it.
A message
Your explanation. The only part the machine doesn't generate.
An ID
A hash of all of the above. Change any of it and you get a different commit with a different ID โ€” you haven't edited it, you've made a new one.

Diffs, then, aren't stored โ€” they're computed when you ask for them, by comparing two snapshots. That's why git diff can compare any two points in history instantly, however far apart.

The obvious objection: wouldn't storing a full copy of every file at every commit be enormous? Two things prevent it. Files that didn't change between commits aren't stored twice โ€” both snapshots point at the same stored content. And Git periodically repacks its storage, at which point it does compress similar objects against each other. So the model you reason about is snapshots; the thing on disk is cleverer.

This is also why commit IDs are hashes rather than sequential numbers. There's no central authority handing out "version 47" โ€” you might be offline, and so might four other people. A hash of the content is a name that everyone independently arrives at, and that can't collide by accident.

4 ยท Why branches are almost free

In older systems, making a branch meant copying the entire project. It was slow, took disk space, and teams avoided it.

In Git, a branch is a file containing a commit ID. That's the whole implementation. Forty-one bytes: a hash and a newline.

a branch, unmasked
$ cat .git/refs/heads/main
9df8a3157e2c1b0a4f6d8e2c1b0a4f6d8e2c1b0a

# that's it. that's the branch.

Creating one writes a new small file. Deleting one removes it. Switching between them changes which files are in your folder, but the branches themselves cost nothing. This is the single design decision that makes the entire pull request workflow practical โ€” the daily loop only works because branching is trivial.

HEAD is one more layer of the same idea: a file that records which branch you're currently on. "Switching branches" means pointing HEAD somewhere else and updating your working files to match.

Committing, precisely: Git writes a new commit whose parent is wherever the current branch points, then moves the branch to point at the new commit. The branch "advances". Nothing is inserted into a list; a pointer moves.

5 ยท What Git is genuinely bad at

Every tool has a shape, and knowing where Git's ends saves a lot of confusion.

Large binary files
Git can store a video or a design file, but it can't show you what changed inside one, and it can't compress successive versions the way it does with text. Twenty revisions of a 200 MB file means a repository everyone has to download forever. Git LFS exists precisely for this.
Anything not plain text
Word documents, spreadsheets, and PDFs are technically binary. They'll be tracked, but a diff is meaningless and merge conflicts in them are unresolvable by hand.
Empty directories
Git tracks files, not folders. An empty directory simply doesn't exist as far as Git is concerned. The conventional workaround is a placeholder file, usually .gitkeep.
File permissions
Git records exactly one bit: whether a file is executable. Ownership and the rest of the permission mode aren't tracked at all.
Partial checkouts
Historically it was all or nothing โ€” you got the whole repository. Sparse checkout and partial clone have improved this, but Git is still happiest with projects that fit comfortably on one machine.
Forgetting
Git's entire purpose is to remember. That becomes a liability the moment you commit a password: the history is the point, and removing something from it means rewriting every commit since. Covered in Level up.

6 ยท Git without GitHub

Worth stating plainly, because the two names get used interchangeably: Git needs no website, no account, and no internet connection.

Run git init in a folder on a laptop with the Wi-Fi off and you have a fully functional version control system. Commit, branch, merge, examine history from three years ago, restore a deleted file. Nothing about that requires anyone's server.

What you don't get alone is the sharing โ€” an off-site backup, a copy other people can reach, and somewhere to have a conversation about a change. That's the job GitHub does, and it's not the only thing that can do it.

Git is free software, released under the GPLv2, developed by a large community rather than any single company. Its trademark is held by the Software Freedom Conservancy. Nobody can take it away, put it behind a paywall, or shut it down.

The useful takeaway: your version history belongs to you, on your disk, in an open format. Whatever happens to any hosting company, that stays true.

Back to home