I think you may be misusing the term "detached HEAD" here to refer to a dangling commit (and I'm basing this answer on that assumption).
To start with, we would need a list of all the commits in a repository, including "dangling" commits that aren't currently reachable from any branch, tag, or other reference. At some point, git cat-file
developed options that make this really easy:
git cat-file --batch-check --batch-all-objects
If your version of git
doesn't have these options, there are other ways to get a list of all objects.
The above will produce output like:
2bd7a7d258cb8c0f529e267e72c37bfee2be3a92 tree 32
2d83b892c0922c9168d3c474e73da24301bc86bf tree 64
3eda82acd62f56b19d88a80650ed88428be8ac9b commit 231
42dae79fef2ede926a081821e6a7cf89387cd9f0 tree 66
5e9fac93b855f5cf5ed44969cf9cc53121195377 blob 29
b01735609620636d7b0179a940f7409a32041f87 commit 182
We're only interested in commits, so we would filter that through awk
:
$ git cat-file --batch-check --batch-all-objects | awk '$2 == "commit" {print $1}'
3eda82acd62f56b19d88a80650ed88428be8ac9b
b01735609620636d7b0179a940f7409a32041f87
Now, for each commit, we need to first extract the top-level tree id:
git show --quiet --format='%T' <commit id>
And then recursively list all the trees contained in that tree:
git ls-tree -r -t <tree id>
Putting it all together, we get:
#!/bin/sh
git cat-file --batch-check --batch-all-objects |
awk '$2 == "commit" {print $1}' |
while read cid; do
tree=$(git show --quiet --format='%T' $cid)
echo $cid $tree
git ls-tree -r -t $tree |
awk -v cid=$cid '$2 == "tree" {print cid,$3}'
done
This will, for every tree object discovered, output a line of the format:
<commit id> <tree id>
So the answer to your question is to pipe the output of the above script into grep <tree id>
(or modify the script to only output the specific information you want).