Split a subdirectory into a separate Git repository

Extract a directory and its relevant history with git-filter-repo or subtree split, then publish the new repository and update its dependencies.

Best practices
Illustration of Git branches and version history

Use git filter-repo --subdirectory-filter path/to/subdir in a fresh clone to move a subdirectory to the repository root and keep its relevant history. git subtree split is another option when available in your Git installation. Both create rewritten history, so commit IDs can change.

Extract with git-filter-repo

Install git-filter-repo using a method supported by your environment, such as pipx install git-filter-repo. Work in a fresh disposable clone, keeping the original repository intact:

git clone https://example.com/team/original.git new-repo
cd new-repo
git filter-repo --subdirectory-filter path/to/subdir

For a local source path, use git clone --no-local /path/to/original new-repo to avoid local-clone optimizations when preparing a fresh clone for filtering.

The chosen directory becomes the root. Commits that become empty may be pruned, and historical renames are not followed automatically. If the directory previously lived elsewhere, include and map those older paths deliberately. This preserves relevant history under the selected rules, not every original commit unchanged.

git-filter-repo normally removes origin during a full rewrite to reduce the chance of mixing old and rewritten history. Review the result before adding the new destination.

Extract with subtree split

From the original repository:

git subtree split --prefix=path/to/subdir -b subdir-history

Then create an independent repository from the extracted branch:

mkdir ../new-repo
cd ../new-repo
git init -b main
git pull /absolute/path/to/original subdir-history

This starts an empty repository on an explicitly named main branch. git subtree is bundled by many Git distributions but may be packaged separately; check its availability first.

Publish and finish the migration

After inspecting the extracted history and running the project's checks:

git branch -M main
git remote add origin https://example.com/team/new-repo.git
git push -u origin main

Use a new empty destination and confirm origin is absent before adding it. Remove the old directory from the original repository only after consumers and builds have migrated. For a transition period, subtree synchronization or a submodule can keep a source-level relationship, but choose an ownership model to avoid conflicting edits in both locations.

FAQ

Does filtering rewrite paths mentioned in commit messages?

It can update references to rewritten commit hashes. It does not automatically correct arbitrary directory names in prose; that needs an explicit message transformation if required.

Can I also remove large historical files?

git-filter-repo supports options such as --strip-blobs-bigger-than 10M. That deletes matching historical contents, so review the consequences separately from the directory split.

How should a monorepo consume the extracted library?

Publish versioned packages through your npm, Python, or Maven registry when practical. Use submodules or subtree integration when consumers need a source checkout instead, and update build paths and release automation accordingly.

See the git-filter-repo manual and git-subtree documentation.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting