A tree object describes the contents of one directory. Each line in a tree is one entry:
100644 blob 5f7e9c12... README.md
100644 blob 8a3f2e91... index.html
040000 tree e2b5a91f... images
100644 blob b1d4a7e0... style.css
Four columns:
- Mode -
100644is a regular file,100755is executable,040000is a subdirectory,120000is a symlink,160000is a gitlink (submodule). Git stores the mode as a number;git ls-treealways prints it as six digits with a leading zero. - Type -
blobfor a file,treefor a subdirectory. - SHA - a pointer to the blob or tree object.
- Name - the filename or directory name within this directory.
The file content lives in a blob. The tree links a name to that content.
Recursive structure
A tree entry of type tree points to another tree object for a
subdirectory. This builds a hierarchy of tree objects that mirrors the
project's directory tree:
root tree
├── blob README.md
├── tree images/
│ ├── blob logo.png
│ └── blob banner.jpg
└── blob style.css
When a tree is created
On git commit. Before the commit, no tree exists; there is only
.git/index, which holds a flat list of paths. git write-tree converts
the index into a hierarchy of tree objects and returns the SHA of the root.
Inspecting tree contents
git cat-file -p <tree-sha>
git ls-tree HEAD # tree of the latest commit
git ls-tree -r HEAD # recursive, flat list of all files
Deduplication at the tree level
If a subdirectory has not changed between two commits, its tree object is identical. The parent tree points to the same SHA. Git deduplicates not only individual files but entire subdirectories.