Skip to content
Foxipa

Suggest an edit

Tell us what should be corrected, clarified, or improved. Submission will be connected to Foxipa’s contribution service later.

No information is sent anywhere yet. Your suggestion is only prepared in your browser.

Learning

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.

Levels: Advanced ~35 min read

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.

bash
TREE=$(git rev-parse HEAD^{tree})
GIT_INDEX_FILE=./lab-index git read-tree "$TREE"
GIT_INDEX_FILE=./lab-index git ls-files --stage

Quick 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.

bash
GIT_INDEX_FILE=./lab-index git read-tree --empty
GIT_INDEX_FILE=./lab-index git ls-files

Quick 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.

bash
GIT_INDEX_FILE=./lab-index git read-tree --prefix=imported/ HEAD^{tree}
GIT_INDEX_FILE=./lab-index git ls-files

Quick 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.

bash
GIT_INDEX_FILE=./lab-index git read-tree --index-output=./result-index HEAD^{tree}
GIT_INDEX_FILE=./result-index git ls-files

Dry-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.

bash
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.

bash
GIT_INDEX_FILE=./lab-index git read-tree -m OLD_TREE NEW_TREE
GIT_INDEX_FILE=./lab-index git ls-files --stage

Three-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.

bash
GIT_INDEX_FILE=./merge-index git read-tree -m BASE_TREE OUR_TREE THEIR_TREE
GIT_INDEX_FILE=./merge-index git ls-files --stage

Quick 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.

bash
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.

Was this page helpful?

Mark this learning resource complete to track your learning progress.