1

I'm needing to use the git submodules so that my parent repository can track changes that occur in specific branches. I have a project with testing, beta and production branches. Both my parent and child repositories will need to have testing, beta, and production (main) branches.

Thanks if anyone can suggest me a solution to this.

4
  • 1
    Your repositories can already have all these branches. What was the problem? Commented Jan 21, 2022 at 18:33
  • 1
    Are you asking if you can use different branches of the submodule with different branches of the parent repo? If so, then the answer is yes. Just go into the submodule directory and checkout the branch you want (testing, beta, and production) then commit the submodule version to the parent repo. Commented Jan 21, 2022 at 18:37
  • It's a little confusing to understand at first. So if a file is modified on the testing branch in the child repository, won't that change automatically reflect on the submodule's testing branch? Commented Jan 21, 2022 at 19:03
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. Commented Jan 31, 2022 at 20:37

1 Answer 1

3

At a low level, Git fundamentally works by hash IDs, not by branch names. Hash IDs are large, ugly, random-looking, and impossible for humans to remember. But they're easy and convenient for Git, a computer program, to remember and work with, and so that's what it does.

When we (humans) use Git, we tend to like to use branch names to hide the fact that Git is really using hash IDs. The submodule support in Git, however, mostly refuses to go along with this. (I'll come back to the word mostly in a moment.) Each submodule is being controlled by computer-program, so there's no need for branch names here, and Git simply doesn't bother.

Note that a submodule is really just another Git repository. The only thing that makes it special—that makes it a submodule in the first place—is that some Git software keeps coming over to the submodule Git repository and running:

git switch --detach <hash>

(or the equivalent with git checkout), putting the submodule into detached HEAD mode at a specified commit hash ID. The "controlling Git", which we call the superproject, reads these hash IDs out of data stored inside commits you make (on branches, if you work in the usual way) in the superproject. You don't have to view these hash IDs, just as you don't have to view the hash IDs of each of your commits in the superproject.

So: it is the superproject Git (the commands you run in the superproject repository) that is doing the detached-head thing in the submodule. You run git switch in the superproject, then you run git submodule update in the superproject—or you set "recursive" mode on and just run git switch in the superproject and it does the git submodule update for you—and the superproject forces the submodule into detached-HEAD mode. The submodule therefore never sees or bothers with any branch names at all. The hash ID that the superproject Git uses here comes from an entity that Git calls a gitlink.

The model you should have in mind is that any commits you want in the submodule simply appear, magically, maybe out of nowhere. For instance, perhaps you're using Fred's Library of Wonderful Wonders as a submodule. Fred makes a new release and you'd like to pick it up, so you:

  1. cd library/fred to enter the submodule;
  2. git fetch origin to call up Fred's repository and get version 2.0;
  3. git switch --detach v2.0 to get Fred's version-2.0;
  4. cd ../.. back to your own project;
  5. edit your project if/as needed to make use of the new whizzy features;
  6. run git add library/fred to update the gitlink for the next commit;
  7. run git add as needed on your own files (you can do this before, during, or after step 6); and
  8. run git commit to make a new commit in your superproject.

The new commit has a new gitlink, which records the new (correct) hash ID for Version 2.0 in library/fred. Note how no branch names have been used anywhere in this process.

Sometimes, of course, you would like to use a branch name: instead of tag v2.0, you want to pick up Fred's latest commit on his main. To do that, you change step 3 to read:

git switch --detach origin/main

Again, no branch names on your end are being used, but this time you did use origin/main: your remote-tracking name for Fred's main.

This is the one place that branch name support exists in submodules

In the above, you had to run:

(cd library/fred && git fetch origin && git switch --detach origin/main)

or whatever branch name you wanted. By setting a branch for a submodule, you can make:

git submodule update --remote

do the above sequence of commands for you. That's all it does. There is no magic here. Given how little actual value this adds, I personally recommend that you just use your own literal parenthesized sub-command here, if only to remind yourself of how poor the submodule support is in Git.

If your goal is to do your own work in submodules ...

If you intend to do your own commits in a submodule, the way Git's submodules work becomes more painful. What you end up doing is replacing the eight-step sequence above with:

cd library/mine
git checkout develop
... do development work ...
... test, etc., as needed ...
git commit
git push <options>
cd ../..
git add library/mine
git commit             # make new gitlink
git push <options>

But this assumes that everything always works the first time, which is rarely true in the real world. You end up having to go back and forth between submodule and superproject, and every once in a while you discover that the superproject Git has re-detached your submodule's HEAD. It's always predictable when this will happen, and afterwards you go oh right and fix it, but in practice it's painful and leads to the nickname of sob-modules.

Submodules do work. Just know what kind of experience you're setting yourself up for.

Sign up to request clarification or add additional context in comments.

2 Comments

My sincere thanks. I understand exactly how it works and what I need to do for my use case.
What a write-up. Pure poetry. Thanks for sharing!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.