How to list branches that contain a given commit?
Asked Answered
D

3

1290

How can I query git to find out which branches contain a given commit? gitk will usually list the branches, unless there are too many, in which case it just says "many (38)" or something like that. I need to know the full list, or at least whether certain branches contain the commit.

Dudek answered 14/9, 2009 at 4:3 Comment(2)
See also: How to list all tags that contain a commit?.Canea
Related question for an equivalent commit per comments: stackoverflow.com/questions/16304574/…Achlamydeous
S
1729

From the git-branch manual page:

 git branch --contains <commit>

Only list branches which contain the specified commit (HEAD if not specified). Implies --list.


 git branch -r --contains <commit>

Lists remote tracking branches as well (as mentioned in user3941992's answer below) that is "local branches that have a direct relationship to a remote branch".


As noted by Carl Walsh, this applies only to the default refspec

fetch = +refs/heads/*:refs/remotes/origin/*

If you need to include other ref namespace (pull request, Gerrit, ...), you need to add that new refspec, and fetch again:

git config --add remote.origin.fetch "+refs/pull/*/head:refs/remotes/origin/pr/*"
git fetch
git branch -r --contains <commit>

See also this git ready article.

The --contains tag will figure out if a certain commit has been brought in yet into your branch. Perhaps you’ve got a commit SHA from a patch you thought you had applied, or you just want to check if commit for your favorite open source project that reduces memory usage by 75% is in yet.

$ git log -1 tests
commit d590f2ac0635ec0053c4a7377bd929943d475297
Author: Nick Quaranto <[email protected]>
Date:   Wed Apr 1 20:38:59 2009 -0400

    Green all around, finally.

$ git branch --contains d590f2
  tests
* master

Note: if the commit is on a remote tracking branch, add the -a option.
(as MichielB comments below)

git branch -a --contains <commit>

MatrixFrog comments that it only shows which branches contain that exact commit.
If you want to know which branches contain an "equivalent" commit (i.e. which branches have cherry-picked that commit) that's git cherry:

Because git cherry compares the changeset rather than the commit id (sha1), you can use git cherry to find out if a commit you made locally has been applied <upstream> under a different commit id.
For example, this will happen if you’re feeding patches <upstream> via email rather than pushing or pulling commits directly.

           __*__*__*__*__> <upstream>
          /
fork-point
          \__+__+__-__+__+__-__+__> <head>

(Here, the commits marked '-' wouldn't show up with git cherry, meaning they are already present in <upstream>.)

Southard answered 14/9, 2009 at 4:8 Comment(19)
From the output of this command, does that mean the commit is on tests and master, or just master?Slub
tests and master - master is the current branch, therefore the asterisk.Inflexed
This only shows which branches contain that exact commit. If you want to know which branches contain an "equivalent" commit (i.e. which branches have cherry-picked that commit) that's git cherry: "Because git cherry compares the changeset rather than the commit id (sha1), you can use git cherry to find out if a commit you made locally has been applied <upstream> under a different commit id. For example, this will happen if you’re feeding patches <upstream> via email rather than pushing or pulling commits directly." kernel.org/pub/software/scm/git/docs/git-cherry.htmlJochebed
How can you do something similar but to see if a branch instead of a commit has been brought in? something like git branch --contains branchnameJegger
@jhanifen: considering a branch is just a pointer to a certain commit in the DAG of commits, you might have to list all its commits and apply this answer for each one.Southard
Add a -a parameter to also check remote branches.Vernellvernen
Is there an easy way to get this information in a shell-parseable format?Phidippides
You can also do git tag --contains <commit>. See Searching for all tags that contain a commit?.Canea
Can someone provide a working example of how to use git cherry to achieve this? Git cherry SEEMS to be geared for the reverse, finding branches not pushed upstream but that only works if you know where to start, and know the name of every branch you want to test as upstream.Achlamydeous
@Achlamydeous I would recommend making that a separate question (with a link referring back to this one).Southard
This answer did not work for me, but it did when I found out I needed to do git branch -a --contains <commit>. It was in a branch on a remote -- can you maybe update your answer?Avian
For the git cherry part @Achlamydeous asked the question here: stackoverflow.com/questions/16304574/…, alas, the question has not (yet) been answered.Allistir
@VonC: Is it possible to see exact date/time at which that hash was committed or merged or rebased in specific branch? Because I see multiple branches for single hash. So in one of the branch that code was committed and in remaining branches it was merged/rebased. How do I see exact event date/time?Chicane
@Chicane I suppose you simply can get the log for that hash: git log <sha1>Southard
Unfortunately, for a commit that is the branching point of a branch, git branch --contains will list not only the branch created from that commit, but also master and all subsequent branches. I wonder if there is a method to only find the created branch descending from the given commit.Locule
@AlexanderAmelkin I'm a couple of months late, but... not exactly. Branches are just names for the commits at their heads, after all. If you make a note of the commit after the one you want on master, you could find all branches that didn't subsequently merge from master using git branch --contains <target> --no-contains <child_on_master> (but ones that later merged from master won't show up), or you could use git rev-list --children <target> and then try git branch --contains on each child to get all branches that started there.Perfoliate
@andreee That sounds Leet. Not sure why git branch --show-current was downvoted though.Southard
is there an argument I can add to git branch --contains {hash} that will also output the dateTime that the commit was merged into respective branches?Standush
@BradKent I don't think so, not without a script. The --format= on git branch is for the branch itself, not a merge commit.Southard
H
31

You may run:

git log <SHA1>..HEAD --ancestry-path --merges

From comment of last commit in the output you may find original branch name

Example:

       c---e---g--- feature
      /         \
-a---b---d---f---h---j--- master

git log e..master --ancestry-path --merges

commit h
Merge: g f
Author: Eugen Konkov <>
Date:   Sat Oct 1 00:54:18 2016 +0300

    Merge branch 'feature' into master
Hauteur answered 29/10, 2016 at 13:53 Comment(5)
Nice! I used git log <SHA1>..master --ancestry-path --merges --oneline | tail -n1 to get this in one lineTal
If you would like to use pure git command, you could use: git log <SHA1>..master --ancestry-path --merges --oneline -1Lubricant
Note: When your commit sha is the most recent commit on the master/foo branch (HEAD)... you can't do an A..B commit range, just dont use a range like so:: git log HEAD --oneline -1 > 82c12a9 (HEAD, origin/remote-branch-name, origin/master, origin/dev, origin/HEAD, master, dev) commit message.Mutation
If this git repo is a submodule and you are trying to solve the detached HEAD problem... then you have a hard question of a preferred branch... In my previous example you could easily say that master is always preferred if it's in this list. From there it's less clear. You could try and read git branch from .gitmodules file: git config -f .gitmodules submodule.src/foo/submodule.branch. This could be a long standing fork/pr. You can cd to repo root and run git config submodule.src/foo/submodule.branch. You can also use the superprojects current git branch.Mutation
As a small aside: git config submodule.src/foo/submodule.branch Can be influenced by any variety of git configs, including a repo-local .gitconfig file. (requires running git config --local include.path ./path/to/your/.gitconfig)Mutation
J
4

The answer for git branch -r --contains <commit> works well for normal remote branches, but if the commit is only in the hidden head namespace that GitHub creates for PRs, you'll need a few more steps.

Say, if PR #42 was from deleted branch and that PR thread has the only reference to the commit on the repo, git branch -r doesn't know about PR #42 because refs like refs/pull/42/head aren't listed as a remote branch by default.

In .git/config for the [remote "origin"] section add a new line:

fetch = +refs/pull/*/head:refs/remotes/origin/pr/*

(This gist has more context.)

Then when you git fetch you'll get all the PR branches, and when you run git branch -r --contains <commit> you'll see origin/pr/42 contains the commit.

Joettajoette answered 5/11, 2020 at 2:50 Comment(1)
@Southard Thanks for improving my answer! I didn't realized I was doing git commit --add.Joettajoette

© 2022 - 2024 — McMap. All rights reserved.