如何检查有效的 Git 分支名称?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12093748/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I check for valid Git branch names?
提问by Alex Chamberlain
I'm developing a git
post-receive
hook in Python. Data is supplied on stdin
with lines similar to
我正在git
post-receive
用 Python开发一个钩子。数据提供的stdin
行类似于
ef4d4037f8568e386629457d4d960915a85da2ae 61a4033ccf9159ae69f951f709d9c987d3c9f580 refs/heads/master
The first hash is the old-ref, the second the new-ref and the third column is the reference being updated.
第一个哈希是旧引用,第二个是新引用,第三列是正在更新的引用。
I want to split this into 3 variables, whilst also validating input. How do I validate the branch name?
我想将其拆分为 3 个变量,同时还要验证输入。如何验证分支名称?
I am currently using the following regular expression
我目前正在使用以下正则表达式
^([0-9a-f]{40}) ([0-9a-f]{40}) refs/heads/([0-9a-zA-Z]+)$
This doesn't accept all possible branch names, as set out by man git-check-ref-format. For example, it excludes a branch by the name of build-master
, which is valid.
这不接受所有可能的分支名称,如man git-check-ref-format 所述。例如,它排除了名称为 的分支build-master
,这是有效的。
Bonus marks
加分
I actually want to exclude any branch that starts with "build-". Can this be done in the same regex?
我实际上想排除任何以“build-”开头的分支。这可以在同一个正则表达式中完成吗?
Tests
测试
Given the great answers below, I wrote some tests, which can be found at https://github.com/alexchamberlain/githooks/blob/master/miscellaneous/git-branch-re-test.py.
鉴于下面的好答案,我写了一些测试,可以在https://github.com/alexchamberlain/githooks/blob/master/miscellaneous/git-branch-re-test.py找到 。
Status: All the regexes below are failing to compile. This could indicate there's a problem with my script or incompatible syntaxes.
状态:以下所有正则表达式都无法编译。这可能表明我的脚本存在问题或语法不兼容。
回答by Joey
Let's dissect the various rules and build regex parts from them:
让我们剖析各种规则并从中构建正则表达式部分:
They can include slash
/
for hierarchical (directory) grouping, but no slash-separated component can begin with a dot.
or end with the sequence.lock
.# must not contain /. (?!.*/\.) # must not end with .lock (?<!\.lock)$
They must contain at least one
/
. This enforces the presence of a category like heads/, tags/ etc. but the actual names are not restricted. If the--allow-onelevel
option is used, this rule is waived..+/.+ # may get more precise later
They cannot have two consecutive dots
..
anywhere.(?!.*\.\.)
They cannot have ASCII control characters (i.e. bytes whose values are lower than
\040
, or\177 DEL
), space, tilde~
, caret^
, or colon:
anywhere.[^
0-77 ~^:]+ # pattern for allowed characters[^
0-77 ~^:?*[]+ # new pattern for allowed characters^(?!/) (?<!/)$ (?!.*//)
They cannot have question-mark
?
, asterisk*
, or open bracket[
anywhere. See the--refspec-pattern
option below for an exception to this rule.(?<!\.)$
They cannot begin or end with a slash
/
or contain multiple consecutive slashes (see the--normalize
option below for an exception to this rule)(?!.*@\{)
They cannot end with a dot
.
.(?!@$)
They cannot contain a sequence
@{
.(?!.*\)
They cannot be the single character
@
.# must not contain /. (?!.*/\.) # must not end with .lock (?<!\.lock)$
They cannot contain a
\
..+/.+ # may get more precise later
它们可以包含
/
用于分层(目录)分组的斜杠,但斜杠分隔的组件不能以点开头.
或以序列 结尾.lock
。(?!.*\.\.)
它们必须至少包含一个
/
. 这会强制存在像 head/、tags/ 等类别,但实际名称不受限制。如果使用该--allow-onelevel
选项,则放弃此规则。[^
0-77 ~^:]+ # pattern for allowed characters[^
0-77 ~^:?*[]+ # new pattern for allowed characters^(?!/) (?<!/)$ (?!.*//)
他们不能在
..
任何地方有两个连续的点。(?<!\.)$
它们在任何地方都不能有 ASCII 控制字符(即值小于
\040
, 或 的字节\177 DEL
)、空格、波浪号~
、插入符号^
或冒号:
。(?!.*@\{)
它们不能在任何地方有问号
?
、星号*
或左括号[
。有关--refspec-pattern
此规则的例外情况,请参阅下面的选项。(?!@$)
它们不能以斜杠开头或结尾,也不能
/
包含多个连续的斜杠(请参阅--normalize
下面的选项以了解此规则的例外情况)(?!.*\)
它们不能以点结尾
.
。^(?!.*/\.)(?!.*\.\.)(?!/)(?!.*//)(?!.*@\{)(?!@$)(?!.*\)[^
0-77 ~^:?*[]+/[^^(?!build-)(?!.*/\.)(?!.*\.\.)(?!/)(?!.*//)(?!.*@\{)(?!@$)(?!.*\)[^
0-77 ~^:?*[]+/[^^(?!@$|build-|/|.*([/.]\.|//|@\{|\))[^
0-77 ~^:?*[]+/[^# RegExp rules based on git-check-ref-format my $valid_ref_name = qr% ^ (?! # begins with /| # (from #6) cannot begin with / # contains .*(?: [/.]\.| # (from #1,3) cannot contain /. or .. //| # (from #6) cannot contain multiple consecutive slashes @\{| # (from #8) cannot contain a sequence @{ \ # (from #9) cannot contain a \ ) ) # (from #2) (waiving this rule; too strict) [^07 ~^:?*[]+ # (from #4-5) valid character rules # ends with (?<!\.lock) # (from #1) cannot end with .lock (?<![/.]) # (from #6-7) cannot end with / or . $ %x; foreach my $branch (qw( master .master build/master ref/HEAD/blah /HEAD/blah HEAD/blah/ master.lock head/@{block} master. build//master build\master build\master ), 'master blaster', ) { print "$branch --> ".($branch =~ $valid_ref_name)."\n"; }
0-77 ~^:?*[]+(?<!\.lock|[/.])$refs/heads/(?!.)(?!build-)((?!\.\.)(?!@{)[^\cA-\cZ ~^:?*[\])+))(?<!\.)(?<!\.lock)
0-77 ~^:?*[]+(?<!\.lock)(?<!/)(?<!\.)$(?!.)((?!\.\.)(?!@{)[^\cA-\cZ ~^:?*[\])+))(/(?!.)((?!\.\.)(?!@{)[^\cA-\cZ ~^:?*[\])+)))*?/(?!.)(?!build-)((?!\.\.)(?!@{)[^\cA-\cZ ~^:?*[\])+))(?<!\.)(?<!\.lock)
0-77 ~^:?*[]+(?<!\.lock)(?<!/)(?<!\.)$^(?!/|.*([/.]\.|//|@\{|\\))[^07 ~^:?*\[]+(?<!\.lock|[/.])$
它们不能包含序列
##代码##@{
。它们不能是单个字符
##代码##@
。它们不能包含
##代码##\
.
Piecing it all together we arrive at the following monstrosity:
拼凑起来,我们得出了以下怪物:
##代码##And if you want to exclude those that start with build-
then just add another lookahead:
如果你想排除那些以开头的,build-
那么只需添加另一个前瞻:
This can be optimized a bit as well by conflating a few things that look for common patterns:
这也可以通过合并一些寻找常见模式的东西来优化:
##代码##回答by Brendan Byrd
There's no need to write monstrosities in Perl. Just use /x:
没有必要在 Perl 中编写怪物。只需使用 /x:
##代码##Joey++ for some of the code, though I made some corrections.
Joey++ 的一些代码,虽然我做了一些更正。
回答by murgatroid99
Taking the rules directly from the linked page, the following regular expression should match only valid branch names in refs/heads
not starting with "build-":
直接从链接页面获取规则,以下正则表达式应仅匹配refs/heads
不以“build-”开头的有效分支名称:
This starts with refs/heads
as yours does.
这从refs/heads
你的开始。
Then (?!build-)
checks that the next 6 characters are not build-
and (?!.)
checks that the branch does not start with a .
.
然后(?!build-)
检查接下来的 6 个字符是否不是,build-
并(?!.)
检查分支是否不以 开头.
。
The entire group (((?!\.\.)(?!@{)[^\cA-\cZ ~^:?*[\\])+)
matches the branch name.
整个组(((?!\.\.)(?!@{)[^\cA-\cZ ~^:?*[\\])+)
匹配分支名称。
(?!\.\.)
checks that there are no instances of two periods in a row, and (?!@{)
checks that the branch does not contain @{
.
(?!\.\.)
检查在一行中没有两个句点的实例,并(?!@{)
检查分支是否不包含@{
.
Then [^\cA-\cZ ~^:?*[\\]
matches any of the allowed characters by excluding control characters \cA-\cZ
and all of the rest of the characters that are specifically forbidden.
然后[^\cA-\cZ ~^:?*[\\]
通过排除控制字符\cA-\cZ
和所有其他特别禁止的字符来匹配任何允许的字符。
Finally, (?<!\.)
makes sure that the branch name did not end with a period and (?<!.lock)
checks that it did not end with .\lock
.
最后,(?<!\.)
确保分支名称不以句点结尾并(?<!.lock)
检查它是否不以.\lock
.
This can be extended to similarly match valid branch names in arbitrary folders, you can use
这可以扩展为类似地匹配任意文件夹中的有效分支名称,您可以使用
##代码##This applies basically the same rules to each piece of the branch name, but only checks that the last one does not start with build-
这对分支名称的每一部分应用基本相同的规则,但只检查最后一个不以 build-
回答by zanbaldwin
For anyone coming to this question looking for the PCRE regular expression to match a valid Git branch name, it is the following:
对于任何来到这个问题寻找 PCRE 正则表达式以匹配有效 Git 分支名称的人来说,它是以下内容:
##代码##This is an amended version of the regular expression written by Joey. In this version, however, an oblique is not required (it is for matching branchName
rather than refs/heads/branchName
).
这是Joey编写的正则表达式的修正版本。然而,在这个版本中,不需要倾斜(它用于匹配branchName
而不是refs/heads/branchName
)。
Please refer to his correct answer to this question.
He provides a full breakdown of each part of the regex, and how it relates to each requirement specified on the git-check-ref-format(1)
manual pages.
请参考他对这个问题的正确回答。他提供了正则表达式每个部分的完整细分,以及它与git-check-ref-format(1)
手册页上指定的每个要求的关系。