Search code examples
gitgit-submodules

Git: Possible to use same submodule working copy by multiple projects?


I'm new to Git. Lets say, I have two git repositories that have the same library added as submodule:

/home/projects/project1/library_XYZ
/home/projects/project2/library_XYZ

Also lets say, I'm working on the projects and the library simultaneously. When I did changes to the library, lets say in /home/projects/project1/library_XYZ, I would have to push these changes and then pull them in /home/projects/project2/library_XYZ to make them available for project2, right? I think this is unhandy for two reasons:

  • I will have to build library_XYZ two times.
  • I have an unwanted redundancy that contradicts the actual project organization.

Is there any way to make Git clone the submodule library_XYZ to the same local directory, i.e. making the files being organized like this

/home/projects/project1
/home/projects/project2
/home/projects/library_XYZ

while library_XYZ still being a submodule of both projects?

I think this might be related to this, which is unanswered, although my setup is somewhat different.


Solution

  • Setting up shared dependencies as submodules is easy. The git submodule command doesn't do it automatically, but a submodule is nothing more than a nested repository -- and git doesn't require any actual repository or its worktree to be in any particular place.

    Set up a libraryXYZ repo for use as a shared submodule

    # a submodule is just a repository. We're going to share this one.
    git clone u://r/libraryXYZ 
    
    # and keep its worktree right here:
    ( cd libraryXYZ; git config core.worktree .. )
    

    Then, from anywhere, clone the project using the submodule and set it up to use the shared one:

    git clone u://r/project1
    cd project1
    git submodule init
    echo gitdir: path/to/shared/libraryXYZ/.git > libraryXYZ/.git
    

    Now project1's libraryXYZ submodule will use the shared libraryXYZ repo and worktree.

    Set up your build system to use that same worktree and you're done. You can of course get git to tell you where those are in any given repo:

    # for example to see where all a project's submodules' parts are kept
    git submodule foreach git rev-parse --git-dir --show-toplevel
    
    # or for just one:
    git --git-dir=$project1/libraryXYZ/.git rev-parse --git-dir --show-toplevel
    

    (late edit: @twalberg's remark is worth keeping in mind, this might make it a bit too easy to do a git submodule update from one project without realizing you've also altered the build environment for every other project that shares dependencies.)