By admin , 29 April 2026

Synopsis

git subtree add --prefix=<path> <repo> <ref> [--squash]
git subtree pull --prefix=<path> <repo> <ref>
git subtree push --prefix=<path> <repo> <ref>
git subtree split --prefix=<path> -b <new-branch>

Description

The git subtree command is an alternative to submodules that merges another project's content directly into a subdirectory of your repo. Unlike submodules, subtree consumers don't need any special steps — the files are simply there. The cost is that the foreign history is incorporated into your own.

The two main operations are add (initial import, often with --squash to flatten history) and pull (bring in upstream changes). To send back changes, git subtree push filters out commits that touch the prefix and pushes them to the upstream repo.

In day-to-day use, git subtree integrates closely with shell aliases, editor plugins, and continuous integration. Power users often add aliases that combine flags they always pass, or wrap the command in scripts that enforce team conventions. Output formatting can be customized via Git config — pretty formats, color schemes, and pager behavior are all tunable. When something goes wrong, the first diagnostic step is usually to re-run the command with GIT_TRACE=1 in the environment, which reveals the underlying plumbing calls. For unusual situations, the --help output (git subtree --help) opens the full manual page with details on every option, including those rarely used in casual workflows but essential for debugging or scripting at scale.

Understanding how git subtree interacts with the rest of Git's data model — the object database, the index, refs, and the working tree — pays dividends. Each command operates on some subset of these pieces, and knowing which it touches helps predict outcomes and recover from mistakes. Reading the official Git documentation alongside hands-on practice in a throwaway repository is the fastest way to internalize the nuances. Most production issues with Git stem from one of three causes: surprising default behavior, partial network operations, or rewriting history that was already shared. A working mental model of git subtree's side effects helps avoid all three.

Common Options

SubcommandDescription
addImport an external repo into a subdirectory.
pullMerge upstream changes for that prefix.
pushPush prefix-only history back upstream.
mergeMerge an arbitrary tree into the prefix.
splitExtract a subdirectory's history as a standalone branch.
--squashFlatten foreign history into a single commit.
--prefix=<path>Subdirectory under which to place the subtree.

Examples

git subtree add --prefix=vendor/foo https://github.com/lib/foo.git main --squash
# Import foo into vendor/foo, squashing history

git subtree pull --prefix=vendor/foo https://github.com/lib/foo.git main --squash
# Pull updates

git subtree split --prefix=lib -b lib-only
# Extract lib/ as its own branch for sharing

git subtree push --prefix=vendor/foo upstream main
# Send prefix-scoped commits back to upstream

Common Mistakes

Mixing --squash on some operations and not others creates messy history. Pick one mode and stick with it. Subtree merges produce nontrivial commit graphs that confuse some tooling. git subtree split can be slow on large histories.

Related Commands

git submodule, git merge, git filter-repo