给定提交ID,如何确定当前分支是否包含提交?


155

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



10
有关如何查找包含指定提交的所有分支的信息,请参见建议的副本。要确定当前分支是否包含提交C,请使用“ plumbing”命令git merge-base --is-ancestor。如果C是的祖先,则当前分支包含C,因此:HEADif git merge-base --is-ancestor $hash HEAD; then echo I contain commit $hash; else echo I do not contain commit $hash; fi
torek '17

1
你好,请提交此作为一个答案,以便它可以被选择为正确答案=)

1
@Ben-我将其添加为社区Wiki答案。
Zitrax

1
@Remover:在shell脚本中,零为true,非零为false:与C约定相反。/bin/true最初实现exit 0/bin/false作为exit 1。(然后内置了现代炮弹。)
torek '19

Answers:


217

有多种方法可以实现此结果。第一个朴素的选择是使用,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答案时,您需要添加一些内容,然后与ifbash 结合使用,

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

9
那是不对的。grep如果git log由于其他原因提到提交SHA,则可能导致误报,例如,在提交消息中提到的是来自另一个分支的端口的结果。
亚当·斯皮尔斯

1
已更正(或更确切地说,添加了另一个选项)。
JiriS

3
请参阅有关问题的评论,该评论使用内置的git工具集。 stackoverflow.com/questions/43535132/...

2
我喜欢第一个选项,但是要排除亚当的反对意见,可以将选项添加--format=format:%Hgit log
PJSCopeland '18

71

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

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

1
grep如果还有其他分支包含提交且其名称也包含<branch-name>为子字符串,则此处也会导致误报。
亚当·斯皮尔斯

1
是@AdamSpiers,由grep -E '(^|\s)branchname$'
Sajib Khan

1
根据对相关问题的此注释,添加-r(“ remote”)或-a(“ all”)选项git branch以查找可能无法在本地回购克隆中复制的分支可能会很有用。
sxc731

这对我不起作用,我需要 git branch --all --contains <commit-id>
亚瑟·塔卡

7

通过@torek提取评论作为答案:

有关如何查找包含指定提交的所有分支的信息,请参见建议的副本。

要确定当前分支是否包含提交C,请使用“ plumbing”命令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脚本中,退出零的命令为“ true”,而退出非零的命令为“ false”。)


4

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

git branch --contains <commit-id>

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

git branch -a --contains <commit-id>

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

git log <branch> | grep <commit_id>

如果分支在本地不存在,则使用 origin/


投票赞成有关的评论-a。感谢您的建议!
ThorkilVærge

3

是的,另一种选择:

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

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

这不仅涵盖了OP关于“当前分支”的问题,但我对询问该问题的“任何分支”版本感到愚蠢,因此无论如何我决定在此处发布。


1
git branch --contains <commit-id> --points-at <target branch name>

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


不...error: malformed object name 'branch-name'
bbodenmiller

1
在2种情况下,您可能会收到该错误。1.给定的<分支名称>不包含给定的<commit id> 2.结帐<分支名称>不是给定的<分支名称>
DreamUth '18

0

由于此问题有一些不错的脚本答案,因此,我添加了我的收藏夹。

这将向您展示最后的$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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.