How to split Git repositories into two
August 14, 2017
Ever wondered how to split your Git repo into two repos?
First you need to find out what files and directories you want to move to separate repos. In the above example we’re moving dir3, dir4 and dir7 to repo A, and dir1, dir2, dir5 and dir8 to repo B.
What you need to do is to go through each and every commit in git history for every branch and filter out commits that modify directories that you dont care about in your new repo. The only flaw of this method is that it will leave those empty, filtered out commits in the history.
Track all branches
First we need to start tracking all branches locally:
for i in $(git branch -r | grep -vE "HEAD|master" | sed 's/^[ ]\+//'); do git checkout --track $i done
Then copy your original repo to two separate dirs: repo_a and repo_b.
cp -a source_repo repo_a cp -a source_repo repo_b
Filter the history
Following command will delete all dirs that exclusively belong to repo B, thus we create repo A. Filtering is not limited to directories. You can provide relative paths to files, dirs etc.
cd repo_a git filter-branch --index-filter 'git rm --cached -r dir8, dir2 || true' -- --all cd repo_b git filter-branch --index-filter 'git rm --cached -r dir3, dir4, dir7 || true' -- --all
Note that the
|| true prevents git from failing to filter our dirs mentioned in the
rm clause in early stages of the git history where the dirs did not yet exist.
Look at the list of branches once again (in both repos):
git branch -l
Set new origins and push
In every repo, we need to remove the old origin and set up new origin. After it’s done, we’re ready to push.
Remove old origin:
git remote rm origin
Add new origin:
git remote add origin firstname.lastname@example.org:YourOrg/repo_a.git
Push all tracked branches:
git push origin --all