I am looking for a regex to enforce a valid git branch naming convention.
Rules are
- A branch name can only be
main
,master
,development
- A branch name can start with
features
,tests
,bugfix
,hotfix
; followed by/
description, number,-
,_
(or nesting of it but max allowed in upto 2) - A branch name can start with
release/
then version number, and it can havebeta
,alpha
orrc
tag with or without number.
Here are the example of few valid name
main
bugfix/user-list
bugfix/user_list
bugfix/123
bugfix/123/account-update
bugfix/123/account_update
bugfix/User_crud/account-update
bugfix/User_crud/account_update
tests/api
tests/123
tests/123/hello
release/1.0.1
release/1.0.1-beta1
release/1.0.1-beta
release/1.0.1-rc3
I had written this regex (https://regex101.com/r/n0CAuM/1), but it is not matching all the above example
^(development|master|main|(((features|tests|bugfix|hotfix)\/(([0-9A-Za-z-_] )|((\/[0-9A-Za-z-_] )))|release\/(?:(\d )\.)?(?:(\d )\.)?(\d )?(-(alpha|beta|rc)[0-9]))))
Also note as I will be using the regex in a bash script which only support POSIX regex engine.
CodePudding user response:
You can put the alternations for all 3 parts in their own part of the pattern.
For the groupings, instead of a non capture group you can use a capture group, and for the digits use [0-9]
instead of \d
.
If there is maximum of 1-2 parts, you can use a quantifier {1,2}
You could write the pattern as:
^(main|development|master|(features|tests|(bug|hot)fix)(\/[a-zA-Z0-9] ([-_][a-zA-Z0-9] )*){1,2}|release\/[0-9] (\.[0-9] )*(-(alpha|beta|rc)[0-9]*)?)$
^
Start of string(
Start outer grouping to match 1 of the 3 allowed patternsmain|development|master
Match 1 of the single named alternatives|
Or(features|tests|(bug|hot)fix)(\/[a-zA-Z0-9] ([-_][a-zA-Z0-9] )*){1,2}
Match a variation for features, tests and fixes a following with/
and not starting with-
or_
and repeat that part 1 or 2 times|
Orrelease\/[0-9] (\.[0-9] )*(-(alpha|beta|rc)[0-9]*)?
Match a variation for the release branch with optional alpha, beta or rc
)
Close outer grouping$
End of string
See a regex demo and a Bash demo.
Example
array=(development main bugfix/user-list bugfix/user_list bugfix/123 bugfix/123/account-update bugfix/123/account_update bugfix/User_crud/account-update bugfix/User_crud/account_update tests/api tests/123 tests/123/hello release/1.0.1 release/1.0.1-beta1 release/1.0.1-beta release/1.0.1-rc3 bugfix/ bugfix/- bugfix/_ bugfix/-name bugfix/_name bugfix/-/name bugfix/-/- bugfix/-/_ release/v1.0.1)
for i in "${array[@]}"
do
if [[ "$i" =~ ^(main|development|master|(features|tests|(bug|hot)fix)(/[a-zA-Z0-9] ([-_][a-zA-Z0-9] )*){1,2}|release/[0-9] (\.[0-9] )*(-(alpha|beta|rc)[0-9]*)?)$ ]]; then
echo "Match: "$i
else
echo "No match: "$i
fi
done
Output
Match: development
Match: main
Match: bugfix/user-list
Match: bugfix/user_list
Match: bugfix/123
Match: bugfix/123/account-update
Match: bugfix/123/account_update
Match: bugfix/User_crud/account-update
Match: bugfix/User_crud/account_update
Match: tests/api
Match: tests/123
Match: tests/123/hello
Match: release/1.0.1
Match: release/1.0.1-beta1
Match: release/1.0.1-beta
Match: release/1.0.1-rc3
No match: bugfix/
No match: bugfix/-
No match: bugfix/_
No match: bugfix/-name
No match: bugfix/_name
No match: bugfix/-/name
No match: bugfix/-/-
No match: bugfix/-/_
No match: release/v1.0.1