A 32-minute working session on what Git actually does under the hood — the snapshot model and commit graph, the three areas, branching and merging, rebase trade-offs, collaboration with remotes and pull requests, the workflow that fits your team, and how to undo almost anything safely.
Most confusion with Git comes from picturing it wrong. Git does not store a list of file edits or diffs. It stores a series of full snapshots of your project, each one pointing back to the snapshot it came from. Get this one picture right and almost every command stops feeling like magic.
Each commit names its parent and a full snapshot. Newest first, the arrows point backward in time.
commit → tree → blobs. Unchanged files reuse the same blob, so a snapshot is cheap.
A pointer to the commit (usually via a branch) that your next commit will build on. "Detached HEAD" just means it points straight at a commit, not a branch.
A branch like main is just a movable label pointing at one commit. Making a commit moves the label forward — that is the whole mechanism.
History is a directed acyclic graph — commits with parent edges, no cycles. Merges give a commit two parents; that is the only way the graph branches and rejoins.
A commit doesn't snapshot your files directly. There is a deliberate middle step — the staging area — that lets you choose exactly what goes into the next commit. Understanding these three places is the difference between fighting Git and steering it.
git add copies a file's current content into the stage; git commit seals whatever is staged into a new snapshot. Files you edited but didn't stage are simply left out.add stages a draft; commit seals it; restore pulls a clean copy back the other way.
git add -p stages parts of a file (hunks), so a single messy editing session becomes several focused commits.git status always shows the split: staged, modified-but-unstaged, and untracked. Read it before every commit.Only the staged bucket enters the commit. The rest stays in your working tree, untouched.
Because a branch is just a pointer to a commit, creating one is instant and costs nothing. You work on a branch, then merge it back to bring its commits into another line of history. There are two ways that join can happen.
git switch -c feature creates a new label at your current commit and moves HEAD onto it. New commits push that label forward while main stays put.If main hasn't moved, Git just slides its label up to the branch tip. History stays linear.
When both branches have new commits, Git makes a merge commit M with two parents to tie them together.
A conflict isn't an error — it's Git asking you to pick between two edits to the same lines. Edit, stage, commit.
Conflicts only happen when two branches change the same lines of the same file. Small, frequent merges keep them rare and tiny — which is the whole argument behind the workflows in section 06.
Both bring one branch's work onto another. Merge records what really happened — two lines that met. Rebase rewrites your commits as if you had started from the latest tip, producing a clean straight line. Neither is "correct"; they optimize for different things.
Keeps every commit and records the join. History shows the branch really existed — at the cost of a busier graph.
A' and B' are copies of your commits with new hashes. The graph is clean; the originals are gone.
squash merge) into main.A squash merge collapses every commit on a branch into a single new commit on the target. You get one tidy entry per feature in main, and the branch's noisy work-in-progress commits never land in shared history. Popular on GitHub and GitLab for exactly that reason — just know you lose the per-commit granularity of the branch.
Git is distributed, so a server isn't special — it's one more clone that everyone happens to agree on. You fetch to download its commits, push to upload yours, and use a pull request as the place where humans review before code joins the shared line.
origin. Your local origin/main is a read-only snapshot of where the server's main was the last time you talked to it — not a live view.fetch downloads without touching your work; pull = fetch + merge; push uploads your commits.
origin/* pointers but never changes your branches or files — always safe to run.fetch then merge (or rebase with --rebase). It does change your branch, so it can conflict.main to origin/main so Git can say "ahead 2, behind 1."main.The Git engine is identical everywhere; you're choosing the collaboration platform around it. One line each — pro, con, and when it wins.
Choose when you want maximum reach, open source visibility, or the path of least resistance for a new team.
Choose when you want one vendor end-to-end, or you need to run the whole stack inside your own infrastructure.
Choose when your team is already standardized on Atlassian and you want tight issue-to-code traceability.
Git imposes no process. A branching workflow is the convention your team agrees on for how branches are named, how long they live, and how work reaches production. The honest truth: simpler workflows win for most teams — complexity should be earned by a real constraint.
Fits teams shipping continuously with solid CI — the modern default for product engineering.
main), short feature branches, review by PR, deploy on merge.main frequently; offers no built-in slot for parallel released versions.Fits most web apps and services with continuous deployment — start here unless you have a reason not to.
develop, release, and hotfix — useful when you maintain several shipped versions at once.Fits versioned/desktop/on-prem software with scheduled releases — rarely the right call for a SaaS that ships daily.
Commits you make are kept around even after you "lose" them — the reflog remembers where HEAD has been. Knowing four recovery tools turns most scary moments into a two-command fix.
HEAD has pointed to, kept for ~90 days. Botched a rebase or a hard reset? git reflog shows the commit you were on a moment ago, and git reset --hard HEAD@{1} puts you back.Rewrites local history — great before pushing, dangerous after. --soft keeps changes staged, --hard discards them.
Makes a new commit that cancels an old one. Safe on shared branches because it never rewrites history.
git bisect binary-searches between a known-good and known-bad commit to pinpoint the one that broke things — log(n) tests, not n.
Five quick questions on the commit model, staging, merge vs rebase, remotes, and recovery — instant feedback, no sign-in.
Navigate with ← → or scroll · back to library