Commit-msg Hook: Enforcing Message Format
A real commit, genuinely rejected for missing a ticket reference. Then genuinely accepted.
git runs a real script at .git/hooks/commit-msg (if one exists and is executable) every single time a commit is attempted, passing it the path to a real temp file holding the proposed message. If the script exits non-zero, the real commit is genuinely rejected — no exceptions, no way around it short of --no-verify.\n\nThis lab writes a real hook requiring every commit message to start with a ticket reference like RECIPE-123: . A real commit without one gets rejected on the spot; the identical real change, committed with the right prefix, goes through immediately.
A Real, Executable Hook
#!/bin/sh
if ! grep -qE "^[A-Z]+-[0-9]+: " "$1"; then
echo "ERROR: commit message must start with a ticket reference, e.g. 'RECIPE-123: ...'"
exit 1
fi
git passes the proposed commit message's real file path as $1. A non-zero exit genuinely blocks the commit.
A Real Rejection
git commit -m "add meal prep containers guide"
# ERROR: commit message must start with a ticket reference...
Rejected immediately — the real commit never happens, the staged changes stay staged.
The Same Real Change, Now Accepted
git commit -m "RECIPE-301: Add meal prep containers guide"
Identical content, real ticket prefix — the hook lets it straight through.
commit-msg hook
A real, local script git runs automatically on every commit attempt, given the proposed message's file path. Confirmed directly in this lab: a non-zero exit genuinely blocked the commit before it was created.
Hooks are local, not shared
A hook committed inside a repository's tracked files is never automatically installed for anyone else — .git/hooks/ itself is never part of a real clone. Real teams distribute hooks separately (a setup script, or a tool like Husky).
🪝 Write the Real Hook
A real, executable script enforcing the ticket-reference format.
cd ~/team-recipes && printf '#!/bin/sh\nif ! grep -qE "^[A-Z]+-[0-9]+: " "$1"; then\n echo "ERROR: commit message must start with a ticket reference, e.g. '"'"'RECIPE-123: ...'"'"'"\n exit 1\nfi\n' > .git/hooks/commit-msgcd ~/team-recipes && chmod +x .git/hooks/commit-msgcd ~/team-recipes && cat .git/hooks/commit-msgstudent@lab:~$ cd ~/team-recipes && printf '#!/bin/sh\nif ! grep -qE "^[A-Z]+-[0-9]+: " "$1"; then\n echo "ERROR: commit message must start with a ticket reference, e.g. '"'"'RECIPE-123: ...'"'"'"\n exit 1\nfi\n' > .git/hooks/commit-msg student@lab:~$ cd ~/team-recipes && chmod +x .git/hooks/commit-msg student@lab:~$ cd ~/team-recipes && cat .git/hooks/commit-msg #!/bin/sh if ! grep -qE "^[A-Z]+-[0-9]+: " "$1"; then echo "ERROR: commit message must start with a ticket reference, e.g. 'RECIPE-123: ...'" exit 1 fi
🚫 A Real Rejection
No ticket prefix — the hook genuinely blocks it.
cd ~/team-recipes && echo 'Meal Prep Containers' > meal-prep-containers.mdcd ~/team-recipes && git add meal-prep-containers.mdcd ~/team-recipes && git commit -m "add meal prep containers guide"student@lab:~$ cd ~/team-recipes && echo 'Meal Prep Containers' > meal-prep-containers.md student@lab:~$ cd ~/team-recipes && git add meal-prep-containers.md student@lab:~$ cd ~/team-recipes && git commit -m "add meal prep containers guide" ERROR: commit message must start with a ticket reference, e.g. 'RECIPE-123: ...'
✅ The Same Real Change, Accepted
Add the real ticket reference — the hook lets it through.
cd ~/team-recipes && git commit -m "RECIPE-301: Add meal prep containers guide"cd ~/team-recipes && git log --oneline -1student@lab:~$ cd ~/team-recipes && git commit -m "RECIPE-301: Add meal prep containers guide" [master 0d592cc] RECIPE-301: Add meal prep containers guide 1 file changed, 1 insertion(+) create mode 100644 meal-prep-containers.md student@lab:~$ cd ~/team-recipes && git log --oneline -1 0d592cc (HEAD -> master) RECIPE-301: Add meal prep containers guide
Lab 3.6.1 complete. A real commit-msg hook, genuinely enforcing the team's format:\n\n\n Hook installed : ✅ real, executable\n No ticket ref : ✅ genuinely rejected\n With ticket ref : ✅ genuinely accepted\n
Enable JavaScript to run the live terminal and track your progress.