365

What I'm trying to do is a version check. I want to ensure the code stays on top of a minimum version. So I need a way to know if the current branch contains a specified commit.

boatcoder
  • 17,525
  • 18
  • 114
  • 178
TieDad
  • 9,143
  • 5
  • 32
  • 58
  • 7
    Possible duplicate of [How to list branches that contain a given commit?](http://stackoverflow.com/questions/1419623/how-to-list-branches-that-contain-a-given-commit) – kowsky Apr 21 '17 at 06:11
  • 15
    See the proposed duplicate for how to find *all* branches that contain a specified commit. To find out if the *current* branch contains commit *C*, use the "plumbing" command `git merge-base --is-ancestor`. The current branch contains *C* if *C* is an ancestor of `HEAD`, so: `if git merge-base --is-ancestor $hash HEAD; then echo I contain commit $hash; else echo I do not contain commit $hash; fi` – torek Apr 21 '17 at 08:09
  • 1
    Hi, please submit this as an answer so that it can be selected as the correct answer =) – Ben Feb 15 '18 at 21:18
  • 1
    @Ben - I added it as a community wiki answer. – Zitrax Sep 03 '18 at 13:39
  • 1
    @torek one strange thing i find is the docs on `--is-ancestor`: `Check if the first is an ancestor of the second , and exit with status 0 if true, or with status 1 if not.`. this makes me think the `if` in your snippet is the wrong way around since it exits with `0` for true but in practice it seems to work... could the docs be wrong or am I just reading it wrong?? – Remover Aug 21 '19 at 10:40
  • 2
    @Remover: in shell scripts, zero is true, nonzero is false: the reverse of the C convention. `/bin/true` was originally implemented as `exit 0` and `/bin/false` as `exit 1`. (Modern shells have then built in.) – torek Aug 21 '19 at 16:12

10 Answers10

438

There are multiple ways to achieve this result. First naive option is to use git log and search for a specific commit using grep, but that is not always precise

git log | grep <commit_id>

You are better off to use git branch directly to find all branches containing given COMMIT_ID using

git branch --contains $COMMIT_ID

The next step is finding out current branch which can be done since git 1.8.1 using

git symbolic-ref --short HEAD

And combined together as

git branch $(git symbolic-ref --short HEAD) --contains $COMMIT_ID

But the command above doesn't return true or false and there is a shorter version that returns exit code 0 if commit is in current branch OR exit code 1 if not

git merge-base --is-ancestor $COMMIT_ID HEAD

Exit code is nice, but as you want string true or false as answer you need to add a bit more and then combined with if from bash you get

if [ 0 -eq $(git merge-base --is-ancestor $COMMIT_ID HEAD) ]; then echo "true"; else echo "false"; fi
ThomasMcLeod
  • 7,603
  • 4
  • 42
  • 80
JiriS
  • 6,870
  • 5
  • 31
  • 40
  • 22
    That's not correct; the `grep` could result in false positives if `git log` mentions the commit SHA for other reasons, e.g. it's mentioned in a commit message as the result of a port from another branch. – Adam Spiers Jul 27 '17 at 15:21
  • 3
    Please see the comment on the question, which uses the built-in git toolset. https://stackoverflow.com/questions/43535132/given-a-commit-id-how-to-determine-if-current-branch-contains-the-commit/43535152#comment74126598_43535132 – Ben Feb 15 '18 at 21:18
  • 3
    I like the first option, but to rule out Adam's objection, I would add the option `--format=format:%H` to `git log`. – PJSCopeland Feb 20 '18 at 23:27
  • @AdamSpiers If you're doing this programmatically, sure, but to the human eye it should be clear. git log messages are formatted so that the entries start with `commit 012345beef`, and then the content is prefixed by spaces, `____Adds lime to coconut`. So only if a line started and only contained the word commit and hash would it look suspect. Normally you'd see something like `____(cherry picked from commit 12341234)`. ***(Note, I had to put underscores because it renders the Markdown wrong if I use spaces.)*** – Captain Man Sep 02 '20 at 19:24
  • When used in *detached head* mode repo, `merge-base --is-ancestor` worked while other options didn't. Thanks. – Chen A. Sep 16 '20 at 17:13
  • how do you search within remote branches? The issue is `git branch -r != git branch --list` – Geoff Langenderfer Mar 07 '22 at 01:08
  • @AdamSpiers If you're concerned about that then use `git branch --contains $COMMIT_ID | grep "$(git branch --show-current)"`. – aderchox Jun 28 '22 at 05:18
113

Get a list of branch(es) that contains the specific commit.

# get all the branches where the commit exists
$ git branch --contains <commit-id>

Check if a branch has the specific commit.

# output the branch-name if the commit exists in that branch
$ git branch --contains <commit-id> | grep <branch-name>

Search the branch (say, feature) with exact matching.

$ git branch --contains <commit-id> | grep -E '(^|\s)feature$'

e.g. If you have 3 local branches called feature, feature1, feature2 then

$ git branch --contains <commit-id> | grep 'feature'

# output
feature
feature1
feature2

$ git branch --contains <commit-id> | grep -E '(^|\s)feature$'

# output
feature     

You can also search in both local and remote branches (use -a) or only in remote branches (use -r).

# search in both 'local' & 'remote' branches  
$ git branch -a --contains <commit-id> | grep -E '(^|\s)feature$'

# search in 'remote' branches  
$ git branch -r --contains <commit-id> | grep -E '(^|\s)feature$'
Sajib Khan
  • 22,878
  • 9
  • 63
  • 73
  • 1
    The `grep` here could also result in false positives if there are other branches containing the commit whose names also contain `` as a substring. – Adam Spiers Jul 27 '17 at 15:23
  • 1
    Yes @AdamSpiers, Updated the answer with exact matching the branch name by `grep -E '(^|\s)branchname$'` – Sajib Khan Jul 27 '17 at 22:46
  • 2
    Per [this comment on the related question](https://stackoverflow.com/questions/2706797/finding-what-branch-a-git-commit-came-from#comment9642845_2707110) it can be useful to add the `-r` ("remote") or `-a` ("all") option to `git branch` to look for branches that may not be replicated in the local repo clone. – sxc731 May 23 '18 at 08:37
  • This didn't work for me, I needed `git branch --all --contains ` – Arthur Tacca Mar 13 '20 at 10:53
  • Doesn't actually show all the branches for me, if I'm on master - it shows it & its remotes, if I'm in my feature branch - shows the branch and it's remotes, but not master – Alexander Telegin Apr 11 '23 at 07:01
18

Extracted comment by @torek as answer:

See the proposed duplicate for how to find all branches that contain a specified commit.

To find out if the current branch contains commit C, use the "plumbing" command git merge-base --is-ancestor. The current branch contains C if C is an ancestor of HEAD, so:

if git merge-base --is-ancestor $hash HEAD; then
    echo I contain commit $hash
else
    echo I do not contain commit $hash
fi

(Side note: in shell scripts, a command that exits zero is "true" while one that exits nonzero is "false".)

torek
  • 448,244
  • 59
  • 642
  • 775
Zitrax
  • 19,036
  • 20
  • 88
  • 110
13

Checks only in the local branches, that's been checked-out.

git branch --contains $COMMIT_ID

Checks in all the branch (local and remotes that are fetched)

git branch -a --contains $COMMIT_ID

Make sure to fetch the remote

git fetch origin
PKV
  • 424
  • 4
  • 6
11

To list local branches containing commit:

git branch --contains <commit-id>

and to list all branches, including remote only, containing commit:

git branch -a --contains <commit-id>

Similarly to check if commit is in particular branch:

git log <branch> | grep <commit_id>

and if branch does not exist locally prefix branch name with origin/

hgrey
  • 3,033
  • 17
  • 21
9

Yeah another alternative:

git rev-list <branch name> | grep `git rev-parse <commit>`

This works best for me since it also works on locally cached remote branches such as remotes/origin/master, on which git branch --contains won't work.

This covers more than OP's question about just "current branch" but I find it dumb to ask a "any branch" version of this question so I decide to post here anyway.

xiay
  • 855
  • 8
  • 19
3
git branch --contains <commit-id> --points-at <target branch name>

It will return the target branch name if the commit id exists in that branch. Otherwise the command will fail.

DreamUth
  • 122
  • 2
0

Since this question has some nice scripty answers, I'm adding my favorites.

This one will show you, for last $n commits in $br which branches contains each:

br=mybranch
n=10
git log --oneline -n$n $br | awk '{print; system("git branch --contains "$1)}'

This one is similar but does the same for a list of branches:

br="mybranch yourbranch herbranch"
n=4
for br in $brs; do git log --oneline -n$n $br | awk '{print; system("git branch --contains "$1)}'; done
Bruno Bronosky
  • 66,273
  • 12
  • 162
  • 149
0

On a Windows machine on Windows/CMD terminal. You can do:

> git log | findstr "commit-id"

like:

> git log | findstr "c601cd6366d"
Habib
  • 219,104
  • 29
  • 407
  • 436
-1

Git checkout will return you to the branch of your current HEAD (current file) but it will not check out all branches. For example if you do a git checkout master the code will be checked out as if you were on master branch but it will not check out any files for changes outside of that branch.