I am looking for a regex to enforce a valid git branch naming convention.
Rules are
main
, master
, development
features
, tests
, bugfix
, hotfix
; followed by /
description, number, -
, _
(or nesting of it but max allowed in upto 2)release/
then version number, and it can have beta
, alpha
or rc
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.
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 patterns
main|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 stringSee 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