2

I have a repo which has a submodule. For a given SHA of the submodule, I want to find commits in the repo where this submodule exists and has the given SHA.

How would I do this with the most recent version of git?

Kentzo
  • 3,881
  • 29
  • 54

1 Answers1

0

You can use git ls-tree to read that gitlink (a special entry in the index) to read the SHA1 of a submodule:

git ls-tree HEAD mysubmodule 
160000 commit c0f065504bb0e8cfa2b107e975bb9dc5a34b0398  mysubmodule 

That will include the SHA1 at which the submodule is recorded in the parent repo.

Knowing that, you can combine it with a git filter-branch, using an index filter (to avoid having to checkout the parent repo for each commit)

git filter-branch --prune-empty --index-filter 'git ls-tree mysubmodule' -- --all|grep <yourSHA1>

A shell approach combining git rev-list and git ls-tree is probably cleaner:

#!/bin/sh
for r in $(git rev-list FIRST_REV..LAST_REV) 
do 
    git ls-tree $r mysubmodule
done | grep <yourSHA1>

With git 2.7, you will soon get:

git for-each-ref --contains <SHA1>

That should be easier.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • That's not what I asked for. I want for a given SHA of a submodule to find commits in the repo that has it. – Kentzo Dec 31 '15 at 07:47
  • @Kentzo so find in the parent repo commits the commits which reference a gitlink specific SHA1? – VonC Dec 31 '15 at 07:49
  • @Kentzo OK. I'll have to test it, but the first approach would be to use a filter-branch. I have updated the answer. – VonC Dec 31 '15 at 07:54
  • Hm, this strikes me off-hand as abuse of filter-branch, although it should work fine (it just "feels wrong" to use a rewrite tool when you're not rewriting—and the `--prune-empty` might actually make changes, too). There's no other command that will quickly scan through each commit though. Perhaps git needs a `for-each-object` command, a la `for-each-ref`... – torek Dec 31 '15 at 08:02
  • @torek I agree. I am still experimenting as we speak (write) – VonC Dec 31 '15 at 08:02
  • @torek note that for-each-ref is soon greatly improved with git 2.7 (http://stackoverflow.com/search?q=user%3A6309+for-each-ref+2.7) – VonC Dec 31 '15 at 08:04
  • I fail to see how `for-each-ref` solves this problem. Using the given command in this answer, it doesn't work in the parent repo because the SHA1 specified doesn't exist in the parent, it is a commit in the submodule. And `for-each-ref` doesn't inspect file contents to match SHA1s using the gitlink. – void.pointer Nov 12 '18 at 14:29
  • @void.pointer "because the SHA1 specified doesn't exist in the parent" Yes it should (exist in the parent): we are talking about the gitlink SHA1, that is the SHA1 of the root tree of the submodule repo, as recorded by the parent repo. – VonC Nov 12 '18 at 17:13
  • @VonC But for all intents and purposes, that's file contents, not an actual SHA1 in the parent repo itself. Point is, I ran your command and it failed. I do not see an example of how `for-each-ref` helps you find the SHA1 of the parent repo that contains a modification to point to a different SHA1 of a submodule. Unless I'm misunderstanding the question, I do not see how this solves the problem. Need a better example/explanation. – void.pointer Nov 12 '18 at 21:19
  • @void.pointer "that's file contents": that is not how I interpreted the OP's request at the time (3+ years ago). For me, "has the given SHA" refers to the root tree of the submodule repo, not to a file content. – VonC Nov 12 '18 at 22:15
  • @void.pointer But don't hesitate to illustrate your issue in a separate question, with an example, what you got vs. what you expected. – VonC Nov 12 '18 at 22:15