Aug 13, 2014

[git] How to split repository by sub directories and retain all branches and tags

Because of Legacy and Enterprise code, I have a very big git repository moved from svn. If I build and deploy a external API's client, other clients are also updated and I should spent time to find why my war file has so many differences between current and new. If I fixed parent pom.xml, I could solve this problem. But I decided to split a big repository into 20 small repositories.

As usual, I Googled I found how to use git subtree to divide a sub directory to new git repository. It is very simple way!
Detach subdirectory into separate Git repository
 But it looses our commit logs and branches.

I asked Google again and found what I want.
git splitting repository by subfolder and retain all old branches
But I missed tags with this answer. Yes I know I should study myself. So I just added one more process to above.

Here is an example with github.

Make new repository on you github.
You can see how to push your project to new repository.

git clone voldemort
cd voldemort
git checkout --detach 
# delete all branches
git branch | grep --invert-match "*" | xargs git branch -D 
# get all branches
for remote in `git branch --remotes | grep --invert-match "\->"`; do
    git checkout --track $remote
# confirm you have all branches and tags
git branch
git tag

# make another local repository
git clone voldemort voldemort2
cd voldemort2
git checkout --detach
git branch | grep --invert-match "*" | xargs git branch -D
for remote in `git branch --remotes | grep --invert-match "\->"`; do
    git checkout --track $remote
git branch
git tag 
# Isolate docs and recreate branches
# --prune-empty removes all commits that do not modify docs
# -- --all updates all existing references, which is all existing branches
git filter-branch --prune-empty --subdirectory-filter docs -- --all

# clean up git log
rm -rf .git/refs/original/*
git reflog expire --all --expire-unreachable=0
git repack -A -d
git prune

# push all branches and tags to new repository
git remote set-url origin
git push --all
git push --tags

I made separated repository shell script. I hope it helps you.