Three areas, three responsibilities
Almost every confusion in Git traces back to mixing up the three areas. Internalizing them once will save you years of guesswork. The three are the working tree, the index (staging area), and the repository.
The working tree is the regular files on disk you edit. It has nothing to do with Git directly — it is just the current checkout. Editors, build tools, and your eyes interact with the working tree.
The index, also called the staging area, is the most surprising layer. It is a binary file at .git/index that holds a proposed next snapshot. When you say git add file.js, you are not "marking the file for commit" in some abstract list — you are copying the current content of file.js into the index as a blob and updating the index entry. If you change file.js again afterward, the index still has the version you added. This is why git diff shows working tree vs index, and git diff --staged shows index vs last commit.
The repository is everything under .git/: objects, refs, the index file itself, hooks, configs, packed history. git commit takes the current index, freezes it as a tree object, wraps it with metadata into a commit object, and points the current branch at that commit. Three areas, three commands: git add moves working tree → index, git commit moves index → repository, git restore moves either direction back.