prepare-commit-msg Hook
Auto-populate karo, developer ko bas WHY likhna hai. Ticket, template, Co-authored-by — sab automatic.
prepare-commit-msg is the hook that runs BEFORE your commit message editor opens. Think of it as a pre-fill assistant — it writes to the message file before you see it.
It receives 3 arguments:
$1— path to the message file (this is what you write to)$2— message source: "message" (-m flag), "template" (-t flag), "merge", "squash", or "commit" (amend)$3— commit SHA (only for amend/squash operations)
The message source ($2) is critical — it tells you WHERE the message came from so you can decide whether to modify it.
Possible values of $2:
- empty string — user ran
git commit(editor mode), no existing message - "message" — user used
git commit -m "..." - "template" — user used
git commit -t template_file - "merge" — this is a merge commit (auto-generated message)
- "squash" — this is a squash merge (combined messages)
- "commit" — user is amending a commit (
git commit --amend)
Unlike commit-msg (which VALIDATES after the user writes), prepare-commit-msg PRE-POPULATES before the user writes. The developer sees a pre-filled message in their editor and just adds their description.
This hook should rarely block commits (exit 1). It is for automation, not enforcement.
# Understand the arguments
cat > .git/hooks/prepare-commit-msg << 'EOF'
#!/bin/bash
MSG_FILE=$1 # Path to message file
MSG_SOURCE=$2 # Where the message came from
COMMIT_SHA=$3 # SHA (only for amend/squash)
echo "Message file: $MSG_FILE"
echo "Source: $MSG_SOURCE"
echo "Commit SHA: $COMMIT_SHA"
# Don't modify anything yet — just observe
EOF
chmod +x .git/hooks/prepare-commit-msg
# Try different commit types:
git commit -m "test" # source = "message"
git commit # source = "" (editor)
git commit --amend # source = "commit"
# During merge: source = "merge"The #1 use case for prepare-commit-msg: extract the ticket number from the branch name and add it to the message automatically.
Branch: feature/JIRA-456-add-auth → Message starts with [JIRA-456]
The pattern is simple: git rev-parse --abbrev-ref HEAD gets the branch name, then extract the ticket with a regex like [A-Z]+-[0-9]+.
Important: only add the ticket if it is not already in the message — always check before appending to avoid duplication.
This saves developers from manually typing ticket numbers on every single commit. No more "forgot to add the JIRA ticket" excuses.
For GitHub-style branches: extract #123 from fix-123-bug and add (#123) to the message.
# Auto-add JIRA ticket from branch name
cat > .git/hooks/prepare-commit-msg << 'EOF'
#!/bin/bash
MSG_FILE=$1
MSG_SOURCE=$2
# Don't modify merge, squash, or amend messages
if [ "$MSG_SOURCE" = "merge" ] || [ "$MSG_SOURCE" = "squash" ] || [ "$MSG_SOURCE" = "commit" ]; then
exit 0
fi
# Get current branch name
BRANCH=$(git rev-parse --abbrev-ref HEAD)
# Extract ticket number (JIRA-123, PROJ-456, etc.)
TICKET=$(echo $BRANCH | grep -oE '[A-Z]+-[0-9]+')
if [ -n "$TICKET" ]; then
# Check if ticket is already in the message
EXISTING=$(cat "$MSG_FILE")
if ! echo "$EXISTING" | grep -q "$TICKET"; then
# Prepend ticket to message
echo "[$TICKET] $EXISTING" > "$MSG_FILE"
fi
fi
exit 0
EOF
chmod +x .git/hooks/prepare-commit-msg
# Now when you commit on branch feature/JIRA-456-add-auth:
git commit
# Editor opens with: [JIRA-456]
# Developer just types the description after the ticket!prepare-commit-msg can inject a template that guides developers on what to write. Instead of facing a blank editor, they see a structured form with helpful reminders.
A good template includes:
- First line — subject (what changed, max 72 chars)
- Blank line — separator between subject and body
- Body — describe WHY the change was made (the diff shows WHAT)
- Footer — references, breaking changes, co-authors
You can include reminders as comments (# lines are ignored in commit messages). This ensures consistent message structure across the team.
Templates are especially helpful for new developers who don't know the team's commit message conventions yet.
# Inject a template via prepare-commit-msg
cat > .git/hooks/prepare-commit-msg << 'EOF'
#!/bin/bash
MSG_FILE=$1
MSG_SOURCE=$2
# Don't modify merge/squash/amend
if [ "$MSG_SOURCE" = "merge" ] || [ "$MSG_SOURCE" = "squash" ] || [ "$MSG_SOURCE" = "commit" ]; then
exit 0
fi
# Write template to message file
cat > "$MSG_FILE" << TEMPLATE
# Type your commit subject here (max 72 chars)
#
# Describe WHY this change was made (not what — diff shows what)
#
# Footer: References, Breaking Changes, etc.
TEMPLATE
exit 0
EOF
chmod +x .git/hooks/prepare-commit-msg
# Now git commit opens editor with:
# # Type your commit subject here (max 72 chars)
# #
# # Describe WHY this change was made
# #
# # Footer: References, Breaking Changes, etc.
#
# Developer sees instructions, # lines are stripped on save!
In pair programming, both authors should be credited in the commit. The Co-authored-by: trailer in the commit footer gives both authors credit on GitHub.
prepare-commit-msg can auto-add this for teams that always pair program. It checks a pairing configuration file (like .pair) and adds the current pair's information.
GitHub recognizes Co-authored-by: — both authors get contribution credit on their profile. This is the standard way to credit pair programming in Git.
The format must be exact: Co-authored-by: Name <email> — GitHub parses this specific format.
# Auto-add Co-authored-by
cat > .git/hooks/prepare-commit-msg << 'EOF'
#!/bin/bash
MSG_FILE=$1
MSG_SOURCE=$2
# Don't modify merge/squash/amend
if [ "$MSG_SOURCE" = "merge" ] || [ "$MSG_SOURCE" = "squash" ]; then
exit 0
fi
# Check if .pair file exists (team pairing config)
if [ -f ".pair" ]; then
PAIR=$(cat .pair)
# .pair contains: "Jane Smith "
EXISTING=$(cat "$MSG_FILE")
# Only add if not already present
if ! echo "$EXISTING" | grep -q "Co-authored-by"; then
echo "" >> "$MSG_FILE"
echo "Co-authored-by: $PAIR" >> "$MSG_FILE"
fi
fi
exit 0
EOF
chmod +x .git/hooks/prepare-commit-msg
# Create .pair file
echo "Priya Sharma " > .pair
# Now commits automatically include:
# feat: add login
#
# Co-authored-by: Priya Sharma
# Both authors get credit on GitHub! DON'T modify merge commit messages — they contain important branch information like "Merge branch 'feature' into main". Overwriting this breaks Git's automatic merge tracking.
DON'T modify squash commit messages — they're auto-generated from multiple commits and contain the full history of the squashed branch.
DON'T modify amend messages — the developer intentionally changed the message. Your hook would re-add things they just removed.
DON'T overwrite the entire message — always prepend or append. Overwriting destroys existing content including -m messages.
DON'T add metadata that's already in the message — always check before adding to avoid duplicates.
Use $2 (message source) to decide whether to modify: only modify when source is empty or "message".
Lo kar liya — Key Points:
- ✅ prepare-commit-msg runs BEFORE the editor opens — it auto-populates the message
- ✅ It receives 3 arguments: $1 = message file, $2 = message source, $3 = commit SHA
- ✅ Primary use: extract ticket number from branch name and prepend to message
- ✅ Don't modify merge, squash, or amend messages — check $2 before modifying
- ✅ Use comment lines (#) in templates for instructions — Git strips them from final message
- ✅ Auto-add Co-authored-by for pair programming — both authors get credit on GitHub
- ✅ This hook is for CONVENIENCE (auto-fill), not ENFORCEMENT (use commit-msg for that)
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login