How to subtree split in Git
Git subtree split extracts a subdirectory into a new branch containing only the commits that touched that path.
As the creator of CoreUI with over 25 years of version control experience since 2000, I’ve used subtree split to extract reusable libraries from monorepos without losing history.
The standard approach runs git subtree split --prefix to create a new branch, then optionally pushes it to a separate repository.
This preserves the complete commit history of the extracted code.
Split a subdirectory into a new branch with its full history.
git subtree split --prefix=src/utils -b utils-library
The --prefix specifies which directory to extract. The -b creates a new branch containing only commits that modified files in that directory. The branch has a clean history as if the library always lived in its own repo.
Pushing Split Branch to New Repository
Publish the extracted code as a standalone repository.
# Create the split branch
git subtree split --prefix=src/utils -b utils-library
# Add remote for the new repository
git remote add utils-repo https://github.com/username/utils.git
# Push the split branch as main
git push utils-repo utils-library:main
The split branch maps onto the new repository’s main branch. All commits from the subdirectory appear in the new repo with their original messages and timestamps. Contributors keep their attribution.
Splitting with a Squash
Create a clean single commit instead of full history.
git subtree split --prefix=src/utils --squash -b utils-clean
git push utils-repo utils-clean:main
The --squash condenses all history into one commit. Use this when the full history is noisy or contains sensitive information. The new repository starts fresh from a single snapshot.
Verifying the Split
Check the extracted branch before pushing.
# Switch to the split branch
git checkout utils-library
# Verify only expected files are present
ls -la
# Check commit history
git log --oneline
# Count commits
git rev-list --count HEAD
# Switch back to main
git checkout main
Review the file structure and history before pushing. The directory should be the repository root. Only commits touching the original subdirectory should appear.
Automating Regular Splits
Keep a split repository synchronized.
# Initial split
git subtree split --prefix=src/utils -b utils-library
git push utils-repo utils-library:main
# After new commits to src/utils
git subtree split --prefix=src/utils -b utils-library
git push utils-repo utils-library:main
Running subtree split again on an existing branch is safe. Git detects which commits are new and appends only those. Push updates the external repository incrementally.
Best Practice Note
This is the same subtree split workflow we use when extracting shared utilities from CoreUI into standalone packages. Subtree split is the cleanest way to share code from a monorepo. The key advantage over copying files is the preserved history - git blame still works correctly. After splitting, decide whether to continue development in the monorepo and sync periodically, or move to the standalone repository permanently. For ongoing projects, add the split-and-push as a CI/CD step to keep external repositories up-to-date automatically.



