Here's what I suggested as a comment, in expanded form. (I think this is what you're asking for.)
We set K to your chosen commit (abcdefg1234
in your example). Then, we want to iterate through all labels L where L has the form refs/heads/*
or refs/remotes/*
(all branches and remote-tracking branches). Each label L points to some specific commit C. If C is an ancestor of K, print label L.
[Edit: as sschuberth answered, this is just git branch --merged
; the new feature I was thinking of is that git for-each-ref
also now implements --merged
, which means you can script things more easily, but if all you want is the names, git branch
does it. If you do want tags, see git tag --merged
, if available. If your version of Git is too old, read on to the script. :-) ]
Here is a shell script (untested!) that implements this. Note that git for-each-ref
has new capabilities in later versions of Git that would simplify this, but this should work all the way back to 1.6-ish—maybe 1.7-ish; I forget when git merge-base
acquired --is-ancestor
.
#! /bin/sh
# find branches and remote-tracking branches that targt
# ancestors of $1.
showthem() {
local tgt label lbltgt
tgt=$(git rev-parse "$1") || return $?
git for-each-ref --format='%(refname:short) %(objectname)' \
refs/heads refs/remotes |
while read label lbltgt; do
if git merge-base --is-ancestor $lbltgt $tgt; then
echo "$label"
fi
done
return 0
}
case $# in
0) usage 1>&2; exit 1;;
1) showthem "$1";;
*) for i do "echo ${i}:"; showthem "$i" || exit; done
esac
(You may want to tweak this slightly, e.g., to discard symbolic refs like origin/HEAD
.)