-1

I've removed and re-added the submodule over and over and over, but everytime we clone the parent repository, the submodule is at "(no branch)" Can someone provide the steps to get a submodule and properly, definitively, without any doubt, lock it on a commit?

Steps I took:

  • git submodule add https://bitbucket.org/bla/bla.git my/submodule/path
  • Update the submodule to point to a latest commit in a branch. Commit message says From <hash> X months ago Initial commit To: <hash> 1 day ago <somemessage>
  • Pushed the changes
  • git clone on a colleague's computer git clone https://bitbucket.org/bla/bla.git

The submodule is on (no branch) on my colleague's computer. It should not be. It should be at the commit I put it at. What have I missed?

Edit So maybe "(no branch)" is just misleading. On my colleague's machine, it checks out at Initial commit. That's the core problem.

phd
  • 82,685
  • 13
  • 120
  • 165
Diana
  • 789
  • 8
  • 34
  • 3
    Submodules are on no branch by design. As you say, they are locked in on a commit, not on a branch. – mkrieger1 Apr 15 '22 at 10:43
  • That's not my question. I definitively locked the submodule to a commit. I have the commit here, in front of me to prove that I changed the submodule to a specific commit. But when I clone the repository fresh, the ***-ing submodule does not check out at the commit I told it to – Diana Apr 15 '22 at 10:55
  • And `git submodule update --recursive` does not work either. The submodule is at the very first "initial commit" no matter what I do – Diana Apr 15 '22 at 10:56
  • I updated the question with the steps I did to add a submodule and put it at the exact commit – Diana Apr 15 '22 at 10:59
  • What steps exactly hide behind "Pushed the changes"? – mkrieger1 Apr 15 '22 at 11:00
  • Why do you conclude that "on (no branch)" means that it is not at a particular commit? It can very well be at a commit but not on a branch. – mkrieger1 Apr 15 '22 at 11:02
  • The usual `git push` or `git push -f` to push the commit that changed the commit I put the submodule on. I didn't expect that I have to add a parameter for that? Yeah, perhaps I'm focusing on (no branch) and that isn't the point. On my colleague's machine the /my/submodule/path is empty... – Diana Apr 15 '22 at 11:03
  • 3
    After updating the submodule you need to return to the superproject, add the change in the submodule, commit and push the superproject. Like in https://stackoverflow.com/a/5828561/7976758 – phd Apr 15 '22 at 14:03
  • so why can you specify a branch in .gitmodules? @mkrieger1 – mohas Jul 25 '22 at 10:25
  • 1
    @mohas For the `git submodule update --remote` command. See https://git-scm.com/docs/git-submodule#Documentation/git-submodule.txt---remote – mkrieger1 Jul 25 '22 at 11:49

2 Answers2

3

You'll need to make a new commit in the superproject, after you make a new commit in the submodule.

As multiple comments say, this is how submodules are supposed to work (though people find it quite frustrating). It may help to understand why they work this way, though.

Remember that a submodule is a (separate) Git repository. That is, if you have repository X as a superproject with submodule Y as a submodule, you have two repositories, X and Y. A Git repository is, at its, heart, a database of commits. To make the database of commits more usable, the repository also includes a database of names that map to hash IDs. However, for submodule purposes, the names database in Y becomes irrelevant! So we'll pretend it doesn't exist.

To use this thing, you (or someone else) will clone repository X to a copy X2 and then select some commit within X2 to check out. You'll use the new names database in X2 (which is independent of the names database in X—your branch names aren't their branch names—but is at least primed from that one) to pick the commit hash ID. Then you'll run git submodule update --init within the X2 clone, which will read the .gitmodules file extracted by the checkout so that it knows where to go to clone Y to make Y2 within X2.

Having cloned Y into Y2, the Git operating in X2 needs to know which commit within Y2 to check out. This is where the Y2 names database becomes irrelevant. Your Git software, operating in your X2, gets the hash ID to use in Y2 from a commit in X2. Which commit? Why, the current commit, the one that supplied the .gitmodules file and the fact that there's a Y in the first place.

Each commit you make in X or X2 carries with it the correct commit to check out in a Y or Y2. Hence, if you ever add a new commit to a Y repository, you must then also go back to the corresponding X superproject, run git add there to pick up the new hash ID from the updated Y, and run git commit in X to record that new hash ID in a new X commit. That way, any clone of this X will know to get the new Y commit. Clones of X are not using any Y names-database to get commit hash IDs for a Y submodule. They're using commits within the clone of the superproject X.

In other words, it's all a question of where the hash ID comes from. Branch names feed into branch-and-other-names databases within a Git clone, but they're easily changed. Superprojects that are controlling submodules want a rigid, unchangeable identifier for the commit to check out in the submodule—and that's a hash ID, not a name.

(Humans sometimes want more flexibility than this, and the first answer submodules give to that is "tough s**t". However, Git does now have some mechanisms for recording branch names and trying to use them. But backwards compatibility means that these mechanisms are klunky and extremely user-unfriendly, and I don't recommend them as they are not only klunky, they're also fragile. Know what the original design here is, and hence why submodules behave the way they do, and use that.)

torek
  • 448,244
  • 59
  • 642
  • 775
0

Well, this is embarrassing, it took us way too long to figure this out because we weren't reading properly, as you can already tell from the question.

The reason it worked fine on my machine and not on my colleague's machine is because I was using https to check out the repository and he was using SSH. The submodule was included with a https url and that failed. I used the relative path as suggested here https://stackoverflow.com/a/48067316/1980516

Diana
  • 789
  • 8
  • 34