Skip to content

The Three Trees

Git manipulates three distinct data structures, conventionally called trees (though “tree” is overloaded in Git terminology — see Git Objects). These are:

  1. The Working Directory (also called the working tree). The actual files on disk.
  2. The Index (also called the staging area or cache). A binary file at .git/index that encodes a snapshot of what the next commit will contain.
  3. The Repository (the .git/ directory). The committed history, stored as a directed acyclic graph of objects.

Almost every Git command is a transformation between these three trees. Understanding this model makes Git”s behavior predictable, even for commands that appear confusing (like git checkoutWhich can mean different things depending on context).

stateDiagram-v2
    [*] --> WorkingDirectory: git clone / git init
    WorkingDirectory --> Index: git add
    Index --> Repository: git commit
    Repository --> WorkingDirectory: git checkout
    Repository --> Index: git reset --soft
    Index --> WorkingDirectory: git restore --staged

    state WorkingDirectory {
        [*] --> WD: files on disk
    }

    state Index {
        [*] --> IDX: .git/index binary
    }

    state Repository {
        [*] --> REPO: .git/objects/
    }

The working directory is the directory on your filesystem where you edit files. It is a checkout of a particular commit”s tree — Git extracts the files referenced by a tree object and writes them to disk.

  • Mutable: You can edit files freely. Git does not track changes until you explicitly stage them.
  • Possibly dirty: The working directory can differ from both the index and the HEAD commit. The difference between the working directory and the index is what git diff shows by default.
  • Not versioned: Deleting a file from the working directory does not delete it from Git history. It merely stages the deletion (if git add is run).

Git classifies files in the working directory into two categories:

StateDefinitionShown by
TrackedFile is in the index (either as a new addition or inherited from the last commit).git diff (modified), git status (deleted)
UntrackedFile is not in the index and not in .gitignore.git status (untracked files)

Files listed in .gitignore are ignored — they are not tracked and git status will not mention them.

Git’s three trees are the working directory (your desk), the staging area (your outbox), and the repository (the archive). When you git add, you move changes from the desk to the outbox. When you git commit, you file the outbox into the archive. This three-stage process lets you craft commits carefully: you can stage some changes and leave others, creating clean, logical commits. Understanding these trees is the foundation for every Git operation.