3

I am using shell to write a git hook file, to check my commit message before commit. I an a total beginner, this is what I have tried:

My commit-msg hook file is like below:

#!/bin/sh
msg=`head -n 1 $1`


if echo $msg | egrep -qv '(Android-\d{3,4}.{20,})'; then
  echo "[Message Format] Your message is not formatted correctly. Correct message format\n 
    #Ticket Number - Minimum 20 or more Character \n 
    like #Android-123 Bug fixed for login issue"
  exit 1;
fi

So whenever I make a commit message like this:

git commit -m " #Android-123 I pretty sure this is more than 20 character,but it still failed to commit"

So I pretty sure my commit message is more than 20 character, and the ticket number, but every time I commit it still get the error I set.

I think my logic problem is that I should use if not echo $msg | egrep -qv '(Android-\d{3,4}.{20,})', so I tried:

 if ! [[echo $msg | egrep -qv '(Android-\d{3,4}.{20,})']] ; 
 then....

But this give me this error: .git/hooks/commit-msg: line 5: syntax error near unexpected token !'

Question:

  1. What I going wrong that cause failed to commit, even though I make a right commit message?

  2. How can I fix it?

3
  • i tried(in commit-msg file) exactly this : if echo " #Android-123 I pretty sure this is more than 20 character,but it still failed to commit" || egrep -qv '(Android-\d{3,4}.{20,})' ; then ,then git commit again,it still give me the same error
    – ken
    Apr 12 '20 at 13:31
  • [Message Format] Your message is not formatted correctly. Correct message format\n #Ticket Number - Minimum 20 or more Character \n like #Android-123 Bug fixed for login issue exactly this error that I set myself
    – ken
    Apr 12 '20 at 13:32
  • Note that [[ ... ]] syntax 1) is not supported in the plain POSIX shell (it's a bashism; see this SO question), 2) doesn't do what you thought it did. To group multiple commands you should use { echo hello; echo hi; } instead, or run them in a subshell like ( echo hello; echo hi ).
    – Ruslan
    Apr 13 '20 at 10:15
6

Your regular expression uses PCRE syntax like \d, but grep -E (that's what your egrep is, but use grep -E instead, egrep is being deprecated) doesn't understand that. Also, you don't need the parentheses there, you aren't actually capturing anything. If you have GNU grep, you can use grep -P instead:

grep -Pqv 'Android-\d{3,4}.{20,}'

If not, you will have to replace \d with [0-9]:

grep -Eqv 'Android-[0-9]{3,4}.{20,}' 

However, you don't need (or want) to only take the first line of the file, you can just grep the whole file directly. You also don't need to reverse the match (-v), that just complicates things. Here's a simpler, working version of your script, using if ! to negate the condition:

#!/bin/sh
if ! grep -E 'Android-[0-9]{3,4}.{20,}' "$1"; then
  printf "[Message Format] Your message is not formatted correctly. Correct message format: 
    #Ticket Number - Minimum 20 or more Character 
    like #Android-123 Bug fixed for login issue\n"
  exit 1;
fi
7
  • Note that to match on 0123456789, the syntax is [[:digit:]] or [0123456789]; [0-9] matches on a lot more characters in some locales on some systems. Apr 13 '20 at 7:05
  • Your approach wouldn't flag as incorrect a message whose second line matches the pattern, but not the first. Apr 13 '20 at 7:06
  • The error message should probably go on stderr. Apr 13 '20 at 7:07
  • With the GNU or busybox implementations of grep, you'd need a -- after -E or better use redirections instead of passing the filename as argument or it wouldn't work for file names that start with -. Apr 13 '20 at 7:08
  • Note that POSIX doesn't forbid grep implementations to support \d as meaning decimal digit, as it leaves the behaviour unspecified if one uses it in a regex (outside of bracket expressions). Some implementations like ast-open's grep do support it. GNU grep doesn't support it yet. Apr 13 '20 at 7:16
0

Here, I'd do:

#! /bin/sh -
file="${1?No file specified}"

die() {
  printf >&2 '%s\n' "$@"
  exit 1
}

awk '
  BEGIN {ret = !ok}
  /^#Android-[[:digit:]]{3,4}[^[:digit:]].{19}/ {ret = ok}
  {exit}
  END {exit ret}' < "$file" || die \
    '[Message Format] Your message is not formatted correctly. Correct message format:' \
    '#Ticket Number - Minimum 20 or more Character' \
    'like #Android-123 Bug fixed for login issue'

(remove the ^ if you don't require the ticket number to be at the start of the line).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.