From Git SCM Wiki
Revision as of 22:58, 15 January 2010 by Warthog9 (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

What is the index?

Many a times the subject comes up on the mailing list: "Why keep the index?" or, "The index is a performance trick."

The truth is: the index is a staging area. Every SCM has it, but git shows it to you, and uses it effectively.

A staging area

For those used to CVS or similar: What happens when you do

cvs add some.file
cvs commit some.file

The first command, cvs add some.file does not commit the file, right? Where has it gone? Answer: into the staging area.

With the second command, cvs commit some.file, you can finally commit. But what happens to the other modified files? Are they committed? Answer: no, the last revision is updated with the new version of some.file, "in the staging area", and then committed.

So really, it is neither a new concept, nor an intimidating one. The index comes naturally to you when you say

git add some.file

Now, the file is in the index. And here comes the difference to CVS: once you put something into the index, a simple git diff will only show differences with respect to the indexed version. Which means that you will not see any differences to some.file, once you put it into the index. The reason: git assumes that you know what you are doing. If you put something into the staging area with git add, remove a file with git rm, or put a modified version of a file into the staging area with git update-index some.file, git assumes that you want to commit this state, and will not bother you by showing differences you are most likely not interested in.

One special case exists:

git commit some.file

In this case, git assumes that you want to create a temporary staging area from the tip of the current branch ("HEAD"), update some.file, and commit the resulting state. After you committed that state, the staging area is resurrected as it was before that commit.

This operation ("save the current staging area, construct a new one, commit it, and then restore the staging area") seems a bit illogical, since you would usually expect only one staging area. However, in practice it happens quite often that you slap your forehead, because you forgot to commit something very important. So, just edit the respective files, commit just these, and continue with what you were doing before you hurt yourself (slapping your forehead).

In essence: The index is a staging area for the next commit, but for convenience, passing filenames explicitely to git commit builds a temporary staging area from the latest revision and the current version of the provided files before committing that state.


Normally, a git user will rarely be exposed to the index, if he/she is not committing a revision. But there is one notable exception: merges.

When you merge the work of others, sometimes conflicts happen. These are put in the index. (Strictly speaking, the whole merge is done inside the index by inserting the current version, the version of the branch-to-be-merged, and the merge base (common ancestor) into the index, and merging them using a three-way-diff. If there are no conflicts, these three entries are collapsed into a single entry. Otherwise the three entries stay there, with the common ancestor being replaced by the result of the merge.)

Again, git is intelligent about what to show you upon a git diff: those entries which merged cleanly are already updated in the staging area. It is unlikely that you want to see these differences right now, because you have to fix up conflicts -- if there are any. So, a git diff will show you a combined diff, i.e. a simultaneous diff of the merged-with-conflicts file against both the current version and the version in the branch-to-be-merged.

Now you know what the index is good for.

Personal tools