I want to see all branches that are ancestors of commit abcdef1234
.
This is sort of the inverse of:
git branch --contains abcdef1234
The above command would list all branches that are descendants of abcdef1234
. I want to see a list of all branches that are ancestors of abcdef1234
.
I am also interested the equivalent for tags.
UPDATE
To be extra clear, I mean I want to see a list of all commits that meet 2 criteria:
abcdef1234
Obviously most commits at some point had a branch pointing to them when they were brand new. I am only interested in whether they are branches at this particular moment.
It is based on "Find merge commit which include a specific commit". Find when a commit was merged into one or more branches. Find the merge commit that brought COMMIT into the specified BRANCH(es). Specifically, look for the oldest commit on the first-parent history of BRANCH that contains the COMMIT as an ancestor.
If you add --sort=authorname to the above command you can get your branches grouped together.
The git log command shows a list of all the commits made to a repository. You can see the hash of each Git commit, the message associated with each commit, and more metadata. This command is useful for displaying the history of a repository.
git merge-base finds best common ancestor(s) between two commits to use in a three-way merge. One common ancestor is better than another common ancestor if the latter is an ancestor of the former. A common ancestor that does not have any better common ancestor is a best common ancestor, i.e. a merge base.
git branch --merged abcdef1234
should do what you want. It lists all branches that are merged into the named commit (and thus are ancestors of it), i.e. those whose tip commits are reachable from the named commit.
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
.)
comm -23 <(git branch -a | sort) <(git branch -a --contains abcdefg1234 | sort)
This will give you all the branches that do not have commit abcdefg1234
; it's the output of git branch -a
minus the output of git branch -a --contains abcdefg1234
.
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