views:

1340

answers:

3

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:

  1. When checking out Super with all its dependencies, I'd end up with three copies of Core.
  2. 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)?

+4  A: 

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.

Igor Zevaka
Super is a project in itself. Don't assume it has no content just because I called it Super.
Mauricio Scheffer
But I want each project to be stand-alone. And I like that git submodules are fixed to a particular commit instead of following like svn externals, so that a change in Core wouldn't immediately break A, B and Super.
Mauricio Scheffer
Whether you track branches or commit SHAs is completely up to you. But the best answer for your problem is that it's not really possible to have both the stand-alone and the super-project option. In practice I found having a super-project for each sub-project is not that big of a deal.
Igor Zevaka
A: 

I would not try and map a dependency tree with sub-modules - for the reasons you have already discovered.

Sub-modules track a given revision of a given branch, so they are useful of giving a snapshot of a consistent set of modules.

So, if your project required a certain set of versions of different modules to be tracked as one unit, you can group them together as sub-modules. You can then tag different set of modules at different versions, to give a history of the project, where each tag shows what versions of what modules were compatible at a point in time.

 tags/
     release1/ 
           |-> [email protected]
           |-> [email protected]
           |-> [email protected]
     release2/
           |-> [email protected]
           |-> [email protected]
           |-> [email protected]

At least that how I understand them, although like most things with Git, there is probably a whole lot more to it than that. In terms of managing dependencies, all I can say is find another way, it is not what Git with or without sub-modules was designed for as I understand it.

megamic
Ok... but I think this solves a different problem... not the one I'm asking about.
Mauricio Scheffer
+4  A: 

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)

VonC