I am trying to write a server side hook to check the pattern of the commit messages using bash.
I want to reject the push if any commit not followed the specific Commit-Message
format.
For example,
Commit didn't follow the specific commit message format:-
$ git log -1
commit 98yad93c64d06f8cd49a8905b2b28f7509c87aef (HEAD -> master)
Author: Admin <[email protected]>
Date: Mon Jun 20 16:33:00 2022 0530
Updated java file.
For the above case, script need to reject to follow the hard-coded commit message format.
For the below commit message case, push should allow.
$ git log -1
commit c4d4a5c1d83ca1327c1b7e57f60eabe161d467b3 (HEAD -> master)
Author: Admin <[email protected]>
Date: Mon Jun 20 16:33:00 2022 0530
1. Project Name: Java App
2. Jira ID: 12345
3. Testing Status: Completed
4. Employee Name: Robby Nithin
5. Office: Norway
I have below script to enforce the hard-coded commit message policy.
#!/bin/bash
echo $@
COMMIT_MSG="Project Name:","Jira ID:","Testing Status:","Employee Name:","Office:"
# Hard-coded template
FORMAT=$(cat /opt/template)
if echo "$FORMAT" | grep -qE "$COMMIT_MSG" ;then
echo "Commit message validation is success!"
exit 0
else
echo "Validation failed!"
exit 1
fi
Script is getting success even the commit not followed the commit message format.
Need help to enforce a specific(Hard-coded) commit message format. Thanks in advance.
CodePudding user response:
You haven't mentioned how your are running the script, so I'll assume you're talking about a local git repo and are not asking about a particular vendor's hooks. In that case, you could put something like the following in .git/hooks/commit-msg
:
#!/bin/sh
i=1
for label in 'Project Name' 'Jira ID' 'Testing Status' 'Employee Name' Office; do
if ! grep -q "^ $((i )). $label:" $1; then
cat <<- EOF
Proposed commit message does not satisfy this repository's exacting standards
It must match the template:
1. Project Name: xxx
2. Jira ID: xxx
3. Testing Status: xxx
4. Employee Name: xxx
5. Office: xxx
The proposed commit message does not contain the label: $label" >&2
EOF
exit 1
fi
done
Make sure the hook script is executable. Also note that the above mixes hard tabs and spaces to take advantage of the <<-
heredoc syntax in the error message. The script will be called with the file name of the proposed commit message as its sole argument. This particular script is IMO far too finicky, and you will probably want to verify the ordering of the labels and be more flexible with whitespace, but this should get you started.
As with most hooks, exiting non-zero will cause the commit to fail. But this script can easily be by-passed with the --no-verify
option to git commit
. YMMV
Running multiple grep
s against the file is ... icky, but for simplicity I'll leave that example here. But you may prefer to use something like:
#!/bin/sh
if ! awk '
NR==3 && ! /^ 1. Project Name:/{exit 1}
NR==4 && ! /^ 2. Jira ID:/{exit 1}
NR==5 && ! /^ 3. Testing Status:/{exit 1}
NR==6 && ! /^ 4. Employee Name:/{exit 1}
NR==7 && ! /^ 5. Office:/{exit 1}
END { exit NR < 7}
' "$1"; then
sed -e 's/<t>/ /' <<- EOF
Proposed commit message does not satisfy this repository's exacting standards
It must match the template: (starting in line 3, and with correct leading whitespace)
<t>1. Project Name: xxx
<t>2. Jira ID: xxx
<t>3. Testing Status: xxx
<t>4. Employee Name: xxx
<t>5. Office: xxx
EOF
exit 1
fi >&2