What Is Git? A Practical Guide to Version Control
Git is a distributed version control system. It records the state of a set of files over time, lets you move between those recorded states, and lets many people build on the same project without overwriting each other’s work.
That one-sentence answer is accurate but thin. The rest of this lesson unpacks what “recording state” actually means, why Git records it the way it does, and what that buys you in day-to-day engineering.
The short answer
Section titled “The short answer”Git tracks changes to files. You tell it which version of your files matters by creating a commit — a permanent, named snapshot of your entire project at one moment. Git keeps every commit you have made, so you can compare any two points in time, return to an earlier one, or split off a new line of work and merge it back later.
The word distributed means every copy of the project is a complete repository. Your laptop holds the full history: every commit, every branch, every file version. You do not need a server to look at history, create a commit, or switch branches. That single design decision drives most of what makes Git feel different from the version control systems that came before it.
The problem Git solves
Section titled “The problem Git solves”Before version control, teams managed history by hand. The evidence is still visible in any directory that has escaped a proper tool:
report.docxreport-v2.docxreport-v2-FINAL.docxreport-v2-FINAL-jim-edits.docxreport-v2-FINAL-jim-edits-USE-THIS-ONE.docxThat scheme fails in specific, predictable ways:
- It loses information. You know
v2came afterv1, but not what changed, who changed it, or why. - It does not merge. If two people edit the same file at once, someone’s work is discarded.
- It does not scale. Five files is annoying. Five thousand files across forty contributors is impossible.
- It cannot answer questions. “When did this stop working?” has no mechanical answer.
A version control system replaces the filename convention with a structured, queryable history. Git answers all four of those questions directly: it stores what changed, who changed it, when, and the message they wrote explaining why.
A brief history of source control
Section titled “A brief history of source control”Understanding the three generations of version control explains why Git looks the way it does.
Local version control (1980s, e.g. RCS) tracked file versions on a single machine, usually one file at a time. It gave you history but no collaboration.
Centralised version control (1990s–2000s, e.g. CVS, Subversion, Perforce) introduced a single server holding the authoritative history. Developers checked out a working copy, made changes, and committed back to the server. This made teamwork possible, but the server became a hard dependency: no network meant no commits, no history, no branching. If the server was lost and backups were stale, the project history was gone.
Distributed version control (mid-2000s, e.g. Git, Mercurial) gave every developer a full copy of the repository. Commits are local operations. History is queryable offline. The “central” repository became a convention — a copy everyone agrees to synchronise with — rather than a technical requirement.
Git itself was created in 2005 by Linus Torvalds for the Linux kernel project, after the kernel team lost access to the proprietary tool they had been using. The kernel’s requirements — thousands of contributors, very large history, patches arriving by email, and speed above all — shaped Git’s design directly.
The mental model: snapshots, not diffs
Section titled “The mental model: snapshots, not diffs”This is the single most useful idea for a beginner, and it is where many people’s intuition goes wrong.
Most older version control systems store history as a list of changes to files: file A gained
three lines, file B lost one. Reconstructing an old version means replaying those changes.
Git works the other way round. Each commit stores a snapshot of what every tracked file looked like at that moment. Conceptually, a commit is a complete picture of your project, not a description of what moved.
Three commits shown left to right. Each commit contains a full set of files. Commit A contains README, app.py and config.yml. Commit B contains the same three files with app.py changed. Commit C contains all three plus a new file, test.py. Each commit points back to the previous one.
In practice Git is efficient about this. Files that did not change between commits are not stored twice — both commits simply reference the same stored content. But the model you should hold in your head is snapshots. It makes branching, merging and history navigation far easier to reason about, and it is what Git’s commands actually behave like.
The core building blocks
Section titled “The core building blocks”Five concepts carry almost all of Git’s day-to-day behaviour.
Repository
Section titled “Repository”A repository is a project plus its complete history. Physically, it is your project directory
containing a hidden .git subdirectory. That subdirectory holds every commit, every stored file
version, and every branch pointer. Delete .git and you are left with ordinary files and no history.
Lesson 12 tours that directory in detail.
Commit
Section titled “Commit”A commit is one snapshot plus its metadata: author, timestamp, a message describing the change, and a reference to the commit that came before it (its parent). Every commit is identified by a 40-character hexadecimal object ID, computed from the commit’s own content:
a936f7ce6532d0e18aba39d1081bde0ee51895fdYou will usually see it abbreviated to the first seven or so characters — a936f7c. Because the ID is
derived from the content, it is effectively a fingerprint: change anything about the commit and you get
a different ID. This is what makes Git history tamper-evident.
Branch
Section titled “Branch”A branch is a movable pointer to a commit. That is the entire definition. It is not a copy of your files, not a directory, and not a separate folder somewhere. When you commit on a branch, the branch pointer moves forward to the new commit.
Because a branch is just a pointer — a file containing an object ID — creating one is nearly free. This is why Git workflows use branches liberally, where centralised systems treated branching as a heavyweight operation to be avoided.
A chain of three commits labelled A, B and C connected left to right. A label named main points at commit C. A second label named feature also points at commit C, showing that two branches can reference the same commit without duplicating any files.
Merging combines the work from two branches. Git looks at where the branches diverged and applies both sets of changes. When two branches changed different files — or different parts of the same file — Git resolves it automatically. When they changed the same lines, Git stops and reports a conflict, which you resolve by choosing what the combined result should be.
A conflict is not an error or a failure. It is Git declining to guess about a decision only a human can make.
Remote
Section titled “Remote”A remote is another copy of the repository, usually on a server, that you have given a short name to.
The conventional name for the main one is origin. You send commits to it with git push and retrieve
others’ commits with git fetch or git pull.
Nothing about a remote is special to Git — it is another repository. That is what “distributed” means in practice.
The basic workflow
Section titled “The basic workflow”Most Git work is a short loop. Here it is end to end, with real commands:
git statusgit add app.pygit commit -m "Handle empty input in the parser"git pushgit statusWhat it doesReports which files have changed, which of those are staged for the next commit, and which are untracked.
Why we run itIt is the cheapest way to see the current state before you do anything. Running it before add and before commit prevents most beginner mistakes.
Expected resultA short report listing your branch name and any changed, staged or untracked files. On a clean repository it says nothing to commit, working tree clean.
git add app.pyWhat it doesCopies the current content of app.py into the staging area (the index), marking that content for inclusion in the next commit.
Why we run itGit does not commit everything you changed. You choose what goes in. This lets you make one focused commit even when your working directory contains several unrelated edits.
Expected resultNo output. Silence means success. Run git status again and app.py moves to the Changes to be committed section.
git commit -m "Handle empty input in the parser"What it doesCreates a new commit from whatever is currently staged, recording it permanently with the message you supplied.
Why we run itThis is the operation that writes a snapshot into history. Until you commit, nothing is recorded.
Expected resultA summary line like [main 4ff2767] Handle empty input in the parser, followed by a count of files and lines changed.
git pushWhat it doesSends commits from your local branch to the corresponding branch on the remote repository.
Why we run itYour commits exist only on your machine until you push. Pushing is how you share them and how they get backed up.
Expected resultProgress output ending in a line showing the branch that was updated. This is the only step in the loop that needs a network connection.
That is the whole daily cycle for most work: change files, stage what belongs together, commit with a clear message, push to share. Lesson 7 walks through this hands-on with a real repository you build yourself.
Why the index exists
Section titled “Why the index exists”New users often ask why git add is a separate step. Why not have commit just save everything?
Because commits are the unit of understanding for everyone who reads your history later. If you fixed a bug, updated a dependency, and renamed a variable in one afternoon, three separate commits tell a readable story. One commit containing all three tells nobody anything.
The staging area — also called the index — is what makes that possible. It is a workspace where you assemble exactly the change you want to record, without needing to have made only that change on disk. Lesson 9 goes deep on how the index works.
Why developers use Git
Section titled “Why developers use Git”History that answers questions. git log shows what changed and why. git blame shows which
commit last touched a given line. When a bug appears, you can find the commit that introduced it
instead of guessing.
Safe experimentation. Branching is cheap, so trying an approach costs nothing. If it does not work, you delete the branch. The main line of work was never at risk.
Real parallel work. Several people can develop several features simultaneously and integrate them deliberately, rather than coordinating who is allowed to edit which file.
Review before integration. Because a branch is a self-contained unit of work, it can be reviewed as a unit before it becomes part of the main line.
Recovery. Committed work is very hard to lose. Git also keeps a local log of where your branches have pointed recently, which makes recovering from most mistakes possible.
Why DevOps and platform engineers use Git
Section titled “Why DevOps and platform engineers use Git”Git’s reach extends well beyond application source code. In modern infrastructure practice, the repository is frequently the control plane.
Infrastructure as code. Terraform configurations, Kubernetes manifests, Ansible playbooks and Helm charts live in Git. Infrastructure changes then get the same review, history and rollback story as application changes.
Pipelines triggered by commits. Continuous integration systems watch repositories. A push runs tests; a merge to the main branch can build and deploy. The commit becomes the unit of delivery.
GitOps. In this model, a Git repository holds the declared desired state of a system, and an agent continuously reconciles the running environment to match. Deploying means merging a commit; rolling back means reverting one.
Auditability. Because every change carries an author, a timestamp and a message, and because commit IDs are content-derived, a repository is a credible audit trail of who changed what and when.
Git compared to centralised version control
Section titled “Git compared to centralised version control”| Centralised (e.g. Subversion) | Distributed (Git) | |
|---|---|---|
| Where history lives | On the central server | In every clone |
| Committing | Requires the server | Local; no network needed |
| Viewing history | Requires the server | Local and fast |
| Branching cost | Often expensive; used sparingly | Very cheap; used constantly |
| If the server is lost | History may be lost | Every clone is a full backup |
| Working offline | Very limited | Nearly everything works |
| Central authority | Enforced by the tool | A convention teams agree on |
The trade-off is real: Git asks you to understand more concepts up front. Distributed history means learning about local versus remote state, and about merging as a normal activity rather than an exception. That is the cost of the model. This curriculum exists to make that cost small.
Common misconceptions
Section titled “Common misconceptions”“Git and GitHub are the same thing.” They are not. Git is the version control software; GitHub is one of several companies that host Git repositories. See Git vs GitHub.
“Git stores the differences between versions.” The model to hold is snapshots. Git optimises storage internally — including by storing some objects as deltas inside packfiles — but commits represent complete states, and that is what the commands behave like.
“A branch is a copy of my project.” A branch is a pointer to one commit. Switching branches updates the files in your working directory to match that commit; it does not move you into a different folder.
“Committing shares my work.” Committing is entirely local. Nothing leaves your machine until you push.
“git add tells Git about a filename.” git add records file content into the index. If you
edit the file after staging it, the staged content is still the older version until you stage it again.
This surprises nearly everyone once. Lesson 9 explains why.
“I need a server to use Git.” You do not. git init in any directory gives you a fully functional
repository.
“Git is only for code.” Git works well for any collection of mostly-text files: configuration, documentation, infrastructure definitions, research notes. It is less well suited to large binary files, which do not diff or compress usefully.
What You Learned
Section titled “What You Learned”- Git is a distributed version control system: every clone contains the project’s complete history.
- A commit is an immutable snapshot of your whole project, identified by a content-derived ID.
- A branch is a movable pointer to a commit, not a copy of your files.
- The index (staging area) is where you assemble exactly the change you want to record.
- Committing is local; sharing requires an explicit
push. - Git’s design came from the Linux kernel’s needs: speed, scale and distributed collaboration.
- Git underpins modern DevOps practice, from CI pipelines to GitOps.
Try It Yourself
Section titled “Try It Yourself”You do not need to install anything to do this one — it is a thinking exercise, and it will make the next lessons land harder.
- Pick a project you have worked on, code or otherwise.
- Write down three moments in its life you would want to return to.
- For each, note what you would want to know: what changed, who changed it, and why.
- Now consider: with only filenames and modification dates, could you answer any of those questions?
That gap between “the files I have” and “the history I want” is precisely what Git fills.
Next Lesson
Section titled “Next Lesson”Almost everyone new to Git meets GitHub at the same time, and the two blur together immediately. The next lesson draws a clean line between them: what Git does on your machine, what GitHub adds on top, and which parts of your workflow depend on which.