Express course · No. 17
Git records every version of your project and lets a whole team change the same files without overwriting each other. Almost all of the fear around it comes from unfamiliar words — commit, branch, rebase — not from real difficulty. Learn the handful of terms and Git turns from a source of dread into the calmest safety net you'll ever have.
Essence only · One picture per idea · Learn the words
Before the commands, the problem. Once you feel the pain version control removes, every feature of Git reads as an obvious answer instead of arbitrary jargon.
The folder full of _final_v2_FINAL files
A desk buried in report.doc, report_v2.doc, report_final.doc, report_final_FINAL.doc — nobody sure which is current, and the good version from Tuesday lost forever.
Everyone has lived the manual way of keeping versions: copy the file, add a suffix, hope. It falls apart instantly — you can't tell which is newest, you can't get back a version you overwrote, and two people editing means one of them loses their work. Version control is the tool built to end this: one project, with its entire history kept safely and every version recoverable.
Git keeps a timeline of snapshots
A camera that photographs your whole project each time you say "save this" — so you can flip back to exactly how everything looked at any past moment.
Git is the version control system nearly everyone uses. It records your project as a series of snapshots — each one a complete picture of all your files at a moment you chose to save. The result is a timeline you can travel: see what changed, when, and by whom, and return to any past state. It's a save button that never forgets a single save.
A repository is the project plus its whole history
A book that carries every draft it ever was, bound into the back — you hold the current text and the complete record of how it got there, together.
A repository (or repo) is your project folder once Git is tracking it: the current files plus the entire hidden history of every snapshot ever taken. Clone a repo and you get not just today's code but the whole story. This is the unit you work in — a repo is "a project Git remembers," and everything else in this course is something you do inside one.
Version control replaces the folder of _final_FINAL copies with one project and a complete, recoverable history. Git keeps that history as a timeline of snapshots.
The single most important word in Git is commit — one saved snapshot in the timeline. Understand how a commit is made and you understand the heartbeat of the whole system.
A commit is one saved snapshot
A photograph of your whole project at a chosen instant, filed with a note saying what this moment was — pinned permanently to the timeline.
A commit is one snapshot in your project's history — a recorded state of the files, with a unique ID and a note. Each commit points back to the one before it, forming the chain that is your history. You don't commit constantly; you commit at meaningful points — "added login," "fixed the date bug" — so the timeline reads as a sequence of deliberate steps, each one a place you can return to.
The staging area: pack the box before you seal it
A shipping box on your desk: you place in exactly the items for this shipment, leaving others aside, and only then tape it shut and send it.
Git doesn't snapshot everything you changed automatically. First you choose which changes go into the next commit by staging them — adding them to the staging area, the box you're packing. Then the commit seals just that box. This two-step — stage what belongs together, then commit — is why Git history can be clean: you decide exactly what each snapshot contains instead of dumping every change in at once.
The message is a note to the future
Labelling that sealed box with what's inside — so months later, someone scanning the shelf knows what each one holds without opening it.
Every commit carries a commit message explaining what changed and why. It feels like a chore and it's pure gold later: when you're hunting the change that broke something, or understanding why a line exists, the messages are the story of the project. A good message ("fix timezone bug in invoice export") turns history from a wall of cryptic IDs into a readable log. Write them for the person who reads them in six months — usually you.
HEAD is your you-are-here marker
The "you are here" dot on a map of the timeline — it marks which snapshot you're currently standing on.
HEAD is Git's pointer to where you currently are in the history — normally the latest commit on your current line of work. When you make a new commit, it's added right after HEAD, and HEAD moves forward to it. You rarely touch HEAD directly, but the word appears everywhere, and knowing it just means "my current position in the timeline" demystifies most of what you'll read.
A commit is one saved snapshot. You stage the exact changes that belong together, then seal them with a message — and HEAD marks where you stand.
Branches are where Git stops being a fancy save button and becomes a way for many people — or many ideas — to move at once without stepping on each other.
A branch is a parallel line of work
Photocopying the manuscript so you can scribble a bold rewrite on your copy, while the original stays clean and others keep working on it.
A branch is an independent line of development — your own copy of the timeline where you can make commits without affecting anyone else's work. You start a branch to build a feature or try an idea, commit freely on it, and the main version stays untouched until you're ready. Branching is how a team works on ten things at once in one repo without chaos: everyone on their own line.
main is the trusted line
The official, shelved edition of the book that everyone trusts — drafts happen elsewhere, and only finished, approved work gets bound into it.
By convention, the primary branch is called main (you'll still see master in older repos). It's meant to hold the stable, working version of the project — the one you'd ship. New work happens on other branches and only joins main once it's ready and reviewed. Treating main as the trusted line, never the scratchpad, is the simple discipline behind most healthy team workflows.
Switching branches changes your files
Swapping which draft is open on your desk — the same desk, but now showing a completely different version of the work, instantly.
When you switch (or check out) a branch, Git changes the files in your folder to match that branch's snapshot. Move to your feature branch and your edits appear; switch back to main and they vanish from view (safely stored, not lost). Branches are cheap and instant in Git, which is why creating one per feature or fix is normal and encouraged — not a heavyweight act but an everyday move.
A branch is a parallel line of work where you commit freely without disturbing anyone. main is the trusted version; new work lives on its own branch until it's ready.
Work that splits onto branches eventually has to come back together. Merging is how Git rejoins the lines — and the conflict is the one moment it needs you to decide.
Merging brings two branches back together
Folding the edits from your separate draft back into the official manuscript, so the book now contains both the original and your new chapter.
Merging combines the commits from one branch into another — typically folding a finished feature branch back into main. Git looks at what changed on each side and weaves them into a single timeline that contains both sets of work. Most of the time this is automatic and effortless: the two branches touched different files or different parts, and Git just stitches them together.
A conflict is two edits to the same line
Two editors who both rewrote the exact same sentence differently — no machine can know which one you meant, so it stops and asks you.
A merge conflict happens when both branches changed the same part of the same file in incompatible ways. Git can't guess which version is right, so it pauses and marks the spot, showing both versions side by side. This isn't an error or a disaster — it's Git correctly refusing to silently throw away someone's work. Conflicts feel scary the first time precisely because the stakes (don't lose work) are clear.
Resolving a conflict is just choosing
Reading both rewritten sentences, then writing the final version you actually want — keeping one, the other, or a blend — and moving on.
You resolve a conflict by editing the marked file to the version you want — keep yours, keep theirs, or combine them — then committing the result. That's the whole mystery: a conflict is Git handing you a decision only a human can make, and resolving it is making that decision. Conflicts get smaller and rarer when branches are short-lived and you merge often, so the two sides never drift far apart.
Merging weaves two branches into one timeline. A conflict is just two edits to the same line — Git refusing to guess, and asking you to choose.
So far everything lives on your machine. Working with others — or backing up your work — means connecting your local repo to a shared one in the cloud.
Local and remote are two copies
Your personal working copy of the manuscript at home, and the shared master copy in the office that the whole team keeps in sync with.
Git is distributed: you have a full copy of the repo on your machine (local), and there's usually a shared copy on a server (remote) — on a service like GitHub or GitLab. You do all your work locally — fast, even offline — and sync with the remote to share it and pull in others' work. The default remote is conventionally named origin. Two copies, kept in step on purpose.
Clone, push, pull, fetch
Photocopying the office master to take home (clone), mailing your finished pages in (push), and collecting everyone else's new pages (pull).
Four words move work between local and remote. Clone makes your first local copy of a remote repo. Push sends your commits up to the remote so others can see them. Pull brings others' new commits down into your copy. Fetch downloads what's new without merging it yet, so you can look first. Master these four and you can collaborate — they're the entire vocabulary of staying in sync.
Pull requests are how teams review work
Submitting your new chapter to the editors, who read it, comment, and approve before it's bound into the official book.
On platforms like GitHub, you usually don't merge straight into main. You push your branch and open a pull request (PR) — a proposal to merge your work, where teammates review it, leave comments, and approve before it joins main. It's the checkpoint where a second pair of eyes catches problems and the team agrees a change is ready. The PR is where most real-world Git collaboration actually happens.
Local is your copy; remote (origin) is the shared one. Clone, push, pull, and fetch keep them in step — and a pull request is where the team reviews before merging.
The deepest comfort of Git is that almost nothing is ever truly lost. Knowing how to read the history and step back safely is what turns Git from scary into reassuring.
The log is the story of the project
Flipping through the dated, labelled stack of every draft — seeing exactly what changed at each step and who made it.
The log is the list of commits — your project's history in order, each with its message, author, and time. It answers "what happened, and when?" and is the starting point for understanding any codebase or hunting any bug. When something breaks, the log lets you find the exact commit that introduced it, because every change is recorded. History you can read is history you can debug.
Undo safely: revert versus reset
Two ways to undo a mistake: add a clearly-noted correction to the record (revert), or quietly tear the last page out as if it never happened (reset).
Git gives you safe ways back. Revert creates a new commit that undoes a previous one — the mistake stays in history, with its reversal recorded on top, which is honest and safe for shared work. Reset moves you back to an earlier commit, rewriting the recent history as if those commits weren't there — powerful, but dangerous on work others already have. The rule of thumb: revert in public, reset only on private, local work.
Rebase replays your work; respect the golden rule
Instead of stapling your side-draft onto the manuscript with a visible seam (merge), you re-copy your edits cleanly on top of the latest version, as if you'd started from it (rebase).
Rebase is an alternative to merge: instead of joining two lines with a merge commit, it replays your commits on top of another branch, making a tidy, straight-line history. It's great for cleaning up your own branch before sharing. But it rewrites commits, so the golden rule is: never rebase history that others have already pulled. Rewrite shared history and you desync everyone. Rebase your private work; merge to combine shared work.
The log is the readable story; revert and reset are your ways back. Rebase makes tidy history — but never rewrite history others have already pulled.
Git's commands are many, but good practice is a short list of habits. Follow them and Git stays a calm safety net instead of an occasional emergency.
Small, focused commits with clear messages
A photo album where each picture captures one clear moment with a caption — far more useful than one blurry shot of everything at once.
Commit small and often, with each commit a single coherent change and a message that explains it. Tiny, well-labelled commits make history readable, bugs easy to trace, and undos surgical — you can revert one precise change without losing the rest. A giant commit dumping a week of mixed work is the opposite: impossible to review, untangle, or partly undo. The discipline costs seconds and pays back for the life of the project.
A branch per feature, merged often
Each new chapter drafted on its own copy and folded back in while it's still small — so no draft drifts so far from the book that rejoining it becomes a battle.
Do each piece of work on its own branch, keep it short-lived, and merge it back frequently. Long-lived branches drift far from main and turn merging into a painful pile of conflicts; small branches merged often stay easy. Pair it with pull before you push — bring in others' changes first — so you integrate continuously instead of colliding at the end. This rhythm is the heart of smooth team Git.
- Pull the latest before you start, so you build on current work. - Work on a branch, never directly on a fragile main. - Make small commits with clear messages as you go. - Merge often while branches are still short, to keep conflicts tiny. - Push your work and open a pull request for review. - Undo with revert on shared work; never rebase history others have.
- repository / commit / message — the tracked project, one snapshot, and its note. - staging area / HEAD — the box you pack before committing, and your you-are-here marker. - branch / main — a parallel line of work, and the trusted version. - merge / conflict — rejoining branches, and the same-line clash you resolve. - local / remote / origin — your copy, the shared copy, and its default name. - clone / push / pull / fetch — the four moves that keep copies in sync. - pull request / revert / reset / rebase — review, safe undo, and rewriting history.
- Your history reads like a clear story of small, captioned steps. - New work lives on branches; main always works. - You pull before you push and merge while branches are still small. - You reach for revert on shared work and never rewrite shared history. - Git feels like a safety net — you experiment freely, knowing you can always get back.
Good Git is a few habits: pull first, branch your work, commit small with clear messages, merge often, and review before you merge. The commands are many; the discipline is short.