Introduction
The index, also called the staging area or the cache, is one of Git's distinguishing features. It is a binary file at .git/index that holds the tree you intend to commit next. Understanding the index removes most of the mystery from git status output.
Why it exists
The index lets you compose a commit deliberately rather than dumping every change at once. You can edit ten files but commit only the three that fix one bug, leaving the rest staged for a later commit. This decoupling enables clean, atomic history.
Inspecting the index
Two commands compare the three areas:
git diff # working tree vs index
git diff --staged # index vs HEAD
git diff HEAD # working tree vs HEAD
The plumbing command git ls-files --stage shows the raw contents of the index, including SHA-1 hashes:
git ls-files --stage
Staging changes
git add file.txt # add or update
git add . # add everything from cwd down
git add -u # update tracked files only
git add -p # interactive hunk-by-hunk
git add -N new.txt # intent-to-add (track empty)
Unstaging
If you staged something by mistake, take it out without losing the edit:
# Modern (Git 2.23+)
git restore --staged file.txt
# Older syntax, still works
git reset HEAD file.txt
The index in conflicts
During a merge conflict, the index gains three entries per conflicted path: stage 1 is the common ancestor, stage 2 is "ours", stage 3 is "theirs". git ls-files -u shows them:
git ls-files -u
Resolving the conflict means writing a final version and git add-ing it, collapsing back to a single stage-0 entry.
The index file format
The index is a binary format documented in the Git source under Documentation/gitformat-index.txt. It begins with a 12-byte header (signature DIRC, version, entry count) followed by sorted entries. Several optional extensions add caching: TREE caches subtree hashes for fast write-tree, and UNTR caches untracked-file lists for fast git status. Modern Git also supports a sparse index that elides entries outside the cone you have checked out:
git sparse-checkout init --cone
git config core.sparseCheckoutCone true
git update-index --test-untracked-cache
Common mistakes
Believing that git add is final. It is not: you can stage, edit again, and stage again. The index is just the next commit's draft. Another classic confusion: editing a staged file, then committing, and being puzzled that the new edits are not included. git add captures a snapshot at the moment you run it; subsequent edits live only in the working tree. Run git diff (no flags) to see what is staged-but-then-modified. Lastly, never delete .git/index manually; rebuild it with git read-tree HEAD if it ever becomes corrupt.