Split your monorepo into two clean Git repositories — interactively, safely, and with history rewritten to match your file layout.
• One command to launch. • Arrow keys + Space to move. • Shift+Enter to apply.
- Python 3.8+
- Git (CLI)
- git-filter-repo (mandatory)
- macOS:
brew install git-filter-repo - Any OS:
pipx install git-filter-repo
- macOS:
The CLI refuses to run if git-filter-repo is not available.
From the repository you want to split, run:
bin/git-splitrepo <repo1_dir> <repo2_dir>
Both <repo1_dir> and <repo2_dir> must be outside the source repository directory.
- Tab — switch panel
- Space — move selected file/folder to the other repo
- b — keep selected file/folder in both repos
- Shift+Enter (or F5) — apply the plan and rewrite history
- q — quit
- Clean outputs: copies your repo, removes symlinks/empty dirs, drops
originremotes. - Precise history: uses
git-filter-repoto keep only commits relevant to kept paths. - Safe by default: only connected local branches are rewritten; orphan branches are left untouched.
- “Keep in both”: any path you mark with
bappears in both outputs (files and history).
bin/git-splitrepo ../out-repo-1 ../out-repo-2
Then:
- Space on a folder to move it
- b on a shared folder to keep it in both
- Shift+Enter to apply
Drive the split from a YAML file instead of the UI.
Use the CLI flag (the current working repository is the input; folders.* define the output repositories and must contain only keys main and secondary; alias secondry is accepted for secondary):
bin/git-splitrepo --spec /absolute/path/to/split.yml
Two-output mode (JSON): produces two destination repositories
folders:
main: /abs/out-repo-1
secondary: /abs/out-repo-2
includes:
- repo2
excludes:
- drop
both:
- shared
bothExcludes:
- shared/tmp
Single-output mode (JSON): produces one destination repository
folders:
main: /abs/out-repo
includes:
- keep2
excludes:
- drop
- shared/tmp
TOML examples (Python 3.11+ via tomllib, or with tomli installed). Input is the current working repo; folders.* define outputs (keys: main, secondary; alias secondry is accepted).
Two-output mode (split.toml): produces two destination repositories
[folders]
main = "/abs/out-repo-1"
secondary = "/abs/out-repo-2"
includes = ["repo2"]
excludes = ["drop"]
both = ["shared"]
bothExcludes = ["shared/tmp"]
Single-output mode (single.toml): produces one destination repository
[folders]
main = "/abs/out-repo"
includes = ["keep2"]
excludes = ["drop", "shared/tmp"]
Notes for spec mode:
- When
folders.secondaryis omitted, the split produces a single output infolders.main. - In single‑output mode,
bothandbothExcludesare not allowed (useincludes/excludesinstead). - You can still use the older env var path (SPLITREPO_SPEC), but the CLI flag is preferred.
-
Behavior
- Copies the source repo to both outputs
- Removes
originremotes (best‑effort) - Removes symlinks and prunes empty directories in outputs
- Rewrites history with
git-filter-reposo each output keeps only commits relevant to kept paths - “Keep in both” (
b) makes selected paths exist in both outputs (files and history) - Reassignment precedence: child paths override parent decisions
-
Branch rewrite scope (important)
- Only connected local branches under
refs/headsare rewritten (share a merge‑base with the current branch) - Orphan branches remain untouched by design
- Remote branches, tags, notes, reflogs are not rewritten
- Only connected local branches under
-
Notes & limitations
- Requires
git-filter-repo(mandatory) - Run from the Git repo root; outputs must be outside the source directory
- Submodules/LFS are not handled specially
- Requires
- Scripts:
scripts/setup,scripts/test,scripts/coverage,scripts/lint,scripts/format - Tests:
pytest -q(orscripts/test)
- “git-filter-repo is required” → install via
pipx install git-filter-repoorbrew install git-filter-repo, then verify withgit filter-repo --help. - “Permission denied” →
chmod +x scripts/* bin/git-splitrepo. - Must run from repo root; outputs must live outside the source directory.
- “Keep in both” is a one-way mark; to revert, reassign the item with Space to a single side.
- Child reassignment overrides parent decisions (e.g., mark
shared/in both, but moveshared/tmp/to repo 2 only). - Outputs are normal Git repos — you can inspect with
git log -- <path>to validate history.
This repository may include additional licensing terms in project files.
git split, split repo, monorepo split, repository splitter, git-filter-repo, history rewrite, subtree split alternative, interactive TUI, non-interactive spec, JSON spec, TOML spec, Python CLI, git tools, refactor monorepo, extract package, split by paths, keep in both, exclude paths