How can I get a git submodule's associated commit ID from a past commit in the parent clone?
Is there a way, short of actually checking out the parent commit, to determine a submodule's SHA-1 commit ID based on a commit ID in the parent clone? I know I can find the currently associated SHA-1 with git submodule
.
Here's an example:
- I have a clone with a single submodule
foo
that has changed several times in the last month. - I have a tag in the parent clone that is a few weeks old called
released-1.2.3
. I want to find out what the associated SHA-1 offoo
was for this tagged commit. - I could simply check out
released-1.2.3
and usegit submodule
to see, but I'm wondering if there's a way to do this without affecting the working tree, as I want to script it.
I want to do this because I want to construct a script to do a 'diff' on all changes within a submodule between two commit开发者_Python百科s within the parent repository - i.e. "tell me what files changed within the submodule foo
between these two commits in the parent."
You may use git-ls-tree
to see what the SHA-1 id of a given path was during a given commit:
$ git ls-tree released-1.2.3 foo
160000 commit c0f065504bb0e8cfa2b107e975bb9dc5a34b0398 foo
(My first thought was git show released-1.2.3 foo
, but that fails with "fatal: bad object".)
Since you are scripting the output, you will probably want to get just the SHA-1 id by itself, e.g.:
$ git ls-tree released-1.2.3 foo | awk '{print $3}'
c0f065504bb0e8cfa2b107e975bb9dc5a34b0398
Also: When writing scripts around git, try to stick to the plumbing commands, as described in the manual. They have a more stable interface, while the more familiar “porcelain” commands will possibly change in incompatible ways.
This one worked for me:
$ git rev-parse released-1.2.3^{commit}:foo
<SHA1>
Perhaps also quite easy to use in script.
I did find one promising avenue:
$ git log --raw <since>..<until> --submodule -- <path/to/submodule>
With the --raw option, this does print out the (abbreviated) SHA-1 IDs corresponding to the submodule's associated commits. Unfortunately the output is very verbose and will take some work to process in a script.
What I really need is a git facility that, given a parent commit ID, gives me the latest change to a submodule prior to that commit. I.e. which submodule SHA-1 'git submodule update' would check out if I were to actually checkout that parent commit.
git slave (gits) might be your answer.
http://gitslave.sourceforge.net/
But you can also do this with plain git.. it's not as easy.
git
ls-tree
will do the job.
But sometimes you should call it several times or use -r
to show subentries recursively.
├─project
│ └─submodules
│ ├─submodule_a
│ ├─submodule_b
│ ├─...
For example, if you has such a project directory, and you want the commit id of submodule_a
with an tag name in parent module.
git ls-tree v5.4.0
will give you the tree id of directory submodules
, not commit id. It looks like as following.
040000 tree e542bc1b084a0394ff16452c27df6572366e0009 submodules
Just feed ls-tree
with the tree id, and you will get the actual commit id of each submodule.
git ls-tree e542bc
You will get something like this.
160000 commit 0f253bf94e0345600cb7a234a24eeec8ee3533bd submodule_a
160000 commit 0edcbaf94e034987cb4eeec8ee3533bd12349ade submodule_b
Or just use
git ls-tree v5.4.0 -r
to check all entries tree id or commit id.
精彩评论