Git read-tree: Read and Merge Trees into the Index
Use git read-tree to populate, empty, and merge the Git index from tree objects while understanding index stages and working-tree boundaries.
Advanced
The index is the destination
`git read-tree` reads the contents of one or more tree objects into Git's index. Without `-u`, it does not update files in the working tree. This makes it a plumbing command for moving tree state from the object database into the index.
TREE=$(git rev-parse HEAD^{tree})
GIT_INDEX_FILE=./lab-index git read-tree "$TREE"
GIT_INDEX_FILE=./lab-index git ls-files --stageQuick check
What does a plain `git read-tree <tree>` primarily change?
Empty the index with `--empty`
`--empty` does not read a tree. It replaces the index with an empty index. Use an isolated `GIT_INDEX_FILE` in experiments so you do not accidentally discard the real index.
GIT_INDEX_FILE=./lab-index git read-tree --empty
GIT_INDEX_FILE=./lab-index git ls-filesQuick check
What does `git read-tree --empty` do?
Build an index under a prefix
`--prefix=<prefix>/` preserves the existing index entries and reads the named tree beneath that directory prefix. Git refuses to overwrite an entry that already exists at the resulting path.
GIT_INDEX_FILE=./lab-index git read-tree --prefix=imported/ HEAD^{tree}
GIT_INDEX_FILE=./lab-index git ls-filesQuick check
What is the key effect of `--prefix=imported/`?
Use `--index-output` for a separate result index
`--index-output=<file>` writes the resulting index to another index file instead of replacing the index named by `GIT_INDEX_FILE`. This is useful for low-level experiments and temporary index workflows.
GIT_INDEX_FILE=./lab-index git read-tree --index-output=./result-index HEAD^{tree}
GIT_INDEX_FILE=./result-index git ls-filesDry-run checks without changing the index
`-n` / `--dry-run` checks whether the operation would fail without updating the index or working tree. It is especially useful before merge-like operations that could overwrite local state.
GIT_INDEX_FILE=./lab-index git read-tree --dry-run -m HEAD^{tree} OTHER^{tree}Quick check
What is the safety property of `--dry-run`?
Two-tree merges
With `-m` and two trees, `git read-tree` performs the low-level carry-forward checks needed for a fast-forward-style transition from one tree to another. It compares the existing index and working tree state with the first tree and refuses to overwrite conflicting local changes.
GIT_INDEX_FILE=./lab-index git read-tree -m OLD_TREE NEW_TREE
GIT_INDEX_FILE=./lab-index git ls-files --stageThree-tree merges create index stages
With three trees, `git read-tree -m <tree1> <tree2> <tree3>` prepares a three-way merge in the index. Stage 1 represents the common ancestor, stage 2 the current side, and stage 3 the other side. Paths that need a later merge-resolution step can therefore coexist as separate index entries.
GIT_INDEX_FILE=./merge-index git read-tree -m BASE_TREE OUR_TREE THEIR_TREE
GIT_INDEX_FILE=./merge-index git ls-files --stageQuick check
In a three-tree `read-tree -m` merge, what does index stage 1 represent?
`-u` crosses into the working tree
Normally `git read-tree` changes only the index. With `-u`, a successful merge also updates working-tree files to match the resulting index. Because this can replace files, use it only when the tree transition and local-state checks are understood.
git read-tree -m -u OLD_TREE NEW_TREE
git status --short`--reset`, `--trivial`, and `--aggressive`
`--reset` is a merge mode that discards unmerged index entries instead of refusing because the index is already unmerged. `--trivial` restricts three-way merging to cases requiring no file-level merging, while `--aggressive` lets read-tree resolve a few additional add/remove cases itself. These are low-level merge controls, not substitutes for the policy decisions made by higher-level merge commands.
Sparse checkout is a boundary, not the main lesson
The current official manual documents `read-tree` interaction with sparse-checkout and `--no-sparse-checkout`. Foxipa teaches the user-facing `git sparse-checkout` workflow separately, so this lesson only explains the boundary: `read-tree` is one of the low-level commands that historically manipulates skip-worktree state. For normal sparse-checkout work, use the dedicated sparse-checkout command.
Do not confuse `read-tree` with nearby commands
`git ls-tree` inspects a tree object. `git mktree` constructs a tree object. `git read-tree` moves tree information into the index and can prepare low-level index merges. `git write-tree` moves the other direction, creating tree objects from the index. `git checkout-index` can then materialize index contents into the working tree. These layers are intentionally separated.
Quick check
Which command is the inverse-direction companion that creates a tree object from the current index?
Practice what you learned
Use the dedicated Git code-completion exercise for this lesson.
Thanks for your feedback.
Mark this learning resource complete to track your learning progress.