Git — Index - odigity/academy GitHub Wiki
The two obvious stores of state are:
- Repository — The collection of committed content, branches, and tags. (These are stored in
.git/objects/
and.git/refs/
, respectively.) - Working Tree — The files and directories in your project (not including
.git/
), which represent a particular snapshot from the repository plus whatever changes you've made but not committed.
However, between making changes to files and committing those changes is an intermediate step, called staging, which updates what's called the index. (Stored at: .git/index
)
The Index
The index (aka "stage", "staging area", and "cache") is a single binary file that stores a list of entries, each of which contains:
- a path to a file in your project
- the permissions on that file (when it was added to the index)
- the SHA-1 of the the file's contents (when it was added to the index)
The two primary purposes of the index are:
- represent which files are currently tracked
- determine what changes will be part of the next commit
Tracked vs Untracked
When you create a new file in your working tree, Git doesn't do anything with or to it until you add that file to the index (git add
).
It is considered untracked.
Once the file has been added to the index, it is considered tracked, and will be part of the next commit. Adding a file to the index is called "staging".
Tracked File States
A tracked file can be in one of three states:
- Committed — The current version is safely stored in your local repository.
- Modified — You have changed the file but have not staged or committed it yet.
- Staged — You have changed the file, and staged it after changing it. (The current version will go into your next commit.)
The commit operation simply uses the index to create the snapshot for the commit.
Note that you can modify a file, stage it, modify it some more, then commit. That commit will contain the staged version of the file — the one that contains the first set of changes, but not the second set.
Status and Diff
The git status
command will give you a summary of both the state of your working tree and the index:
- untracked files (that aren't ignored via
.gitignore
) - tracked files that have unstaged modifications
- tracked files that have staged modifications
The git diff
command can you show you either:
- the difference between the working tree and index (
git diff
) - the difference between the index and repository (
git diff --staged
)
Moving and Removing
Git doesn’t explicitly track file movement. If you rename a file in Git, no metadata is stored in Git that tells it you renamed the file. It will be recorded as a file deletion plus a new file. (However, Git is pretty smart about figuring that out after the fact.)
To remove a file from Git, you have to remove it from the index. (git rm
)
The next time you commit, the file will be gone and no longer tracked.