Git glossary

20terms in plain English — the vocabulary Git’s error messages assume you already know. Worth skimming once: most confusing errors become obvious the moment these click.

Jump to a term

HEAD~1 vs HEAD^

HEAD~1 means the first parent, one generation back. HEAD^ means the same thing for an ordinary commit, but on a merge commit HEAD^2 selects the second parent. Use ~ to walk backwards in time and ^ to choose between a merge's parents.

Index (staging area)

The commit you're composing. git add copies file contents into it, git commit turns it into a permanent snapshot. It's why you can edit a file after staging and commit the older version.

Working tree

The actual files on your disk. Changes here exist nowhere else until you stage or commit them, which is why they're the only thing Git genuinely cannot recover.

Blob / tree / commit

The three object types. A blob is a file's contents, a tree is a directory listing pointing at blobs and other trees, and a commit points at one tree plus its parent commits.

Dangling / unreachable object

An object no reference points to any more — a dropped stash, a deleted branch's commits, or a file staged but never committed. git fsck finds them, and garbage collection eventually deletes them.

Reflog

A local journal of every position HEAD and each branch has held, kept for about 90 days. It's the reason a bad reset, rebase or branch deletion is almost always reversible.

Fast-forward

A merge or push where the target simply moves forward along existing history because nothing diverged. A push that isn't a fast-forward gets rejected, because completing it would orphan commits.

Merge base

The most recent common ancestor of two branches. Every merge and every three-dot diff is computed relative to it, which is why 'unrelated histories' — no shared ancestor — stops a merge dead.

Upstream / tracking branch

The remote branch your local branch is paired with. It's what makes bare git push and git pull know where to go, and what 'ahead 2, behind 3' is measured against.

origin vs upstream

Just naming conventions for remotes. origin is normally where you cloned from; in a fork workflow origin is your fork and upstream is the original project. Git attaches no special meaning to either.

Detached HEAD

HEAD points at a commit rather than a branch, which happens when you check out a hash or tag. Commits made here belong to no branch and become unreachable once you switch away.

Fetch vs pull

Fetch downloads new commits and updates origin/* without touching your files — always safe. Pull is a fetch plus an immediate merge or rebase into your branch, which is why it can surprise you.

Rebase

Replaying your commits onto a new base, creating new commits with new hashes. Produces linear history, and must never be done to commits others have already pulled.

Cherry-pick

Copying the change from one commit into a new commit on your branch. The result is a duplicate change with a different hash, not a link to the original.

Force-with-lease

A force push that first checks the remote is still where you last saw it, and aborts if someone else pushed. Always prefer it over --force, which overwrites unconditionally.

Bare repository

A repository with no working files — just the object database and refs. It's what a server hosts, and what git clone --bare or --mirror produces for backups.

Stash

Uncommitted work parked on a stack as real commit objects. Because they're ordinary commits, a stash you dropped by accident can usually still be recovered with git fsck.

Refspec

The src:dst mapping that tells fetch or push which refs move where. It's why git push origin :branch deletes a branch — you're pushing nothing into it.

Porcelain vs plumbing

Porcelain commands (log, commit, merge) are the friendly interface. Plumbing commands (rev-parse, cat-file, ls-tree) are the stable, scriptable internals the porcelain is built from.

How Git actually works

Git is a distributed version control system: it records the full state of your project every time you commit, and every clone carries the entire history rather than just the latest files. Created by Linus Torvalds in 2005 to manage Linux kernel development, it is now the default way software is tracked, shared and shipped. The practical consequence is that almost nothing you commit can be permanently lost — which is why this page exists.

Commits are snapshots, not diffs

Most people picture Git storing a list of changes. It doesn't — each commit records a complete picture of every tracked file, plus a pointer to its parent. Identical files are stored once and shared between commits, so this is far cheaper than it sounds, and it's why checking out any commit in history is instant.

Three places your work can live

The working directory is your actual files. The index (or staging area) is the commit you're composing. The repository is permanent history. Nearly every confusing Git error makes sense once you ask which of these three a command touches — and it's exactly what separates git reset --soft, --mixed and --hard.

Everything is content-addressed

Git hashes the contents of every file, tree and commit into a SHA identifier. Change one byte and you get a different hash, which is what makes history tamper-evident. It's also why staging a file makes it recoverable: the content is written into .git/objects at that moment and never modified again.

Branches are just pointers

A branch is a file containing a single commit hash. That's the whole implementation. Creating one is instant regardless of project size, deleting one throws away a pointer rather than any commits, and 'moving work between branches' really means pointing a different name at the same commits.

The reflog remembers everything

Git keeps a private journal of every position each reference has held — including states that no branch points to any more. This is the safety net beneath resets, rebases and deleted branches, and it's kept for 90 days by default. It's local only, so a fresh clone starts with an empty one.

Every clone is a full backup

Because clones contain the complete history, there is no single point of failure. A colleague force-pushing over your branch destroys one pointer on one server while the commits themselves survive in every clone that had fetched them. Distribution is what makes most Git disasters recoverable.