Git nested submodules and dependencies
Let's say I have four projects named Core, A, B, Super. The dependency tree is like this:
Super ---> Core
|-> A -> Core
|-> B -> Core
I want each project to be stand-alone, that is, I want to be able to check-out and compile each project on its own (each with its dependencies of course).
I thought about mapping each project to a repository and then referring dependencies with submodules, but I see the following issues with that approach:
- When checking out Super with all its dependencies, I'd end up with three copies of Core.
- Since submodules are fully independent, each of these three copies could be pointing to different revisions of Core and that would be a mess.
So... Am I missing something? Did I misunderstand git submodules or misusing them? Is there any other solution to this problem (other than resorting to binary dependencies)?
Solution 1:
You just discovered the lack of overridden dependencies with Git submodules:
If Super depends on Core, its dependency of Core should "override" the ones A and B have with Core.
The only way to emulate that would be to create your Super project the way you did,
and to remove the sub-module Core of A and B.
(meaning Super depends now on A' and B', A' being A without Core, B' being B without Core)
Solution 2:
git repositories should be fairly atomic in the way that each repository is a stand-alone entity for a specific purpose. What is the purpose of the super project other than combining projects A and B? If there isn't anything unique (i.e. files that are not in either A, B or Core) then it's fairly redundant.
EDIT: Because git submodules are especially painful at one place that I worked at we set up our own dependency system that tracks dependent repos via text files. We set it up so it always tracks the head of a branch, not a particular commit.
We were able to set up all our projects as though they are a part of the Super project like this:
Super
|-A
|-B
|-Core
The projects will reference each other using relative paths e.g. ../A/include.h
. Checking out repo A will not work, you would have to create another "super" repo for working just on A:
AWorking
|-A
|-Core
EDIT Another reason for this behaviour in git is that it can't track things that are above the root repo directory(i.e. above the folder containing .git folder), which would definitely be required if you want your super-projects and sub-projects refer to the same repositories.