Search code examples
gitgit-branchgit-tag

How to find all refs that contain a commit in their history in git


Lets assume you have the following structure in git

    A <-- refs/heads/somebranch
    |
    B 
    | \
    C  D <-- refs/tags/TAG1
    |  |
    E  F
    |  | \
    G  H  I <-- refs/heads/branch1                
    |
    J <-- refs/heads/master

Now I want to find all refs that contain commit B in their history.

So it would be nice if I could do

$ git refs --contains B
refs/tags/TAG1
refs/heads/branch1
refs/heads/master

I took a look at the git decumentation and found git branch -a --contains <commit_id> which lists all branches that contain a commit_id.

$ git branch -a --contains 4af9822
  master
  remotes/origin/someBranch
  ...

and I found the command git tag --contains 9338f2d

$ git tag --contains 9338f2d
  someTag
  anotherTag
  ...

Of course I can do something like this,

$ git branch -a --contains 4af9822 && git tag --contains 9338f2d

but is there a command that prints all refs at once?


Solution

  • To add to torek's answer, git 2.7 (Q4 2015) will offer a more complete version of git for-each-ref, which now support the --contains

    git for-each-ref --contains <SHA1>
    

    See commit 4a71109, commit ee2bd06, commit f266c91, commit 9d306b5, commit 7c32834, commit 35257aa, commit 5afcb90, commit d325406, commit 6841104, commit b2172fd, commit b2172fd, ..., commit b2172fd (07 Jul 2015), and commit af83baf (09 Jul 2015) by Karthik Nayak (KarthikNayak).
    (Merged by Junio C Hamano -- gitster -- in commit 9958dd8, 05 Oct 2015)

    Some features from "git tag -l" and "git branch -l" have been made available to "git for-each-ref" so that eventually the unified implementation can be shared across all three, in a follow-up series or two.

    * kn/for-each-tag-branch:
      for-each-ref: add '--contains' option
      ref-filter: implement '--contains' option
      parse-options.h: add macros for '--contains' option
      parse-option: rename parse_opt_with_commit()
      for-each-ref: add '--merged' and '--no-merged' options
      ref-filter: implement '--merged' and '--no-merged' options
      ref-filter: add parse_opt_merge_filter()
      for-each-ref: add '--points-at' option
      ref-filter: implement '--points-at' option  
    

    Note that starting Git 2.13 (Q2 2017), git for-each-ref --no-contains <SHA1> is finally supported!

    See commit 7505769, commit 783b829, commit ac3f5a3, commit 1e0c3b6, commit 6a33814, commit c485b24, commit eab98ee, commit bf74804 (24 Mar 2017), commit 7ac04f1, commit 682b29f, commit 4612edc, commit b643827 (23 Mar 2017), and commit 17d6c74, commit 8881d35, commit b084060, commit 0488792 (21 Mar 2017) by Ævar Arnfjörð Bjarmason (avar).
    (Merged by Junio C Hamano -- gitster -- in commit d1d3d46, 11 Apr 2017)