By admin , 28 April 2026

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.