Git: Convert a folder to another repository (or a Git submodule)
It’s a common doubt in Git how to organize your repositories: should I have separated repositories for modules or related apps? Should I throw everything in a single repository?
If you have used a single repository for different (though related) things, you may want in the future separete some folders in multiple repositories, maybe in intent of using Git submodules (or not).
Fortunaly, doing so in Git is easy with the
filter-branch command. And it
will keep all the history related to the folder untouched in the new
Make a copy of the original repository
filter-branch command is destructive: you will lose all history not relate to that
folder! You are supposed to run it in a copy, not in the original repository.
cp -r my-repository my-repository-2 cd my-repository-2
Remove all the remotes
Just to prevent a big mess in case of an accidental force push:
git remote -v => origin http://github.com/yourusername/my-repository git remote remove origin
Filter the history based in a directory
Here the magic happens. Just run the command below. Don’t
forget ro replace
my-folder with the folder you want to filter.
git filter-branch --subdirectory-filter my-folder -- --all
git log and you will see that the history only contains commits
related to the specified folder. Also, the filtered folder was moved to the
Optionally remove the folder from the previous repository history
About the original repository, you have two options: just delete the folder, commit and keep the history, or rewrite the entire history to remove past references of the directory. If you choose the latter, keep in mind that other people that contribute to the code will have to clone the repository again. Also, I strongly recommend a backup of the repository.
Doing it is simple as running the following command. Change
my-directory to the name of the given directory:
cd .. cd my-repository # the original one git filter-branch --tag-name-filter cat --index-filter 'git rm -r --cached --ignore-unmatch my-directory' --prune-empty -f -- --all
Optionally use Git submodules
Git submodules is known to not be a good option if you don’t know what you are doing. Be sure to search if it is what you really want. If it is, do the following:
First, push the repository to its new home:
git remote add origin https://github.com/yourusername/my-repository-2.git git push origin master --tags
After, go to the original repository and add the submodule
cd .. cd my-repository git submodule add https://github.com/yourusername/my-repository-2.git