Search:

PmWiki

pmwiki.org

edit SideBar

Main / Gitsubmodules

Back to git

Intro

A submodule record points to a specific commit in another repo. Git submodules are distinct from subtrees in that they have their own .git folder and exist as a separate repo from the parent project.  Changes made to submodules are committed and pushed to the submodule repo and not the parent project repo.  Conceptually then, it should be considered that work done on a submodule is always done in common, i.e. shared with anyone using that submodule.

It's probably best to use repos as a submodule only after they are quite stable and not something being updated frequently, yet needing to be leveraged by multiple other projects.

Getting Started

To add another repo as a submodule to your current (parent) project, use
git submodule add <submoduleremote>
and this will clone the repo into a subdir with the same name as the repo.

A .gitmodules file will be created in the parent. Commit and push the changes:
git commit -m "Add submodule <name>"
git push origin master

Note that when you make a change to submodule code, you need to commit it to that repo obviously, but then you'll also want to do a commit at the parent level because it also records that there was a change to that submodule.

Cloning

When you want to clone this parent project and all submodules, use
git clone --recurse-submodules <remote>

Then combine the submodule init and update steps for the whole tree into one with
git submodule update --init --recursive

Using multiple submodules efficiently

The foreach specifier for submodule commands executes a git command on every submodule folder inside a parent project. For example:
git submodule foreach 'git status'
git submodule foreach 'git pull'

If you need to continue the process despite failures, make sure the command always returns success with:
git submodule foreach 'git checkout dev || :'

De-submodule-ize (integrate back into repo)

If you want to "de-submodule-ize" and make what was a submodule into a regular child directory of the repo, you can use the following steps.

Method 1: Throw away submodule history
If you are in a project fork or similar and don't care about keeping the separate repo history for your submodule, the process is pretty simple.  It's best to do this on the master branch so that you can switch branches without git complaining about files being overwritten.

  1. Ensure you are on the correct branch at top level and in each submodule
  2. Run git rm --cached <subm>
  3. Remove the .git file from the submodule directory, like rm <subm>/.git
  4. Remove the submodule's entry from the parent repo .gitmodules
  5. Remove the submodule's entry from the parent .git/config
  6. Add the changes you've made and commit git add . and git commit -m "De-sub the module" (if these are the only pending changes, otherwise be sure to add only the related files)
  7. Push and you are done.

Method 2: Keep submodule history TODO

Forking submodule repos

When you fork a project with submodules that now needs forked submodules that have moved to other repos, you have a few steps to take.

1. In the new project update the .gitmodules file which points to the new repo locations. 2. After doing a git clone --recurse-submodules then check out the desired branch for your top level project and run git submodule sync --recursive to update the submodule origin paths.


Page last modified on April 08, 2024, at 04:43 PM