Sometimes you realize a part of your current project (like a library for example) should have it's own repository. Sure, you could simply copy and paste the files into a newly created repository, but you would lose all the previous commit network. Not loosing this network while isolating a part of your porject is the goal of this tutorial.
Let ~root/project
be the absolute path of your project and path/to/subproject
the path to your subproject directory (the directory you want to isolate) relatively to the project path, so that ~root/project/path/to/subproject
is the absolute path of the subproject.
Since we never modify to the actual project until the last step, it's all safe. However, always keep a copy of your project somewhere.
-
Isolate the submodule in its own directory.
~root/project$ git clone .git ../subprojectname ~root/project$ cd ../subprojectname ~root/subprojectname$ git remote rm origin ~root/subprojectname$ git filter-branch --subdirectory-filter 'path/to/subproject' --prune-empty -- --all
-
Add
~root/subprojectname
to your GitHub repositories. I prefer to do so through GitHub Desktop. Say you publishedgit@github.com:USERNAME/subprojectname.git
.Feel free to
rebase
the commit network of the submodule before you publish it.If you don't wish to publish it, you're done. Great job 👍
If you don't want or cannot modify the whole project, stop here as well. 🚧
-
Now, we want to replace the subproject directory within the project by a link to the newly created repository in order to support future versions. First, to delete the previous version, you have two options :
-
Delete manually the subproject directory. It will let a trace of the subproject in the project commit network.
-
Remove any trace of the subproject from the project commit network. Don't do this if a lot of, or even a few, people use the repository.
~root/subprojectname$ cd ../project ~root/project$ git clone .git ../copy ~root/project$ cd ../copy ~root/copy$ git remote rm origin ~root/copy$ git filter-branch -f --index-filter 'git rm -rf --cached --ignore-unmatch path/to/subproject' HEAD ~root/copy$ git filter-branch -f --commit-filter 'git_commit_non_empty_tree "$@"' HEAD
Feel free to clean up manually the commit network after this operation.
-
-
Add the subproject directory to the project as a submodule.
~root/copy$ cd path/to/ ~root/copy/path/to$ git submodule add git@github.com:USERNAME/subprojectname.git
-
There you go,
~root/copy
is the new version of your project. Nevertheless, you still need to push it to GitHub. Say your project repository isgit@github.com:USERNAME/project.git
.⚠️ If your are not satisfied with the result, or if anything went wrong during the process, don't push it. Try again or stop to the second step if so.~root/copy$ git push -f git@github.com:USERNAME/project.git
And you are done ! Congratulations 👏👏