我想要做的是版本检查。我希望确保代码始终保持在最低版本之上。因此,我需要一种方法来确定当前分支是否包含指定的提交。
有多种方法可以实现这个结果。第一个朴素的选项是使用 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
退出代码很好,但是如果你想要字符串true
或false
作为答案,你需要再添加一些内容,然后与bash的if
结合使用。
if [ 0 -eq $(git merge-base --is-ancestor $COMMIT_ID HEAD) ]; then echo "true"; else echo "false"; fi
git log
中提到提交 SHA 的原因是其他的,例如在提交消息中作为从另一个分支移植的结果,那么 grep
命令可能会产生误报,因此这句话不正确。请修改。 - Adam Spiersgit branch -r != git branch --list
。 - Geoff Langenderfergit branch --contains $COMMIT_ID | grep "$(git branch --show-current)"
。 - aderchox获取包含特定提交的分支列表。
# 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$'
比如说,如果你有三个本地分支叫做feature
、feature1
和feature2
,那么
$ git branch --contains <commit-id> | grep 'feature'
# output
feature
feature1
feature2
$ git branch --contains <commit-id> | grep -E '(^|\s)feature$'
# output
feature
你也可以搜索 local
和 remote
分支(使用 -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$'
<branch-name>
子字符串,则此处的 grep
也可能导致假阳性。 - Adam Spiersgrep -E '(^|\s)branchname$'
精确匹配分支名称。 - Sajib Khangit branch --all --contains <commit-id>
。 - Arthur Tacca请参考提出的重复问题以查找包含指定提交的所有分支。为了找到当前分支是否包含提交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脚本中,退出状态码为零的命令被认为是“真”,而退出状态码为非零的命令被认为是“假”。)
仅检查已签出的本地分支。
git branch --contains $COMMIT_ID
检查所有分支(包括本地和已获取的远程分支)
git branch -a --contains $COMMIT_ID
确保获取远程内容
git fetch origin
git branch --contains <commit-id>
列出包含特定提交的所有分支,包括仅远程的分支:
git branch -a --contains <commit-id>
检查提交是否位于某个分支上:
git log <branch> | grep <commit_id>
如果本地不存在分支,则在分支名称前加上前缀origin/
。-a
的评论点赞。谢谢你的建议! - Thorkil Værge是的,还有另一种选择:
git rev-list <branch name> | grep `git rev-parse <commit>`
对我来说这是最好的方法,因为它还适用于本地缓存的远程分支,例如remotes/origin/master
,在此分支上git branch --contains
将不起作用。
这涵盖了比OP问题更多的内容,仅与“当前分支”有关,但我认为问一个“任何分支”的版本很愚蠢,所以我决定在这里发布。
git branch --contains <commit-id> --points-at <target branch name>
错误:分支名称格式不正确
- bbodenmiller由于这个问题有一些不错的脚本答案,我要添加我的最爱。
这个脚本将显示最近$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
在Windows/CMD终端上的Windows机器上,您可以执行以下操作:
> git log | findstr "commit-id"
例如:
> git log | findstr "c601cd6366d"
Git checkout 命令会将你返回到当前 HEAD(当前文件)所在的分支,但它不会检出所有分支。例如,如果你执行 git checkout master 命令,代码将被检出,就好像你在 master 分支上一样,但它不会检出该分支之外的任何文件进行更改。
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
- torek--is-ancestor
的文档:检查第一个 <commit> 是否是第二个 <commit> 的祖先,如果是则以状态 0 退出,否则以状态 1 退出。
这让我觉得你代码片段中的if
方向可能是错误的,因为它对于 true 时会以0
退出,但实际上它似乎可以工作... 是文档有误还是我理解有误呢? - Remover/bin/true
最初是实现为exit 0
,而/bin/false
则是实现为exit 1
。(现代shell已经内置了这些功能)。 - torek