Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git Submodule : Cannot update submodule to an earlier revision

I have spent a lot of time in reading and trying out git submodules. But I have really given up.

My problem:

I am cloning a git repository as a submodule. So, I do

git submodule add -b master url localpath

The repository starts downloading and a corresponding entry is made in the .gitmodules file. git submodule status shows the latest commit.

So far so good.

During the development, it was found out that the HEAD commit in the submodule has a bug. So, the commit should be changed from master to some commit id.

So, I changed the commit id ( 7 aplhanumeric ) in the .gitmodule file from branch = master

branch = <commitid> -> .gitmodule file

And did

git submodule update --remote

The error is

Fatal: Need a single revision

Unable to find current origin/ revision in submodule path

I also tried

 git submodule foreach git pull

so that it will pull the commit id, but it simply returns with

Entering name_of_the_submodule

Already up to date.

Can anyone please help me?

P.S: I have already gone through many tutorials and question and answers. So if you want to downvote this for fun, then please first point to an answer and I will delete this post.

like image 864
infoclogged Avatar asked Apr 04 '17 13:04

infoclogged


People also ask

How do I force git update a submodule?

In order to update an existing Git submodule, you need to execute the “git submodule update” with the “–remote” and the “–merge” option. Using the “–remote” command, you will be able to update your existing Git submodules without having to run “git pull” commands in each submodule of your project.

Do submodules update automatically?

Submodules are very static and only track specific commits. Submodules do not track git refs or branches and are not automatically updated when the host repository is updated. When adding a submodule to a repository a new . gitmodules file will be created.

How do you fix a dirty submodule?

You can fix it by: either committing or undoing the changes/evolutions within each of your submodules, before going back to the parent repo (where the diff shouldn't report "dirty" files anymore). To undo all changes to your submodule just cd into the root directory of your submodule and do git checkout .

How do you Reinit a submodule?

Initialize the repository's submodules by running git submodule init followed by git submodule update . Change into the submodule's directory. In this example, cd lib/billboard . The submodule repositories added by git submodule update are “headless”.


1 Answers

I am answering my own question, after a little bit of research, that might be helpful to the others:

It is a big pain to understand git submodules, but once you get it, everything starts making sense !

The following post shows:

  • adding submodules and letting others sync with your submodules.
  • updating submodules and letting others sync with your submodules.
  • removing submodules and letting other sync with your submodules.
  • updating the removed submodules.

Adding submodules

git submodule add -b

The entry in .gitmodules ( name, path, url, branch ) downloads the respective submodule by

git submodule update --init

This does three important thing, the first two of which are hidden from the user:

  1. updates .git/config with an extra entry ( submodules )

  2. downloads a repository in bare form under .git/modules. That means, there is .git inside a .git.

  3. checks out the git submodule from the .git/modules into the parent directory.

Now, on Day 2, the commiter, who commited the submodule realises, that he should change the submodule to some other commit and not the HEAD. So, he would go to his local repository and then go the submodule path and then checkout the commit that he wants by simply invoking

git checkout <hash>
cd <parent dir>
git submodule status

At this point, the git submodule status still does not shows the new hash. The new hash will only be visible when the changes are staged. Now, the commiter, just needs to stage ( add ), commit and push the changes, so that it is visible to all the other developers.

Updating the added submodule

On Day 3, the other developers, would update their repository by just invoking the command

git pull # this is to get the latest commit of the parent git repository.
git submodule update --force # update the submodule with latest hash

Basically, here the point is simple: The submodule does not react until and unless it is told to do so. Just doing git pull, wont update the git submodule. The developers can continue to work on their local submodules and not sync them to the one on the server "forever". The submodule update would happen on explicitly invoking the git submodule update command.

Removing submodule

Now, on Day4, the committer, decides to remove the git submodule completely. Here the steps are also not simple, because there is nothing called git submodule rm that should have been equivalent to git submodule add. This can be done only and only if the following sequence is followed:

git submodule deinit submodulename
  1. this deletes the .git/config entry.

  2. this clears the submodule directory !! You will see nothing in the submdoule directory after this command.

  3. But the contents of the submodule are still available under .git/modules

Hence a git status -u here will still show that Everyting is upto date !

So show the removals,

git rm submodulepath

At this point git status will return that .gitmodules has been changed ( the submodule has been deleted ) and the submodule path has been deleted. Commit and push the changes.

Updating with removed submodule

On Day5, the developers want to delete the submodules "automatically" like it did with git submodule update. So they do first a git pull, which succesfully removes all indices to the git submodules

 git submodule status # shows nothing

BUT, the .git/config still contains valid submodule entry and the submodule folder is there with all its contents and the bare repository under .git/submodules ! There is no command to delete them. All of them must be explicitly removed via hand..( Please correct me if I am wrong )

like image 81
infoclogged Avatar answered Oct 03 '22 03:10

infoclogged