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 published[email protected]: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 [email protected]: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 is[email protected]: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 [email protected]:USERNAME/project.git
And you are done ! Congratulations ππ