Guide

Most engineers learn Git as a list of commands: add, commit, push, plus a search engine for everything else. That works until a rebase goes wrong, a force-push erases a teammate's work, or someone types git reset --hard. Then the command list stops helping, because it does not say what Git is.

Git is simpler underneath. It is a content-addressed object store, a key-value store where each key is the hash of its value. It holds four kinds of objects, plus a few refs, which are named pointers into a graph of commits. Every command, from merge to cherry-pick to rebase -i, creates objects or moves pointers.

Two consequences follow. Almost nothing is truly lost. And most "disasters" are undone by moving a pointer back.

Concepts in this section

Read them in order. The first two explain the model. The rest use it.

StepConceptWhat it answers
1Git's object storeWhat does Git actually store, and why are IDs hashes?
2Refs, HEAD and the reflogWhat is a branch, and how do I get a lost commit back?
3Merge, rebase and squashWhat does each way of combining branches produce?
4Editing history and recovering workHow do I clean up commits, and undo a bad move?
5Bisect regressionsHow do I find the commit that broke something?
6Team workflowsTrunk or GitFlow, small PRs, and monorepo or polyrepo?

Common mistakes

  • Treating commands as a memorized list. Learn the model, and the commands follow.
  • Rewriting shared history. Rebasing commits others have built on forces everyone to untangle duplicates.
  • Panicking after a bad reset or rebase. The old commits are usually still there. Check the reflog first.
  • Keeping work only in the working directory. Uncommitted changes that get overwritten cannot be recovered. Commit early, then squash later.

Key takeaways

  • Git stores four object types (blob, tree, commit, tag) by content hash. History is a graph of hashes, so changing one byte changes every hash after it.
  • A branch is a file containing a commit hash. Creating one is instant.
  • The reflog records pointer moves for about 30 to 90 days, which makes most mistakes reversible.
  • Merge preserves history, rebase rewrites it into a line, and squash collapses a branch into one commit. Never rebase shared commits.
  • Small PRs and trunk-based development keep Git work calm, and git bisect finds regressions in about log2(N) steps.

Further learning

MIT's Missing Semester lecture builds Git from its data model up, the same approach as this section, with live demos.

Lecture 6: Version Control (git) (2020)Missing Semester

Pro Git: Git Internals, Plumbing and Porcelain is the reference for the object model.

The Missing Semester of Your CS Education (MIT) covers the wider set of tools around Git.