Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where is a submodule commit number stored (and how do I change it)?

Tags:

git

In order to get a project with submodules, you run this command after cloning the project:

git submodule init

This command reads .gitmodules and writes information about the module into the index.

Then you run

git submodule update

Which gets a certain commit of the submodule repository.

How does git know which commit in particular to get? Where is this information stored?

The reason I do not understand this, is because I can see that it's not in .gitmodules but I think it's also unlikely to be in the index, since it's git submodule init that writes it into the index. So it leaves this information no logical place to be, that I can think of.

When the above is answered, how do we change this commit number, so that a submodule can be retrieved at a different commit next time?

Note: I read this, this and this. I may have missed it but I did not find the answer to my question.

Update 1

I'd like a clarification on larsks's answer below. It is excellent answer, however I'd like to clarify the following.

In the answer, git checkout a18306f command is used. I'd like to see if I there is a shortcut to doing this for the latest commit on the branch. In order to run this command currently I need to do this:

git branch
## Note the current branch name, let's assume it's master, 
## use this branch name in the following command
git log -1 origin/master
## Now note the commit number. 
## This is where a18306f in the example above comes from in my use case. 
## And finally
git checkout a18306f

Is there a better way of doing that?

like image 365
Andrew Savinykh Avatar asked Feb 04 '16 21:02

Andrew Savinykh


People also ask

Where is the submodule commit stored?

It is stored in Git's object database directly. The tree object for the directory where the submodule lives will have an entry for the submodule's commit (this is the so-called "gitlink").

How do I change my submodule location?

Git Submodules Moving a submodule If needed, create the parent directory of the new location of the submodule ( mkdir -p new/path/to ). Move all content from the old to the new directory ( mv -vi old/path/to/module new/path/to/submodule ). Make sure Git tracks this directory ( git add new/path/to ).

How do I change 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.


1 Answers

How does git know which commit in particular to get? Where is this information stored?

This information is stored as an object in the git filestore. For example, take the ansible repository, which includes the following submodules:

$ git submodule 
+ce6619bf5db87f94001625c991d02960109dee2d lib/ansible/modules/core (remotes/origin/stable-2.0.0.1)
+29af26884ea11639f38c145b348afccdb6923285 lib/ansible/modules/extras (remotes/origin/stable-2.0.0.1)

We can use git cat-file to see the contents of the repository. We start by finding the tree object for the top-level directory in our current commit...

$ git cat-file -p HEAD
tree a67c8a8e47ea232c9404cc1a971c6134c4008c65
parent 4b7b3794c9a3876080633eae2166a741a3330b27
author Toshio Kuratomi <[email protected]> 1454618685 -0800
committer Toshio Kuratomi <[email protected]> 1454618685 -0800

Fix --diff to respect no_log task parameter.

And then work our way down:

$ git cat-file -p a67c8a8e47ea232c9404cc1a971c6134c4008c65 | grep lib
040000 tree 68fa387f2e92cd18288b548a2007ac7ad4c43849    lib
$ git cat-file -p 68fa387f2e92cd18288b548a2007ac7ad4c43849 | grep ansible
040000 tree 6de49b0c156a5055575332e7fe527c9a5e6ca216    ansible
$ git cat-file -p 6de49b0c156a5055575332e7fe527c9a5e6ca216 | grep modules
040000 tree 94211515f23e286a634a7cdaab7958d286bd145f    modules
$ git cat-file -p 94211515f23e286a634a7cdaab7958d286bd145f
100644 blob ae8ccff5952585ebf8134e2f7d09dbfb63772976    __init__.py
160000 commit e1ec52e365a8fbe95c83db5da3046730c4dc39b2  core
160000 commit 14a62fb5d6771871654aedb4a36e17cf358785dc  extras

And there at the end we see the two commit objects that encode the current state of the submodules.

When the above is answered, how do we change this commit number, so that a submodule can be retrieved at a different commit next time?

You change into the submodule:

$ cd lib/ansible/modules/core

Then checkout the commit you want:

$ git checkout a18306f

Return to the parent module, where you will see:

$ cd ..
$ git status
On branch devel
Your branch is up-to-date with 'origin/devel'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

  modified:   core (new commits)

And commit the new submodule version:

$ git commit -m 'updated submodules to new commit' core
like image 142
larsks Avatar answered Sep 30 '22 03:09

larsks