Everything in git is three places
WORKING TREE STAGING (index) HISTORY (commits)
your actual files --add--> what will commit --commit--> permanent snapshots
▲ |
└───────────────── restore / checkout ───────────────┘
Working tree: the files as they are on disk right now. Staging area: a draft of your next commit — you choose exactly what goes in with git add. History: immutable snapshots, each with an ID (hash), author, and message.
Once this clicks, every confusing git message translates instantly: "Changes not staged" = working tree differs from staging. "Changes to be committed" = staging differs from history.
Why ops teams are fanatical about it
Every change to production infrastructure should answer four questions: what changed, who changed it, when, and why. A git commit answers all four in one object. When an incident starts, git log on your infra repo is the first "what changed?" you check.
A commit is a snapshot, not a diff
Git stores the full state of the project at each commit (deduplicated under the hood). Diffs are computed between snapshots. That's why checkout of any commit is instant and complete — you're not replaying patches.
The vocabulary
repository the .git directory — the whole database of history
commit one snapshot + message + author + parent pointer
branch a movable name pointing at a commit (that's ALL it is)
HEAD the name of "where you are right now"
remote another copy of the repo (usually on GitHub/GitLab)