Skip to content

Instantly share code, notes, and snippets.

@francois-rozet
Created January 6, 2019 01:40
Show Gist options
  • Save francois-rozet/24ecbb0d659ca7cdb47a112bdec484f8 to your computer and use it in GitHub Desktop.
Save francois-rozet/24ecbb0d659ca7cdb47a112bdec484f8 to your computer and use it in GitHub Desktop.
Tutorial on how to transform a repository directory into a submodule

Directory to submodule

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.

  1. 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
  2. Add ~root/subprojectname to your GitHub repositories. I prefer to do so through GitHub Desktop. Say you published git@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. 🚧

  3. 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 :

    1. Delete manually the subproject directory. It will let a trace of the subproject in the project commit network.

    2. 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.

  4. 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
  5. 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 git@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 👏👏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment