0
0
Gitdevops~15 mins

commit-msg hook for message validation in Git - Deep Dive

Choose your learning style9 modes available
Overview - commit-msg hook for message validation
What is it?
A commit-msg hook is a script that runs automatically every time you make a commit in git. It checks the commit message you write before the commit is saved. This hook helps ensure that commit messages follow certain rules or formats. It stops commits with bad messages from being saved, keeping your project history clean and understandable.
Why it matters
Without commit message validation, commit messages can be messy, unclear, or inconsistent. This makes it hard for teams to understand changes, track bugs, or review history. The commit-msg hook enforces good message habits, improving communication and collaboration. It saves time and frustration by catching mistakes early.
Where it fits
Before learning commit-msg hooks, you should know basic git commands like commit and push. After mastering commit-msg hooks, you can explore other git hooks like pre-commit or post-commit. Later, you might learn about automated CI/CD pipelines that use commit messages to trigger actions.
Mental Model
Core Idea
A commit-msg hook acts like a gatekeeper that checks your commit message and only lets good messages through.
Think of it like...
It's like a security guard at a building entrance who checks your ID before letting you in. If your ID (commit message) doesn't meet the rules, you can't enter (commit).
┌───────────────┐
│ Write commit  │
│ message       │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ commit-msg    │
│ hook script   │
└──────┬────────┘
       │
  Pass │ Fail
   ┌───▼───┐  ┌───────────────┐
   │ Commit│  │ Reject commit │
   │ saved │  │ with error    │
   └───────┘  └───────────────┘
Build-Up - 7 Steps
1
FoundationWhat is a Git Hook
🤔
Concept: Introduce git hooks as scripts that run automatically on git events.
Git hooks are small scripts placed in the .git/hooks folder of a repository. They run automatically when certain git actions happen, like committing or pushing. These scripts can check or change things before the action finishes.
Result
Learner understands that git hooks automate checks or tasks during git operations.
Knowing that git hooks automate tasks helps you see how commit-msg hooks fit into improving commit quality.
2
FoundationPurpose of commit-msg Hook
🤔
Concept: Explain that commit-msg hook checks the commit message content.
The commit-msg hook runs after you write your commit message but before git saves the commit. It receives the commit message file path as input. The script can read this message and decide if it meets rules like length, format, or keywords.
Result
Learner sees that commit-msg hook controls commit message quality before saving.
Understanding the timing of commit-msg hook clarifies how it prevents bad commit messages.
3
IntermediateWriting a Basic commit-msg Script
🤔Before reading on: do you think the commit-msg hook script must be written in a specific language? Commit to your answer.
Concept: Show how to write a simple commit-msg hook script in bash that checks message length.
Create a file named commit-msg in .git/hooks with this content: #!/bin/sh MESSAGE_FILE="$1" MESSAGE=$(cat "$MESSAGE_FILE") if [ $(echo -n "$MESSAGE" | wc -m) -lt 10 ]; then echo "Commit message too short. Must be at least 10 characters." exit 1 fi exit 0 Make it executable with chmod +x .git/hooks/commit-msg. Now, if your commit message is shorter than 10 characters, git will reject the commit.
Result
Commits with messages shorter than 10 characters are blocked with an error message.
Knowing you can write simple scripts to enforce rules empowers you to customize commit validation.
4
IntermediateEnforcing Commit Message Format
🤔Before reading on: do you think regex can be used in commit-msg hooks to check message patterns? Commit to your answer.
Concept: Introduce using regular expressions to enforce commit message formats like prefixes or ticket numbers.
Modify the commit-msg script to check if the message starts with a ticket ID like 'PROJ-123:': #!/bin/sh MESSAGE_FILE="$1" MESSAGE=$(cat "$MESSAGE_FILE") if ! echo "$MESSAGE" | grep -qE '^PROJ-[0-9]+: '; then echo "Commit message must start with 'PROJ-: '" exit 1 fi exit 0 This script rejects commits without the required prefix.
Result
Only commit messages starting with the correct ticket ID format are accepted.
Using regex in commit-msg hooks allows precise control over message style, improving team consistency.
5
IntermediateSharing commit-msg Hooks Across Team
🤔
Concept: Explain how to share commit-msg hooks with the team using version control.
Git hooks are local and not shared by default. To share, store your commit-msg script in the repository, for example in a folder called hooks/, and add a setup script that copies it to .git/hooks. Example setup script: #!/bin/sh cp hooks/commit-msg .git/hooks/commit-msg chmod +x .git/hooks/commit-msg Team members run this once to install the hook.
Result
All team members use the same commit-msg hook, ensuring consistent commit message validation.
Knowing how to share hooks prevents inconsistent validation and keeps team workflow uniform.
6
AdvancedUsing commit-msg Hook with CI/CD Pipelines
🤔Before reading on: do you think commit-msg hooks run automatically on remote servers during CI builds? Commit to your answer.
Concept: Discuss how commit-msg hooks run locally but CI servers can also validate commit messages separately.
commit-msg hooks run only on local machines during git commit. Remote CI/CD pipelines do not run these hooks automatically. To enforce commit message rules in CI, add scripts or tools in the pipeline that check commit messages of pushed commits. Example: a CI job runs a script that fetches commit messages and validates them with the same rules as the commit-msg hook.
Result
Commit message validation happens both locally and in CI, catching errors missed locally.
Understanding the limits of commit-msg hooks helps design robust validation that covers all commits.
7
ExpertAdvanced commit-msg Hook with External Tools
🤔Before reading on: do you think commit-msg hooks can integrate with external tools like commitlint? Commit to your answer.
Concept: Show how to integrate commit-msg hook with external validation tools for complex rules.
Instead of writing all validation logic in shell, you can call tools like commitlint (Node.js) from the commit-msg hook. Example commit-msg script: #!/bin/sh npx --no-install commitlint --edit "$1" This runs commitlint on the commit message file. commitlint uses config files to enforce complex rules like message types, scopes, and lengths. This approach scales better for large teams and complex policies.
Result
Commit messages are validated against rich, configurable rules using external tools.
Leveraging external tools in commit-msg hooks enables powerful, maintainable validation beyond simple scripts.
Under the Hood
When you run git commit, git prepares the commit message and saves it in a temporary file. Before finalizing the commit, git looks for a commit-msg hook script in .git/hooks. If found and executable, git runs this script, passing the commit message file path as an argument. The script reads the message, performs checks, and exits with status 0 to allow the commit or non-zero to block it. If blocked, git shows the script's error output and cancels the commit.
Why designed this way?
Git hooks were designed as simple executable scripts to allow flexible, customizable automation without changing git's core. Passing the commit message as a file lets scripts handle large messages easily. Using exit codes to control commit success is a standard Unix pattern, making hooks easy to write in any language. This design balances power, simplicity, and portability.
git commit command
     │
     ▼
Prepare commit message file
     │
     ▼
Check for commit-msg hook
     │
     ├─ No hook → commit saved
     │
     └─ Yes hook → run script with message file
           │
           ▼
    Script checks message
           │
    ┌──────┴───────┐
    │              │
Exit 0          Exit non-0
    │              │
Commit saved   Commit rejected
Myth Busters - 4 Common Misconceptions
Quick: Does the commit-msg hook run on the remote git server automatically? Commit to yes or no.
Common Belief:The commit-msg hook runs on the remote server when pushing commits.
Tap to reveal reality
Reality:commit-msg hooks run only locally on the developer's machine during git commit. Remote servers do not run these hooks automatically.
Why it matters:Relying only on local hooks can let bad commit messages slip in if developers disable hooks or use other tools. Remote validation is needed for full enforcement.
Quick: Can you write commit-msg hooks only in shell scripts? Commit to yes or no.
Common Belief:commit-msg hooks must be shell scripts.
Tap to reveal reality
Reality:commit-msg hooks can be written in any executable language (Python, Node.js, Ruby, etc.) as long as the script is executable and accepts the commit message file argument.
Why it matters:Knowing this allows teams to use familiar languages and tools for complex validation logic.
Quick: Does the commit-msg hook change the commit message automatically? Commit to yes or no.
Common Belief:commit-msg hooks can modify the commit message before saving.
Tap to reveal reality
Reality:commit-msg hooks can modify the commit message file, but this is discouraged because it can confuse users. Usually, hooks only validate and reject bad messages.
Why it matters:Misunderstanding this can lead to unexpected commit messages or user frustration.
Quick: Does a commit-msg hook guarantee all commits have valid messages? Commit to yes or no.
Common Belief:Using a commit-msg hook guarantees all commits have valid messages.
Tap to reveal reality
Reality:commit-msg hooks only run on local commits and can be bypassed or disabled. They do not guarantee message quality for commits pushed from other sources.
Why it matters:Relying solely on commit-msg hooks without server-side checks risks inconsistent commit history.
Expert Zone
1
commit-msg hooks run before the commit is finalized but after the message is prepared, so they can read but should avoid complex changes to the message file to prevent confusion.
2
Hooks run with minimal environment variables and no user input, so scripts must be fully automated and not rely on interactive prompts.
3
Because hooks are local, teams often combine commit-msg hooks with server-side validation or CI checks to ensure consistent enforcement.
When NOT to use
Do not rely solely on commit-msg hooks for critical validation in distributed teams or open source projects. Instead, use server-side hooks or CI pipeline checks to enforce commit message policies. For very complex validation, use dedicated tools like commitlint integrated in CI.
Production Patterns
In production, teams store commit-msg hook scripts in the repository and provide setup scripts to install them locally. They use external tools like commitlint for rich validation. CI pipelines run separate checks on pushed commits to catch any invalid messages missed locally. Some projects enforce commit message templates and use commit-msg hooks to ensure compliance.
Connections
Continuous Integration (CI) Pipelines
builds-on
Understanding commit-msg hooks helps grasp how CI pipelines can enforce commit message rules remotely, ensuring quality beyond local checks.
Unix Shell Scripting
same pattern
Knowing shell scripting empowers writing flexible git hooks, as hooks are often simple shell scripts that automate checks.
Quality Control in Manufacturing
similar pattern
Commit-msg hooks act like quality inspectors in manufacturing lines, stopping defective products (bad commits) before they proceed, ensuring overall product quality.
Common Pitfalls
#1Assuming commit-msg hooks run on all machines automatically.
Wrong approach:Relying on .git/hooks/commit-msg without distributing it to team members.
Correct approach:Store commit-msg script in the repo and provide a setup script to copy it to .git/hooks for all team members.
Root cause:Misunderstanding that git hooks are local and not shared by default.
#2Writing commit-msg hook scripts that require user input.
Wrong approach:#!/bin/sh read -p "Enter valid message: " input if [ -z "$input" ]; then exit 1; fi
Correct approach:#!/bin/sh MESSAGE=$(cat "$1") if [ -z "$MESSAGE" ]; then echo "Empty message"; exit 1; fi
Root cause:Not realizing hooks run non-interactively and cannot prompt users.
#3Ignoring exit codes in commit-msg scripts.
Wrong approach:#!/bin/sh echo "Check done"
Correct approach:#!/bin/sh # validation logic if bad; then echo "Error"; exit 1; else exit 0; fi
Root cause:Not understanding that git uses the script's exit code to accept or reject commits.
Key Takeaways
commit-msg hooks are scripts that automatically check commit messages before saving commits in git.
They help enforce consistent, clear commit messages, improving project history and team communication.
Hooks run locally and must be shared explicitly with the team to ensure everyone uses them.
commit-msg hooks do not run on remote servers, so additional validation in CI pipelines is needed for full enforcement.
Using external tools with commit-msg hooks enables powerful, maintainable commit message validation.