The Three States of Git
Git organizes every tracked file into one of three conceptual states: modified, staged, and committed. A file is modified when it has been changed on disk but Git has not yet been told to include that change in the next snapshot. It becomes staged once you run git add, which records it in the staging area (also called the index) as part of the next commit. It becomes committed once git commit writes that snapshot permanently into the local repository's object database. These three states map directly onto three physical locations Git manages: the working directory, the staging area (.git/index), and the .git directory itself (the repository proper).
Cricket analogy: A player's involvement moves through three physical locations — the practice nets where changes happen, the official team-sheet folder at the ground, and the match archive that permanently records who actually played once the toss happens and the game is committed to record.
The working directory
The working directory is simply the checked-out set of files you see and edit in your file manager or editor — a single version of the project pulled out of the compressed database in .git. Files here can be untracked (Git has never seen them), unmodified (matching the last commit), or modified (different from the last commit). Running git status is the fastest way to see which category each file currently falls into.
Cricket analogy: The actual playing eleven on the field is the working directory — a single live version pulled from the club's full historical database; a player might be a brand-new trialist, performing exactly as scouted, or visibly playing differently than their file suggests, and the coach's live radio check is the fastest way to know which.
The staging area (index)
The staging area is a binary file, .git/index, that stores a snapshot of what will go into your next commit — it is not simply a list of filenames but a full tree of blob references. This intermediate step is what lets you build a commit incrementally: you can stage only part of your changes with git add -p, review exactly what is staged with git diff --cached, and unstage without losing work using git restore --staged <file>. This separation between "what changed" and "what will be committed" is one of Git's most distinctive design decisions compared to older version control systems.
Cricket analogy: The official team-sheet document isn't just a list of names — it's a full record of each player's exact confirmed role and batting position; a captain can name only part of the squad first, review exactly who's confirmed so far, and pull a player off the sheet without sending them home from the ground.
$ git status
On branch main
Changes not staged for commit:
modified: src/api/routes.py
Untracked files:
models/user_v2.py
$ git add src/api/routes.py
$ git status
Changes to be committed:
modified: src/api/routes.py
Untracked files:
models/user_v2.py
$ git commit -m "Add pagination support to routes"
[main 4f9a1c2] Add pagination support to routes
1 file changed, 12 insertions(+), 2 deletions(-)
$ git status
Untracked files:
models/user_v2.py # still untracked — not part of the commitThe .git directory (repository)
Once git commit runs, Git takes everything currently in the staging area, wraps it into a new commit object pointing at the previous commit as its parent, and stores that object permanently (until explicitly rewritten) in the .git directory's object database. At this point the change is part of the project's committed history and can be viewed with git log, diffed against other commits, pushed to a remote, or checked out later — it is far more durable than a staged or modified change, both of which live only in your local working copy and index.
Cricket analogy: Once the umpires confirm the result, everything on the team sheet gets wrapped into the official match record pointing back at the previous match, filed permanently in the league archive — from then on it can be looked up, compared, cited, or replayed, far more durable than a team sheet that never made selection.
A useful analogy: the working directory is your desk where you're actively drafting, the staging area is an envelope you're carefully filling with the pages you've decided belong in today's letter, and the repository is the mailbox — once a commit is 'posted', it has a permanent, addressable record.
- The three states — modified, staged, committed — correspond to the working directory, the index, and the .git object database.
git addmoves changes from modified to staged;git commitmoves staged changes into a permanent commit.- The staging area lets you build a commit incrementally, staging only part of your working changes if desired.
git statusreports which state every tracked and untracked file is currently in.git diffcompares working directory to the index;git diff --cachedcompares the index to the last commit.- Committed snapshots are durable and addressable by hash; staged and modified changes are not yet part of history.
Practice what you learned
1. Which command moves a change from the 'modified' state to the 'staged' state?
2. What does `git diff --cached` compare?
3. Where is the staging area physically stored?
4. What is the effect of `git restore --staged <file>`?
5. Which of Git's three states corresponds to data that has been permanently recorded in the object database?
Was this page helpful?
You May Also Like
The Staging Area
Understanding Git's staging area (index) as the intermediate step between editing files and committing them, and why it gives you fine-grained commit control.
Committing Changes
How to create commits, write effective commit messages, and understand what a commit actually records in Git's history.
The Git Object Model
A deep dive into how Git stores data internally as blobs, trees, commits, and tags — the content-addressable database underlying every Git operation.
.gitignore and Clean Repositories
Learn how .gitignore patterns keep build artifacts, secrets, and local config out of version control, and how to handle already-tracked files that should be ignored.
Related Reading
Related Study Notes in Software Engineering
Browse all study notesMicroservices Study Notes
Software Architecture · 30 topics
Software EngineeringTesting & TDD Study Notes
Software Testing · 30 topics
Software EngineeringDesign Patterns Study Notes
Software Design · 30 topics
Software EngineeringSoftware Engineering Study Notes
Python · 40 topics
Software EngineeringSystem Design Study Notes
Architecture · 40 topics