Opinions on using Git Submodules for package management?

What are your Opinions on using Git Submodules for package management? (Git Submodules)

Git submodules allows you to embed another Git repository as a subdirectory.

You can add a submodule by running git submodule add.
For example:

git submodule add 'https://github.com/laytan/back.git' 'deps/back'

This clones the repo to the directory deps/back. This is similar to adding packages using a package manager like NodeJS NPM or Rust Cargo:

npm install package_name
cargo add package_name

After adding a submodule, you can go to the submodule directory deps/back and then switch to a specific commit or tag. Then, go back to the parent project directory and save the commit, which also includes changes to the submodule.

Whenever you want to update the submodule to a new version, repeat the above steps. This is similar to updating packages using NPM and committing the package-lock.json file.

Disadvantages of Submodules

There are several disadvantages to submodules, but the main one is that if you switch to a new commit in the parent repo, Git will not automatically update the submodules to the correct commit. You have to manually run the following command every time you switch to a new branch or commit:

git submodule update --init --recursive

The above command also needs to be run when the parent project repo is cloned.

You can also set the following config in local repo to automate syncing the Git Submodules when switching commits. But it has some problems. (What are the drawbacks to setting git’s submodule.recurse config option to true?)

git config submodule.recurse true

But package managers also need to sync package versions after switching commits. After switching to a new commit, you need to run npm ci to download the correct versions of NPM packages defined in package-lock.json file. Otherwise, packages in node_modules directory will be out of sync.

Advantage of Git Submodules

There is an advantage to Git Submodules. Since Git Submodules are just Git repositories, syncing the submodule package versions do not require Internet connection if the commits are already pulled from the remote repository.

For example, if you switch to an OLDER commit in parent repo that requires OLDER versions of the submodule packages, you just need to switch to an OLDER submodule commit, which probably is already pulled into the local Git repo from the remote repo. Just run the same command we used earlier to sync Git Submodule versions:

git submodule update --init --recursive

How I use this

I have a deps directory that contains other Odin dependency packages as submodules.

Alternatives

Git Subtree is an alternative to Git Submodules.

2 Likes

In my opinion, the main disadvantage is that submodules are not part of your repo. When the commit that you’re referencing is gone and you don’t have a local copy, it’s gone. Subtree does not have this problem because subtree is just a pretty word for copy paste. Submodule can avoid this disadvatage by forking, of course.

1 Like

I actually forked the above laytan/back repo before adding it as a submodule in my project. I just used the original repo URL in the example.

2 Likes

I usually recommend git subtree always because git submodule is too restrictive for what most people want.

2 Likes