Skip to content

Git Subtree: Split, Merge, and Manage Subrepos

When a DevOps team outgrows a single repository — a shared library that needs its own release cycle, a service that must be deployed independently — git subtree provides a surgical split. Unlike submodules (which point to external repos), subtree embeds the subrepo's history inside your repo and lets you split back to a standalone repository when needed.

Why a DevOps Engineer Uses Subtree

  • Split a large monorepo service out to its own repo without losing the full git history.
  • Merge an external library into a subpath while tracking upstream releases cleanly.
  • Publish a subfolder as a standalone package (e.g. lib/ becomes npm install lib/ from a dedicated repo).
  • Maintain a vendor directory that receives upstream patches but still gets its own CI pipeline.

Split Pattern (Monorepo → Independent)

# 1. Extract history of a subfolder into a new branch
git subtree split --prefix=services/auth --branch=auth-split

# 2. Create / push the new standalone repo
git init ../auth-service
git push ../auth-service auth-split:main --force

# 3. The original repo keeps full commit history for that subfolder.

Pull / Push Subrepo Updates

# Pull upstream updates into subfolder
git subtree pull --prefix=vendor/lib --squash https://github.com/vendor/lib main --message="Merge upstream lib v2.1"

# Push your changes back upstream
git subtree push --prefix=vendor/lib https://github.com/vendor/lib main

Pitfalls

  • --squash loses granular upstream history; omit it only if you need full commit replay.
  • Large subrepos produce big split branches; use git subtree split sparingly on CI servers to avoid timeouts.
  • Always specify --prefix explicitly; missing it writes to root.