I was working on a project that wanted commit messages in the following formats
feat(feature-name): message text here (AEROGEAR-Number) fix(feature-name): etc... docs(feature-name): etc... breaking(feature-name): etc...
This was a pain to enforce and check manually so we decided to automate the check for this. Firstly I wrote a script to check the existing branch commits and see if they match the format
#!/bin/bash commit_message_check (){ # Get the current branch and apply it to a variable currentbranch=`git branch | grep \* | cut -d ' ' -f2` # Gets the commits for the current branch and outputs to file git log $currentbranch --pretty=format:"%H" --not master > shafile.txt # loops through the file an gets the message for i in `cat ./shafile.txt`; do # gets the git commit message based on the sha gitmessage=`git log --format=%B -n 1 "$i"` ####################### TEST STRINGS comment out line 13 to use ######################################### #gitmessage="feat sdasdsadsaas (AEROGEAR-asdsada)" #gitmessage="feat(some txt): some txt (AEROGEAR-****)" #gitmessage="docs(some txt): some txt (AEROGEAR-1234)" #gitmessage="fix(some txt): some txt (AEROGEAR-5678)" ######################################################################################################### # Checks gitmessage for string feat, fix, docs and breaking, if the messagecheck var is empty if fails messagecheck=`echo $gitmessage | grep -w "feat\|fix\|docs\|breaking"` if [ -z "$messagecheck" ] then echo "Your commit message must begin with one of the following" echo " feat(feature-name)" echo " fix(fix-name)" echo " docs(docs-change)" echo " " fi # check the gitmessage for the Jira number messagecheck=`echo $gitmessage | grep "(AEROGEAR-"` if [ -z "$messagecheck" ] then echo "Your commit message must end with the following" echo " (AEROGEAR-****)" echo "Where **** is the Jira number" echo " " fi messagecheck=`echo $gitmessage | grep ": "` if [ -z "$messagecheck" ] then echo "Your commit message has a formatting error please take note of special characters '():' position and use in the example below" echo " type(some txt): some txt (AEROGEAR-****)" echo "Where 'type' is fix, feat, docs or breaking and **** is the Jira number" echo " " fi # All checks run at the same time by pipeing from one grep to another messagecheck=`echo $gitmessage | grep -w "feat\|fix\|docs\|breaking" | grep "(AEROGEAR-" | grep ": "` # check to see if the messagecheck var is empty if [ -z "$messagecheck" ] then echo "The commit message with sha: '$i' failed " echo "Please review the following :" echo " " echo $gitmessage echo " " rm shafile.txt >/dev/null 2>&1 set -o errexit else echo "$messagecheck" echo "'$i' commit message passed" fi done rm shafile.txt >/dev/null 2>&1 } # Calling the function commit_message_check
I copied the script to a script directory of the root of the project and was initially using it with Circle ci to check the commit during a build.
steps: - checkout - run: ./scripts/commit-filter-check.sh
It was decided that a local check would more useful, we then decided to use githooks to run the script. There is a .git/hook directory in every git project with sample git hooks.
Remove the .sample and the hook script becomes live in this case I used the commit-msg git hook and use it to run my script. The hook is triggered by a failure with an exit 1
#!/bin/sh # Run the script and get the return code if successful of if fails ./scripts/commit-filter-check.sh && rc=$? || rc=$? echo return code : $rc if $rc == 1 then echo "Script return code 1 so commit failed" exit 1 else echo "No error returned so commit successful" fi
Only issue was the .git directory never gets seen by git commit. So I needed a way to push my changes and allow others to use them. Moving commit-msg file to a .githook directory allows it to be committed. You can then add a line to the setup script of the project to create a sym link to the local .git/hooks directory
ln -sf $$PWD/.githooks/* $$PWD/.git/hooks/
Now every commit message is checked and will fail if it doesn’t match the format
Top comments (0)