stsquad
stsquad

Reputation: 6022

What's the best way to find if a given git commit is in a tagged release

A common problem when dealing with fixes is to work out what releases given fixes have been applied to, i.e "is this fix in release X". What's the best way in git to check what tagged release contains a given commit id.

Going through with gitk manually eye-balling a commit in a complex merge pattern is surprisingly hard.

So far the best solution we can come up with has been to use git-cherry:

git-cherry -v $TAG $COMMIT $COMMIT^

And see if it appears with a -. Is there a better way?

Upvotes: 4

Views: 609

Answers (1)

Mark Longair
Mark Longair

Reputation: 467031

This is nice and easy to do, in fact, with the following command:

git tag --contains f414f31

That will list all the tags such that f414f31 is one of the tag's ancestors, or the tag itself points to that commit.

This is particularly useful for finding which versions of git contain a particular feature :)


Update:

To answer a further question in the comment below:

Is there any easy way to find out all the equivalent commits that may have been applied to separate branches?

You can find a hash of the patch introduced by the commit by using git patch-id - that's the command that git cherry, git rebase, etc. use to find whether a commit has already been cherry-picked. So, if you want to find whether the change introduced by f414f31 was also introduced by a commit on the branch foo, you could always use a short shell script something like:

patch_id () {
    git show $1 | git patch-id | cut -d ' ' -f1
}

P=$(patch_id f414f31)

git rev-list foo | while read C
do
    P2=$(patch_id $C)
    if [ x$P = x$P2 ]
    then
        echo "Also introduced by commit $C"
    fi
done

If you want to look across all branches, you can replace foo with --all. Jefromi's comment below suggests a couple of other refinements, e.g. you can add a break if you want to stop looking after the first match (sensible if you're only searching a single branch), or exclude all ancestors of the original commit by using git rev-list foo ^f414f31 instead.

Jefromi's comment also reminds me that I should say a bit more about this approach. The documentation for git patch-id explains that the ID generated is "reasonably stable" - the line numbers and whitespace can change without affecting the ID, but if you had to fix any conflicts during the cherry-pick or rebase, you may end up changing the text of the patch. In that case, this wouldn't find the commit.

I'm sure you can also do this with an invocation of git cherry somehow, but I can never remember which way round the arguments are meant to go... ;)

Upvotes: 9

Related Questions