【问题标题】:Given a commit id, how to determine if current branch contains the commit?给定一个提交 id,如何确定当前分支是否包含该提交?
【发布时间】:2017-04-21 06:08:11
【问题描述】:

我正在尝试做的是版本检查。我想确保代码保持在最低版本之上。所以我需要一种方法来知道当前分支是否包含指定的提交。

【问题讨论】:

  • 查看建议的副本以了解如何查找包含指定提交的 所有 分支。要确定 current 分支是否包含提交 C,请使用“plumbing”命令 git merge-base --is-ancestor。如果 CHEAD 的祖先,则当前分支包含 C,因此:if git merge-base --is-ancestor $hash HEAD; then echo I contain commit $hash; else echo I do not contain commit $hash; fi
  • 您好,请将此作为答案提交,以便选择正确答案=)
  • @Ben - 我将其添加为社区 wiki 答案。
  • @Remover:在 shell 脚本中,零为真,非零为假:与 C 约定相反。 /bin/true 最初实现为exit 0/bin/false 实现为exit 1。 (现代的 shell 已经内置了。)

标签: git


【解决方案1】:

有多种方法可以实现此结果。第一个天真的选项是使用git log 并使用grep 搜索特定提交,但这并不总是准确的

git log | grep <commit_id>

您最好直接使用git branch 来查找包含给定COMMIT_ID 的所有分支

git branch --contains $COMMIT_ID

下一步是找出从git 1.8.1 开始可以使用的当前分支

git symbolic-ref --short HEAD

并结合在一起成为

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

但是上面的命令不会返回 true 或 false,并且有一个较短的版本,如果提交在当前分支中,则返回退出代码 0,如果不是,则返回退出代码 1

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

退出代码很好,但是如果您想要字符串 truefalse 作为答案,您需要添加更多内容,然后结合 bash 中的 if 得到

if [ 0 -eq $(git merge-base --is-ancestor $COMMIT_ID HEAD) ]; then echo "true"; else echo "false"; fi

【讨论】:

  • 不正确;如果git log 出于其他原因提及提交 SHA,grep 可能会导致误报,例如作为来自另一个分支的端口的结果,它在提交消息中被提及。
  • 请看问题的评论,它使用了内置的 git 工具集。 stackoverflow.com/questions/43535132/…
  • 我喜欢第一个选项,但为了排除亚当的反对,我会将选项--format=format:%H添加到git log
  • @AdamSpiers 如果您以编程方式执行此操作,当然可以,但对于人眼来说应该很清楚。 git log 消息被格式化,使得条目以commit 012345beef 开头,然后内容以空格为前缀,____Adds lime to coconut。因此,只有当一行开始并且只包含单词 commit 和 hash 时,它才会看起来可疑。通常你会看到类似____(cherry picked from commit 12341234) 的东西。 (注意,我必须加下划线,因为如果我使用空格,它会导致 Markdown 错误。)
  • 当在 detached head 模式 repo 中使用时,merge-base --is-ancestor 有效,而其他选项则无效。谢谢。
【解决方案2】:

获取包含特定提交的分支列表。

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

检查分支是否有特定的提交。

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

使用精确匹配搜索分支(例如feature)。

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

例如如果您有 3 个本地分支机构,分别名为 featurefeature1feature2,那么

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

# output
feature
feature1
feature2

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

# output
feature     

您还可以在localremote 分支中搜索(使用-a)或仅在remote 分支中搜索(使用-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$'

【讨论】:

  • 这里的grep 也可能导致误报,如果有其他分支包含名称也包含&lt;branch-name&gt; 作为子字符串的提交。
  • 是的@AdamSpiers,用grep -E '(^|\s)branchname$'grep -E '(^|\s)branchname$'的分支名称更新了答案
  • 根据this comment on the related question,将-r ("remote") 或-a ("all") 选项添加到git branch 以查找可能无法复制的分支会很有用在本地 repo 克隆中。
  • 这对我不起作用,我需要git branch --all --contains &lt;commit-id&gt;
【解决方案3】:

@torek 提取的评论作为答案:

查看建议的副本以了解如何查找包含指定提交的所有分支。

要确定 当前 分支是否包含提交 C,请使用“管道”命令 git merge-base --is-ancestor。如果 C 是 HEAD 的祖先,则当前分支包含 C,因此:

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

(旁注:在 shell 脚本中,退出零的命令是“真”,而退出非零的命令是“假”。)

【讨论】:

    【解决方案4】:

    是的,另一种选择:

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

    这对我来说效果最好,因为它也适用于本地缓存的远程分支,例如 remotes/origin/master,而 git branch --contains 将不起作用。

    这不仅仅涵盖了 OP 关于“当前分支”的问题,但我觉得问这个问题的“任何分支”版本很愚蠢,所以我还是决定在这里发帖。

    【讨论】:

      【解决方案5】:

      列出包含提交的本地分支:

      git branch --contains &lt;commit-id&gt;

      并列出所有包含提交的分支,包括远程分支:

      git branch -a --contains &lt;commit-id&gt;

      类似地检查提交是否在特定分支中:

      git log &lt;branch&gt; | grep &lt;commit_id&gt;

      如果本地不存在分支,则在分支名称前加上origin/

      【讨论】:

      • -a 的评论投了赞成票。谢谢你的建议!
      【解决方案6】:

      仅在已签出的本地分支机构中签入。

      git branch --contains $COMMIT_ID
      

      检查所有分支(获取的本地和远程)

      git branch -a --contains $COMMIT_ID
      

      确保获取遥控器

      git fetch origin
      

      【讨论】:

        【解决方案7】:
        git branch --contains <commit-id> --points-at <target branch name>
        

        如果提交 id 存在于该分支中,它将返回目标分支名称。否则命令会失败。

        【讨论】:

        • 不... error: malformed object name 'branch-name'
        • 您可能会在 2 种情况下遇到该错误 1. 当给定的 不包含给定的 2. checkout 不是给定的
        • 我认为它改变了,现在如果目标分支没有提交你什么都得不到,如果目标分支不存在那么你有一个错误
        【解决方案8】:

        由于这个问题有一些很好的脚本答案,所以我添加了我的最爱。

        这个会告诉你,对于最后一个 $n$br 中的提交,哪些分支包含每个:

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

        这个类似,但对分支列表的作用相同:

        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
        

        【讨论】:

          猜你喜欢
          • 2010-11-28
          • 1970-01-01
          • 2018-11-07
          • 1970-01-01
          • 2021-11-06
          • 2016-05-02
          • 1970-01-01
          • 2021-12-22
          相关资源
          最近更新 更多