Bird
Raised Fist0
Gitdevops~10 mins

commit-msg hook for message validation in Git - Step-by-Step Execution

Choose your learning style10 modes available
Process Flow - commit-msg hook for message validation
Start commit-msg hook
↓
Read commit message file
↓
Validate message format
↓
Allow commit
↓
Show error message
↓
Exit hook
The commit-msg hook runs automatically during commit. It reads the commit message, checks if it matches rules, then allows or rejects the commit.
Execution Sample
Git
#!/bin/sh
MSG_FILE=$1
MSG=$(cat "$MSG_FILE")

if echo "$MSG" | grep -qE '^JIRA-[0-9]+: .{10,}'
then
  exit 0
else
  echo "Error: Commit message must start with JIRA-<number>: and be at least 10 chars"
  exit 1
fi
This hook script checks if the commit message starts with 'JIRA-' followed by a number and a colon, then has at least 10 characters.
Process Table
StepActionCommit Message ContentValidation ResultHook Exit CodeOutput
1Read commit message fileJIRA-123: Fix bug in loginN/AN/A
2Check pattern '^JIRA-[0-9]+: .{10,}'JIRA-123: Fix bug in loginMatches patternN/A
3Exit hookN/AValid message0
4Commit allowedN/AN/AN/ACommit proceeds
5Read commit message fileFix login bugN/AN/A
6Check pattern '^JIRA-[0-9]+: .{10,}'Fix login bugDoes not matchN/A
7Print error messageN/AInvalid messageN/AError: Commit message must start with JIRA-<number>: and be at least 10 chars
8Exit hookN/AInvalid message1
9Commit rejectedN/AN/AN/ACommit aborted
💡 Hook exits with 0 if message valid, 1 if invalid, controlling commit success
Status Tracker
VariableStartAfter Step 1After Step 2After Step 6Final
MSG_FILEunset'.git/COMMIT_EDITMSG''.git/COMMIT_EDITMSG''.git/COMMIT_EDITMSG''.git/COMMIT_EDITMSG'
MSGunset'JIRA-123: Fix bug in login' or 'Fix login bug''JIRA-123: Fix bug in login' or 'Fix login bug''Fix login bug''Fix login bug' or 'JIRA-123: Fix bug in login'
Validation ResultunsetN/AMatches pattern or Does not matchDoes not matchMatches pattern or Does not match
Exit CodeunsetN/A0 or 110 or 1
Key Moments - 3 Insights
Why does the commit get rejected even if the message looks descriptive?
The hook requires the message to start with 'JIRA-' followed by a number and a colon, then at least 10 characters. Messages without this prefix fail validation as shown in rows 6-9 of the execution table.
What does exit code 0 or 1 mean in the hook?
Exit code 0 means the commit message passed validation and the commit proceeds (rows 3-4). Exit code 1 means validation failed and the commit is aborted (rows 8-9).
How does the hook read the commit message to validate it?
The hook reads the commit message file passed as the first argument ($1) and stores its content in MSG variable (row 1). It then applies the pattern check on MSG.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, what is the exit code when the commit message is 'JIRA-123: Fix bug in login'?
A2
B1
C0
DNo exit code
💡 Hint
Check row 3 in the execution table where the message matches the pattern and exit code is set.
At which step does the hook print an error message for an invalid commit message?
AStep 7
BStep 4
CStep 2
DStep 1
💡 Hint
Look for the step where output shows the error message in the execution table.
If the commit message was 'JIRA-45: Add tests', how would the validation result change?
AIt would match the pattern and pass
BIt would fail because message is too short
CIt would fail because no JIRA number
DIt would pass without checks
💡 Hint
Refer to the regex pattern requiring at least 10 characters after the prefix, see execution table row 2.
Concept Snapshot
commit-msg hook syntax:
#!/bin/sh
MSG_FILE=$1
MSG=$(cat "$MSG_FILE")

Validation:
Use regex to check MSG format
Exit 0 to allow commit
Exit 1 to reject commit

Purpose: enforce commit message rules automatically
Full Transcript
The commit-msg hook runs automatically when you make a git commit. It reads the commit message from a file passed as an argument. Then it checks if the message matches a pattern: it must start with 'JIRA-' followed by a number and a colon, and have at least 10 characters. If the message matches, the hook exits with code 0, allowing the commit. If not, it prints an error message and exits with code 1, stopping the commit. This helps keep commit messages consistent and meaningful.

Practice

(1/5)
1. What is the main purpose of a commit-msg hook in Git?
easy
A. To check and validate the commit message before the commit is saved
B. To automatically push commits to the remote repository
C. To merge branches after a commit
D. To delete old commits from history

Solution

  1. Step 1: Understand the role of Git hooks

    Git hooks are scripts that run at specific points in Git's workflow to automate tasks or checks.
  2. Step 2: Identify the function of the commit-msg hook

    The commit-msg hook runs after a commit message is entered but before the commit is finalized, allowing validation of the message.
  3. Final Answer:

    To check and validate the commit message before the commit is saved -> Option A
  4. Quick Check:

    commit-msg hook = validate commit message [OK]
Hint: commit-msg hook validates commit messages before saving [OK]
Common Mistakes:
  • Confusing commit-msg hook with pre-push or post-commit hooks
  • Thinking it automatically pushes commits
  • Assuming it modifies commit history
2. Which of the following is the correct way to make a commit-msg hook executable on a Unix-like system?
easy
A. chmod 000 .git/hooks/commit-msg
B. chmod +x .git/hooks/commit-msg
C. git commit --hook commit-msg
D. git hook enable commit-msg

Solution

  1. Step 1: Understand file permissions for hooks

    Git hooks are scripts stored in the .git/hooks directory and must be executable to run.
  2. Step 2: Identify the correct command to make a file executable

    The command chmod +x adds execute permission to the file, enabling the hook to run.
  3. Final Answer:

    chmod +x .git/hooks/commit-msg -> Option B
  4. Quick Check:

    chmod +x = make executable [OK]
Hint: Use chmod +x to enable hook execution [OK]
Common Mistakes:
  • Using chmod 000 which removes all permissions
  • Trying git commands that don't exist for hooks
  • Not setting executable permission, so hook won't run
3. Given this commit-msg hook script snippet, what will happen if the commit message is empty?
#!/bin/sh
if [ -z "$1" ]; then
  echo "Error: Commit message is empty." >&2
  exit 1
fi
medium
A. The commit will be blocked with an error message
B. The commit message will be replaced with a default message
C. The commit will proceed without any message
D. The script will ignore the message and exit with 0

Solution

  1. Step 1: Analyze the script condition

    The script checks if the first argument $1 is empty using [ -z "$1" ]. In the commit-msg hook, $1 is the path to a temporary file containing the proposed commit message.
  2. Step 2: Understand Git's behavior

    Since $1 is the file path, it is never empty, so the condition [ -z "$1" ] is false. However, the script as written incorrectly checks the variable $1 instead of the content of the file. To check if the commit message is empty, the script should check the content of the file, e.g., if [ ! -s "$1" ] or if [ -z "$(cat $1)" ]. As is, the script will not block empty commit messages.
  3. Final Answer:

    The commit will proceed without any message -> Option C
  4. Quick Check:

    $1 is file path, not content; checking it for emptiness is incorrect [OK]
Hint: $1 is file path, not content; check with `cat $1` [OK]
Common Mistakes:
  • Thinking exit 1 allows commit to proceed
  • Assuming the message is replaced automatically
  • Confusing $1 with the commit message text instead of file path
4. You wrote this commit-msg hook to reject messages shorter than 10 characters:
#!/bin/sh
MSG=$(cat "$1")
if [ ${#MSG} -lt 10 ]; then
  echo "Commit message too short." >&2
  exit 1
fi
But it does not block short messages. What is the likely problem?
medium
A. The hook script is not executable
B. The commit message file path is incorrect
C. The shell does not support ${#MSG} syntax for string length
D. The script should use -z instead of -lt

Solution

  1. Step 1: Check the script logic

    The script correctly reads the commit message and checks its length using ${#MSG} which is valid in sh/bash.
  2. Step 2: Consider common hook issues

    If the hook is not executable, Git will ignore it and allow commits without running the script.
  3. Final Answer:

    The hook script is not executable -> Option A
  4. Quick Check:

    Non-executable hook = script not run [OK]
Hint: Make sure hook script is executable with chmod +x [OK]
Common Mistakes:
  • Assuming ${#MSG} is invalid in shell
  • Confusing file path with message content
  • Using wrong test operators like -z for length comparison
5. You want to enforce commit messages to start with a ticket number like PROJ-123: followed by a space and description. Which commit-msg hook snippet correctly validates this pattern?
hard
A. #!/bin/sh MSG=$(cat "$1") if echo "$MSG" | grep -qE '^PROJ-[a-z]+: .+'; then echo "Invalid ticket format" >&2 exit 1 fi
B. #!/bin/sh MSG=$(cat "$1") if echo "$MSG" | grep -q '^PROJ-[0-9]+: .+'; then exit 1 fi
C. #!/bin/sh if [ -z "$1" ]; then echo "Empty message" >&2 exit 0 fi
D. #!/bin/sh MSG=$(cat "$1") if ! echo "$MSG" | grep -qE '^PROJ-[0-9]+: .+'; then echo "Commit message must start with 'PROJ-<number>: '" >&2 exit 1 fi

Solution

  1. Step 1: Understand the required pattern

    The commit message must start with 'PROJ-' followed by digits, a colon, a space, then some text.
  2. Step 2: Analyze each option's regex and logic

    #!/bin/sh MSG=$(cat "$1") if ! echo "$MSG" | grep -qE '^PROJ-[0-9]+: .+'; then echo "Commit message must start with 'PROJ-<number>: '" >&2 exit 1 fi uses grep -qE with '^PROJ-[0-9]+: .+' and exits with error if pattern not matched, which is correct. #!/bin/sh MSG=$(cat "$1") if echo "$MSG" | grep -q '^PROJ-[0-9]+: .+'; then exit 1 fi exits on match (wrong logic). #!/bin/sh if [ -z "$1" ]; then echo "Empty message" >&2 exit 0 fi exits 0 on empty message (wrong). #!/bin/sh MSG=$(cat "$1") if echo "$MSG" | grep -qE '^PROJ-[a-z]+: .+'; then echo "Invalid ticket format" >&2 exit 1 fi checks for lowercase letters after PROJ- which is incorrect.
  3. Final Answer:

    #!/bin/sh MSG=$(cat "$1") if ! echo "$MSG" | grep -qE '^PROJ-[0-9]+: .+'; then echo "Commit message must start with 'PROJ-<number>: '" >&2 exit 1 fi -> Option D
  4. Quick Check:

    grep -qE '^PROJ-[0-9]+: .+' = valid pattern check [OK]
Hint: Use grep -qE with ^PROJ-[0-9]+: .+ to validate pattern [OK]
Common Mistakes:
  • Reversing logic: exiting on match instead of no match
  • Using wrong regex for digits or colon
  • Exiting with 0 on error conditions
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard