Say your git repo consists of a subdirectory “app” and a subdirectory “database” (or “frontend” and “backend” or “team-a” and “team-b”) and you realize each directories content should be in its own repository. Here is how to split the repo.
To create a repo that consists of the content of the “database” dir and its history, execute
git filter-branch --prune-empty --tag-name-filter cat --subdirectory-filter database -- --all
and then push it to a new remote:
git remote rename origin old-origin
git remote add origin <new-remote>
git push -u origin --all
git push -u origin --tags
This is what Gitlab states on a newly created project page. However in
git push -u origin --all
“-all” should be replaced with “–mirror” because “-all” pushes all local branches only so you would need to checkout all branches you want to keep. “–mirror” pushes remote branches, too.
In the same fashion apply “filter-branches” to the “app” directory.
How does it work? "git filter-branches" rewrites git revision history of the mentioned branches by applying filters:
- The mentioned branches states "--all" so filters are applied to all branches of the repo (you need "--" before "--all" because otherwise "--all" would get interpreted as a revision)
- "--subdirectory-filter" means "only look at the history which touches this directory" and also make that directory the root of the repo.
- "--prune-empty" removes any empty commits that may get created
- Git itself recommends using "--tag-name-filter cat" when not stated, it simply updates tags (apparently "--all" does not include tags).
I like the general idea that you've got here, but I'd like to see you (or someone) break down that long command to help people understand what's actually going on.