More detail on the following is available from the Git concepts
chapter of the user-manual
[3] and gitcore-tutorial(7).
A Git project normally consists of a working directory with a
".git" subdirectory at the top level. The .git directory
contains, among other things, a compressed object database
representing the complete history of the project, an "index" file
which links that history to the current contents of the working
tree, and named pointers into that history such as tags and
branch heads.
The object database contains objects of three main types: blobs,
which hold file data; trees, which point to blobs and other trees
to build up directory hierarchies; and commits, which each
reference a single tree and some number of parent commits.
The commit, equivalent to what other systems call a "changeset"
or "version", represents a step in the project's history, and
each parent represents an immediately preceding step. Commits
with more than one parent represent merges of independent lines
of development.
All objects are named by the SHA-1 hash of their contents,
normally written as a string of 40 hex digits. Such names are
globally unique. The entire history leading up to a commit can be
vouched for by signing just that commit. A fourth object type,
the tag, is provided for this purpose.
When first created, objects are stored in individual files, but
for efficiency may later be compressed together into "pack
files".
Named pointers called refs mark interesting points in history. A
ref may contain the SHA-1 name of an object or the name of
another ref. Refs with names beginning ref/head/
contain the
SHA-1 name of the most recent commit (or "head") of a branch
under development. SHA-1 names of tags of interest are stored
under ref/tags/
. A special ref named HEAD
contains the name of
the currently checked-out branch.
The index file is initialized with a list of all paths and, for
each path, a blob object and a set of attributes. The blob object
represents the contents of the file as of the head of the current
branch. The attributes (last modified time, size, etc.) are taken
from the corresponding file in the working tree. Subsequent
changes to the working tree can be found by comparing these
attributes. The index may be updated with new content, and new
commits may be created from the content stored in the index.
The index is also capable of storing multiple entries (called
"stages") for a given pathname. These stages are used to hold the
various unmerged version of a file when a merge is in progress.