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?
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").
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 ).
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With