简体   繁体   中英

Given a commit id, how to determine if current branch contains the commit?

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.

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

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$'

eg 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$'

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".)

Yeah another alternative:

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

This works best for me since it would also work 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.

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/

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.

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

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

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

> git log | findstr "commit-id"

like:

> git log | findstr "c601cd6366d"

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.

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

git log | findstr "commit-id" like:

git log | findstr "c601cd6366d"

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM