如何在git中查找其历史记录中包含提交的所有引用

时间:2014-07-28 10:58:06

标签: git git-branch git-tag

让我们假设你在git中有以下结构

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

现在我想查找历史记录中包含提交B的所有引用。

所以如果我能做到这样会很好

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

我看了一下git decumentation,发现git branch -a --contains <commit_id>列出了包含commit_id的所有分支。

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

我找到了命令git tag --contains 9338f2d

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

当然我可以这样做,

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

但是有一个命令可以一次打印所有引用吗?

2 个答案:

答案 0 :(得分:8)

要添加到torek的答案,git 2.7(2015年第4季度)将提供更完整版本的git for-each-ref,现在支持--contains

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

请参阅commit 4a71109commit ee2bd06commit f266c91commit 9d306b5commit 7c32834commit 35257aacommit 5afcb90,{{3} },commit d325406commit 6841104commit b2172fd,...,commit b2172fd(2015年7月7日)和commit b2172fd(2015年7月9日){{3 }}。
commit af83baf合并于Karthik Nayak (KarthikNayak),2015年10月5日)

  

来自&#34; git tag -l&#34;的一些功能和&#34; git branch -l&#34;已经成了   可用于&#34; git for-each-ref&#34;这样最终统一了   在后续工作中,可以在所有三个方面共享实施   一两个系列。

* 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  

请注意,启动Git 2.13(2017年第2季度),最终支持git for-each-ref --no-contains <SHA1>

请参阅Junio C Hamano -- gitster --commit 9958dd8commit 7505769commit 783b829commit ac3f5a3commit 1e0c3b6commit 6a33814,{{3} (2017年3月24日),commit c485b24commit eab98eecommit bf74804commit 7ac04f1(2017年3月23日)和commit 682b29fcommit 4612edc,{ {3}},commit b643827(2017年3月21日)commit 17d6c74 commit 8881d35合并于commit b084060,2017年4月11日)

答案 1 :(得分:5)

[编辑,2015年10月:现在有了VonC's new answer},但没有内置任何内容,但使用git branch -a --containsgit tag --contains应该可以帮助您您通常会发现“有趣”的参考文献。

有一种(非内置的)方法可以找到所有这些引用。每当你询问“所有引用”时,你应该看git for-each-ref。它允许您迭代所有引用或所有引用的一部分:

$ git for-each-ref
996b0fdbb4ff63bfd880b3901f054139c95611cf commit refs/heads/master
740c281d21ef5b27f6f1b942a4f2fc20f51e8c7e commit refs/remotes/origin/maint
996b0fdbb4ff63bfd880b3901f054139c95611cf commit refs/remotes/origin/master
7327a17171fc87d5f8f5c790eb1ba1d0e031482d commit refs/remotes/origin/next
[... snip]
efe35e936c6c32a7630086a84b2c3b3471ea534f tag    refs/tags/v2.0.1
b4463ead04f1801104502ea087dbb6bdd21b4ef1 tag    refs/tags/v2.0.2
3c81e95201ece182e799709c91b15a3501919d26 tag    refs/tags/v2.0.3

(在这种情况下,我在git本身的存储库上运行git for-each-refs,没有其他参数,因此它产生默认输出。)

您现在要做的就是在原始参考上运行--contains检测器。虽然没有将此作为动词的管道命令,--contains很容易在git merge-base中使用--is-ancestor表示为测试。正如git branch documentation notes--contains只是测试上面显示的refs/heads/refs/remotes/引用左侧的分支 - 尖端 - SHA-1是否是后代的指定的提交。 “是一个后代”实际上与“是它的祖先”的测试相同,参数被交换:

$ git branch --contains 996b0fd^
* master
$ git rev-parse 996b0fd^
6da748a7cebe3911448fabf9426f81c9df9ec54f

由于master996b0fd...--contains996b0fd及其第一个父6da748a...匹配,因此我们可以判断我们是否有{{1}正确的参数:

git merge-base --is-ancestor

请注意$ git merge-base --is-ancestor 6da748a 996b0fd && echo ok ok 被认为是其自身的祖先:

996b0fd

所以你需要做的就是将$ git merge-base --is-ancestor 996b0fd 996b0fd && echo ok ok 和一个运行git for-each-ref的shell命令或循环串在一起。