Next.js starter your AI actually understands. Ship internal tools in days not weeks. Pre-order $199 $499 → [Get it now]

How to subtree merge in Git

Git subtree allows incorporating external repositories into your project as subdirectories without the complexity of submodules. As the creator of CoreUI with over 25 years of version control experience since 2000, I’ve used subtree merging to integrate third-party libraries while maintaining full control over the code. The standard approach adds a remote for the external repository, then uses git subtree to merge it into a specific directory. This provides cleaner workflows than submodules for vendoring dependencies.

Add an external repository to a subdirectory using subtree.

git remote add library https://github.com/username/library.git
git subtree add --prefix=vendor/library library main --squash

The remote add creates a reference to the external repository. The subtree add merges it into the vendor/library directory. The --squash combines all commits into one. The library code becomes part of your repository history.

Pulling Updates from Upstream

Update the subtree with latest changes from the external repository.

git fetch library
git subtree pull --prefix=vendor/library library main --squash

The fetch downloads new commits from the remote. The subtree pull merges updates into the subdirectory. The --squash keeps a clean history. Your repository stays synchronized with upstream.

Pushing Changes Back to Upstream

Contribute modifications back to the original repository.

git subtree push --prefix=vendor/library library feature-branch

The subtree push extracts commits affecting the subdirectory. Only changes in vendor/library are pushed. The upstream repository receives a clean pull request. This enables bidirectional collaboration.

Splitting a Subdirectory into Separate Repository

Extract a subdirectory into its own repository.

git subtree split --prefix=vendor/library -b library-split
git push library library-split:main

The subtree split creates a branch with only commits affecting the directory. The push uploads it to a remote repository. This is useful for extracting shared code into a library.

Managing Multiple Subtrees

Organize several external dependencies as subtrees.

git remote add ui-lib https://github.com/username/ui-lib.git
git subtree add --prefix=vendor/ui-lib ui-lib main --squash

git remote add utils https://github.com/username/utils.git
git subtree add --prefix=vendor/utils utils main --squash

git fetch --all
git subtree pull --prefix=vendor/ui-lib ui-lib main --squash
git subtree pull --prefix=vendor/utils utils main --squash

Each subtree operates independently. The fetch --all updates all remotes. Individual pulls update each subdirectory. This approach works well for vendoring multiple libraries.

Best Practice Note

This is the same subtree workflow we use when vendoring dependencies in CoreUI projects that require full control over third-party code. Subtrees are simpler than submodules - they’re just regular commits, no special clone procedures needed. Use --squash to avoid polluting your history with hundreds of upstream commits. For read-only dependencies, subtree works great. For bidirectional workflows, ensure clear conventions about where changes originate. Document your subtree remotes and prefixes in the README. For modern projects, consider npm packages or Git submodules - subtrees are best when you need the dependency code fully integrated into your repository.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author