Larry The Blackbird
Larry The Blackbird

Reputation: 89

Git Submodule has a wrong reference to its remote repository

I have two submodules in my main repository, both linked to two another remote repositories.

I think I somehow manage to put my 2nd submodule on some other branch or something like that.
Long story short, I cannot even clone the main rep anymore (git clone --recursive-submodules) cause the 2nd submodule has a wrong ID and cannot get linked to its remote rep.
I am getting "error: no ref to the remote rep".

Can someone help me?
How can I change the ID of a submodule?
Or do I need to get back my 2nd submodule on the main branch?

Upvotes: 1

Views: 3969

Answers (2)

VonC
VonC

Reputation: 1326746

How can I change the ID of a submodule?

In your case, you cannot clone your submodule repo, because its gitlink, (special entry in the index of the parent repo) references a SHA1 that was not pushed to the remote repo of said submodule.

Since you don't have the submodule folder content (it cannot be checked-out), you cannot simply add, push and commit from said submodule.

In order to complete the clone, it is best to change the associated gitlink SHA1 to its previous version:

git checkout $(git log -1 --format=format:%H yoursubmodule) -- yoursubmodule

Replace yoursubmodule by the name of the folder representing your submodule, without trailing slash (since it is an entry in the index, not a folder)

Then a git submodule update --init should be enough to initialize that submodule content.

Finally, see "Git submodules: Specify a branch/tag", and associate your submodule to a branch:

git config -f .gitmodules submodule.<path>.branch <branch>

That way, next time, a git submodule update --remote will be enough to update your submodule to the latest remote SHA1 of that branch.

Upvotes: 2

torek
torek

Reputation: 489073

TL;DR: what you got is, I think, the case I mention below where you have not pushed the submodule commit. So now when the superproject goes to get the one specific commit out of the submodule the superproject has cloned, it (the superproject Git) cannot find it (the desired commit in the submodule).

Background

Submodules are a pain because there is an enormous tension between the fact that each submodule itself is a Git repository, and the fact that each "superproject" (controlling a submodule) insists that it knows which commit that the submodule must use.

This all works just fine when all of your submodules are external libraries that someone else maintains. You write some code that needs libraries A, B, and C. You test it with "commit 1234567" from A, "commit 8888888" from B, and "commit fedcba9" from C, and it all works ... so you decree that this version of the code shall always and forever use those three commits from those three submodules.

You do this simply by making a commit in the superproject. Each commit records, for all time, exactly which commits the submodules must be on.

Then, whenever you check out the superproject, you tell your superproject Git to go meddle in each sub-repository and detach its HEAD. This is why you see "detached at" or "detached from". The "at" or "from" part is totally irrelevant at this point: pay no attention to it! This is meant for your information when you are working on those libraries, and because you're actually working on the superproject, your superproject Git assumes that you are not working on them.

But there's the rub: what if you want to work on them? Your superproject Git screams at you, No no no, you may not touch them! I control them! :-) Well, it's not quite that bad, but ... it's bad.

To work in a repository, you generally want to be on a branch. So you must go into the submodule and undo what your superproject Git did, by checking out some particular branch. Now you can work on the submodule in the normal fashion.

But this upsets your superproject Git. Moreover, you can't really test it until you have everything all lined up again. You must enter all the submodules, yank them back into "branch-y" mode, work in them, maybe test them individually, and maybe even make commits. Now you can go back to your superproject ... but you can't make commits there yet, because they're still remembering the old detached-HEAD hashes!

The only way to get everything all lined up again is to actually make the commits in the submodules. Now each submodule has a new hash ID, which each submodule's Git assigned when you made the commits there. You may now climb back up to your superproject and tell that Git: "I'm ready to commit, but before I do, here are your new hash IDs." You do this by git add-ing each submodule again, which makes your superproject Git go and read out the submodule hashes and put them into your superproject's index. Now you can git commit in the superproject, which permanently, forevermore, records the new commit as using the new hashes for each of the various submodules.

Note that if you now push the superproject, everyone else has a problem: the new commits you made in the submodules are in your submodule repositories, but those commits have not yet been pushed back to wherever they may go. Anyone who fetches your new superproject commit gets a commit that says "submodule A shall use commit feedcab", but they can't get commit feedcab until you push that too. So you must push all the submodules first, and only then push the superproject.

This does all work, but notice how brittle and fragile the process is. Git's submodules have gotten better over time, in that you can now actually tell the superproject controlling Git to (recursively) descend into each submodule Git and put that on a branch (whose branch name is recorded in the superproject). That takes care of the first problem.

If you're not the one who controls the submodule's remote repository, though, you get a different set of problems. The git submodule update command has grown a whole raft of additional options to try to accommodate these cases as well. The git submodule foreach command lets you run anything (such as your own scripts) in every submodule, which gives you complete control, at the expense of making you write, well, complete control. But the situation with submodules is still fairly messy, and many organizations try to avoid them (I would, and do, myself).

Upvotes: 1

Related Questions