3

I've been looking into Git submodules to make a "Git project inside a Git project", but I've run into an issue that tells me submodules might not be the right solution.

Let me explain what I am looking to do:

Currently I have a single project with multiple branches (master and development) and a library that I would like to separate into it's own Git project (so it can be developed independently and with it's own commit history). Specifically I also want to be able to:

  1. Commit and push changes in a separate clone of the library project which are not updated in the superproject until explicitly asked for.
  2. Use library master branch when on superproject master branch.
  3. Use library development branch when on superproject development branch.

It would also be nice (but not required) to be able to:

  1. Commit and push changes to the library project from within the superproject.

As far as I'm aware #1 and #4 are supported by Git submodules (even though #4 requires a few extra checks to make sure you're on the right branch). #2 and #3 not so much.

I've looked at Differences between git submodule and subtree and Vendor Branches in Git, but neither seem to offer exactly the functionality I'm asking for - is it possible to implement with Git? Is it possible without a lot of extra moving/renaming/checking out directories?

Community
  • 1
  • 1
Woodgnome
  • 2,281
  • 5
  • 28
  • 52
  • What are the issues you ran into? – Martin Nyolt Aug 19 '16 at 14:48
  • This suggestion may not apply to your case, but in general if a module needed to be on the development branch when a dependent module was also on the development branch, I would often choose to put both modules in the same repository. – Dietrich Epp Aug 19 '16 at 16:25
  • What if the module is a client library to an external service and you're preparing the development branch to use a newer version? I'd wager that's a quite common use case. – Woodgnome Aug 30 '16 at 15:04

1 Answers1

0

Your requirements 1-3 can be achieved by submodules. Requirement 4 can be achieved by subtrees, but only in a limited fashion by submodules.

First, please note that having many interactions between different projects/repos necessarily requires many interventions to keep the projects in sync. (By interaction, I mean that small changes to the submodule require changes to the subproject.)

There are two things to be aware of:

  • The current commit of the submodule is stored in every commit of the superproject.
  • The submodule stores only the commit id, but never a specific branch.

Specifically, every time you want to update your submodule, you have to

  1. manually check out the latest version within the submodule
  2. commit the new submodules HEAD in the superproject.

Submodules make mostly sense if you only rarely update the submodule (not sure about subtrees, though). At least, that's my impression. I use submodules often as some kind to ensure that code is reproducible (actually, that's what version control is for, after all). I.e., to encode information like "for commit X, we need commit Y of submodule A".

Having a stable interface between two projects is a key in limiting the interactions.

When you switch branches in your super project, then the git submodule will know that it has to be in the specific submodule's commit of that branch. However

  1. git will neither automatically check that commit out - you have to run git submodule update manually,
  2. not will git automatically pull the changes of the submodule's origin.

So, yes, submodules offer requirements 1-3, although with some manual work.

  1. The submodule is just a clone. Thus, you can independently work on the submodules's origin without pulling in changes.
  2. The submodule's commit is saved separately for each super projects commit. Thus, you have different submodule commits for different branches. ut remember to run git submodule update.
  3. See 2.
  4. Can be done only within the submodules directory. Thus cd submodule; git commit; git push works.
Martin Nyolt
  • 4,463
  • 3
  • 28
  • 36
  • I'm not sure this adresses the problem where: 1. Submodule is in development branch. 2. Superproject development branch is now merged into master branch. 3. git submodule update is run in superproject. 4. Superproject now has the development branch of submodule (I want it to be master branch still). Or did I misunderstand your explanation? – Woodgnome Aug 19 '16 at 14:50
  • "every time you want to update your submodule, you have to 1. manually check out the latest version within the submodule". I also added an explanation that the submodule's commit is stored *per superproject commit*. Thus, after (or during) your merge, you have to manually check out the master branch of the submodule. – Martin Nyolt Aug 19 '16 at 14:56