Skip to content

Version Control · Git & GitHub

Foundations (the Git data model, branching & merging, the GitHub flow, and safe undo) · prereq 18 (Terminal & Scripting) — every command in this module runs in the shell that module builds fluency with. · ~1 day (4 reference submodules — the git model, branching & merging, remotes & the GitHub flow, and undoing safely). Reality check: this is the 80/20 on-ramp; real fluency (resolving a nasty conflict under pressure, reviewing someone else's PR well) is built through daily use.

Module 00 got you making one small commit on a branch, safely — the minimum needed to work in the repo at all. This module builds the rest of it: the mental model underneath every Git command, how to bring branches back together (merge vs. rebase), the team-level GitHub flow that turns a branch into a reviewed, merged change, and how to undo a mistake without breaking someone else's copy of the repo.

TL;DR — in 30 seconds:

  • Git stores snapshots linked in a chain; a branch is just a movable pointer to one commit — that one idea explains almost everything else in this module.
  • Merge joins two branches' history with a new commit; rebase replays your commits on top of another branch, rewriting their hashes — never rebase a branch someone else already has.
  • The GitHub flow — branch → commit → PR → review → merge — is how a team keeps main always deployable while work happens on short-lived branches.

Learning objectives

By the end, the junior can:

  • Explain a commit, a branch, and HEAD in terms of the underlying pointer model — not just "commands that work."
  • Choose merge or rebase for a given situation, and explain why rebasing a shared branch is unsafe.
  • Resolve a merge/rebase conflict by hand, without leaving marker lines behind.
  • Walk through the full GitHub flow (branch → commit → PR → review → merge) and explain what a pull request actually is (a GitHub feature, not a Git concept).
  • Pick the right undo tool — revert, reset, or restore — for a given mistake, based on whether the change is already shared.

Do it with Claude

Pair, Do and Prove run in Claude Code, with the onboarding-tutor skill. Click a button to copy the exact prompt, then paste it into Claude Code in this repo.

1. Learn · acquire the concept

No external course — read this brief, then go deeper in the four reference pages below.

Mental model (20 minutes):

Everything in this module builds on one fact: a commit is a snapshot, and a branch is a pointer to one. Once that's solid, the rest follows in order:

flowchart LR
    A["The git model<br/>commits · branches · HEAD · tags"] --> B["Branching & merging<br/>merge vs rebase · conflicts"]
    B --> C["Remotes & the GitHub flow<br/>push/pull · PR · review · merge"]
    C --> D["Undoing safely<br/>revert · reset · restore"]
  • The git model — commits are full snapshots chained by parent pointers; a branch is just a movable pointer to one commit; HEAD says which branch (or commit) you're currently on; a tag is a pointer that never moves.
  • Branching & merging — bringing two branches back together is either a merge (adds a joining commit, rewrites nothing, safe to share) or a rebase (replays commits on top of another branch, rewriting their hashes — safe only on a branch that's still yours alone).
  • Remotes & the GitHub flow — a remote is a bookmark for another copy of the repo; the GitHub flow (branch → commit → PR → review → merge) is the team pattern that keeps main always deployable.
  • Undoing safelyrevert (new commit that cancels a shared one), reset (moves your branch's pointer — safe only unshared), restore (undoes uncommitted file changes, never touches history).

Go deeper: The git model · Branching & merging · Remotes & the GitHub flow · Undoing safely

Check yourself — in one sentence, what's the difference between a branch and a tag?

A branch is a pointer that moves forward as you commit; a tag is a pointer that's fixed at the commit it was created on and never moves again.

Check yourself — you need to bring main's latest changes into your own, not-yet-pushed feature branch before opening a PR. Merge or rebase?

Either works, but rebase is the common choice here specifically because the branch is still yours alone (nobody else has pulled it) — it produces a clean, linear history with no extra merge commit. The moment the branch is shared, switch to merge.

Done when: you can explain, unprompted, why a branch is "instant to create" and why rebasing a shared branch causes problems for teammates — both follow from the same pointer model.

2. Pair · passive → active

Drive the onboarding-tutor:

  • "Draw me the commit graph for a feature branch, then walk me through what changes after I merge it into main versus what changes after I rebase it onto main."
  • "Give me a two-branch conflict scenario and make me resolve it — don't let me skip past the marker lines without explaining what each section means."
  • "Quiz me on the five steps of the GitHub flow, then ask me what happens if I skip the review step."
  • "Give me three different 'oops' scenarios (bad shared commit, bad local-only commit, accidental git add) and make me pick revert, reset, or restore for each — then justify it."

Common gotchas

  • Treating a branch like a full copy of the project. Fix: it's one pointer into shared commit history — see the git model for why that matters.
  • Rebasing (or force-pushing after a rebase) on a branch someone else already pulled. Fix: rebase only your own, not-yet-shared work; merge is the safe default once a branch is shared.
  • Reaching for git reset --hard on a commit that's already pushed. Fix: once a commit is shared, revert it instead — reset --hard rewrites what your branch points at, which breaks everyone else's copy.
  • Assuming a pull request is a Git feature. Fix: Git has no concept of a PR — it's GitHub's review layer on top of a pushed branch; the merge itself is an ordinary Git merge underneath.

Done when: you can pick the right tool — merge vs. rebase, or revert vs. reset vs. restore — for a scenario the tutor gives you, unprompted, and defend the choice.

3. Do · produce an artifact

Exercise — a full branch → conflict → resolve → GitHub-flow cycle, in a scratch repo:

  1. Create a throwaway repo outside the mono-repo (mkdir ~/scratch/git-practice && cd $_ && git init), add one file with a few lines of text, and make an initial commit.
  2. Create two branches off that first commit, branch-a and branch-b. On each, edit the same line of the file differently, and commit on each branch.
  3. Merge branch-a into a main-equivalent branch — confirm you get a clean merge commit (git log --graph --oneline --all).
  4. Now merge (or rebase) branch-b in too — this time it should conflict. Resolve it by hand: edit the file, remove the <<<<<<</=======/>>>>>>> markers, git add the file, then complete the merge (or git rebase --continue).
  5. Add a .gitignore with at least one pattern, confirm (with git status) that a matching new file is no longer flagged as untracked.
  6. Tag the current state as an annotated tag: git tag -a v0.1.0 -m "practice release".
  7. Make one more commit, then practice all three undo tools: git revert it, confirm the reverting commit appears in git log; separately, on a throwaway branch, git reset --soft back one commit and confirm the change reappears staged; git add a file and git restore --staged it to confirm it unstages without losing the edit.
  8. Write down, in your own words, the five steps of the GitHub flow this exercise's branch/PR shape maps onto — you don't need a real GitHub repo for this exercise, but if you have a personal one, push a branch and actually open a PR to see the review UI.

Done when: git log --graph --oneline --all shows a merge commit and a conflict you resolved correctly (no stray marker lines survive anywhere in the file); the tag exists (git tag lists it); and you can point to a concrete moment in the exercise for each of revert, reset, and restore.

4. Prove · understanding gate

Mandatory. Pass bar in the Socratic gate.

  1. The model: Explain what a commit, a branch, and HEAD each actually are — in terms of pointers and snapshots, not just "commands that work."
  2. Merge vs. rebase: Why did you choose the approach you used for each of the two branches in your exercise? What would have gone wrong choosing the other one on a branch someone else already had?
  3. Conflict: Walk through the exact conflict you resolved — what did each side (HEAD/feature) represent, and how did you decide what the resolved line should say?
  4. GitHub flow: Name all five steps in order, and explain what a pull request actually is (and isn't).
  5. Undo: For each of revert, reset, and restore, state the one question that decides whether it's the safe choice — and point to where you used it in your exercise.

Pass bar: you can defend every choice — merge vs. rebase, which undo tool, why the GitHub flow has a review step — by what it specifically prevents, not "that's just what you do." "It worked but I can't say why" = back to Pair.

5. Retain · fight forgetting

This module has no generated Anki deck yet. Recall by re-reading the four reference pages and re-running the Do exercise's conflict-and-resolve cycle with a different file and a different pair of conflicting edits, until you can predict — before running the command — whether a given merge will be clean or conflict. Done when you can walk through the whole exercise, cold, without checking the reference pages.

Key takeaways

  • A commit is a snapshot, a branch is a pointer. Nearly everything else in Git — why branching is instant, why deleting a branch doesn't delete commits, how reset works — follows from that one fact.
  • Merge adds a joining commit and rewrites nothing — safe on any branch, including shared ones. Rebase replays commits with new hashes — safe only on a branch that's still yours alone.
  • A conflict means two changes overlapped, not that you did something wrong — resolve by editing past the <<<<<<</=======/>>>>>>> markers, then git add and continue.
  • The GitHub flow (branch → commit → PR → review → merge) keeps main always deployable — a pull request is GitHub's review layer on top of an ordinary pushed branch, not a Git concept.
  • The undo decision is one question: has anyone else already seen this commit? Yes → git revert (adds a correction). No → git reset is fine. Uncommitted, not even a commit yet → git restore.

Go deeper — curated resources

Hand-picked external material to take this topic further — the best books, courses, talks, and writing. Cost is tagged Free, Free online (full text/course free on the web), or Paid.

  • Book · Pro Git — Scott Chacon & Ben Straub. The definitive Git book; the entire text is free to read online. Free online.
  • Interactive · Learn Git Branching — learngitbranching.js.org. Visual, in-browser exercises that make branching and merging finally click. Free.
  • Video · Missing Semester — Version Control (Git) — MIT. The Git lecture most CS courses skip, taught from the data model up. Free.
  • Game · Oh My Git! — bleeptrack & blinry. An actual game that visualizes a repository's internals as you run real commands. Free.
  • Docs · GitHub Skills — GitHub. Short interactive courses that teach GitHub workflows inside real repositories. Free.

Gate log (mentor fills on pass)

  • Date passed:
  • Passed by: / checked by:
  • Weak spots noticed (feeds system improvement):