lint-commit.sh 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. #!/usr/bin/env bash
  2. # the file containing the commit message is passed as the first argument
  3. commit_file="$1"
  4. commit_message=$(cat "$commit_file")
  5. error() {
  6. echo -e "\033[0;31m$1:\033[0m"
  7. echo "$commit_message"
  8. exit 1
  9. }
  10. # fail if the commit message contains windows style line breaks (carriage returns)
  11. if grep -q -U $'\x0D' "$commit_file"; then
  12. error "Commit message contains CRLF line breaks (only unix-style LF linebreaks are allowed)"
  13. fi
  14. line_number=0
  15. while read -r line; do
  16. # break on git cut line, used by git commit --verbose
  17. if [[ "$line" == "# ------------------------ >8 ------------------------" ]]; then
  18. break
  19. fi
  20. # ignore comment lines
  21. [[ "$line" =~ ^#.* ]] && continue
  22. # ignore overlong 'fixup!' commit descriptions
  23. [[ "$line" =~ ^fixup!\ .* ]] && continue
  24. ((line_number += 1))
  25. line_length=${#line}
  26. if [[ $line_number -eq 2 ]] && [[ $line_length -ne 0 ]]; then
  27. error "Empty line between commit title and body is missing"
  28. fi
  29. merge_commit_pattern="^Merge branch"
  30. if [[ $line_number -eq 1 ]] && (echo "$line" | grep -E -q "$merge_commit_pattern"); then
  31. error "Commit is a git merge commit, use the rebase command instead"
  32. fi
  33. category_pattern='^(Revert "|\S+: )'
  34. if [[ $line_number -eq 1 ]] && (echo "$line" | grep -E -v -q "$category_pattern"); then
  35. error "Missing category in commit title (if this is a fix up of a previous commit, it should be squashed)"
  36. fi
  37. title_case_pattern="^\S.*?: [A-Z0-9]"
  38. if [[ $line_number -eq 1 ]] && (echo "$line" | grep -E -v -q "$title_case_pattern"); then
  39. error "First word of commit after the subsystem is not capitalized"
  40. fi
  41. if [[ $line_number -eq 1 ]] && [[ "$line" =~ \.$ ]]; then
  42. error "Commit title ends in a period"
  43. fi
  44. url_pattern="([a-z]+:\/\/)?(([a-zA-Z0-9_]|-)+\.)+[a-z]{2,}(:\d+)?([a-zA-Z_0-9@:%\+.~\?&\/=]|-)+"
  45. if [[ $line_length -gt 72 ]] && (echo "$line" | grep -E -v -q "$url_pattern"); then
  46. error "Commit message lines are too long (maximum allowed is 72 characters)"
  47. fi
  48. if [[ "$line" == "Signed-off-by: "* ]]; then
  49. error "Commit body contains a Signed-off-by tag"
  50. fi
  51. done <"$commit_file"
  52. exit 0