Skip to content

harryosmar/git-prehooks-commit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Git Pre-Commit Hooks

Automated Git hooks that enforce commit message conventions and code quality standards.

Features

  • Commit Message Validation - Enforces Jira ticket format (CDE-XXXXX) with optional commit types
  • Conventional Commits - Support for feat, fix, hotfix, docs, and more
  • Code Quality Checks - Detects debug statements, TODOs, trailing whitespace
  • Security Checks - Blocks commits with hardcoded credentials
  • Branch Protection - Prevents direct commits to protected branches
  • Configurable - All rules customizable via .githooks-config.json

Installation

Quick Setup

# 1. Navigate to your repository
cd /path/to/your/repo

# 2. Run the setup script
./setup-hooks.sh

# 3. Done! Hooks are now active

Manual Setup

# Copy hooks to .git/hooks/
cp hooks-templates/commit-msg .git/hooks/
cp hooks-templates/pre-commit .git/hooks/

# Make them executable
chmod +x .git/hooks/commit-msg
chmod +x .git/hooks/pre-commit

Configuration

Edit .githooks-config.json to customize behavior:

{
  "commit-msg": {
    "jira_project": "CDE",
    "min_message_length": 10,
    "max_subject_length": 72,
    "require_type": true,
    "allowed_types": ["feat", "fix", "hotfix", "docs", "style", "refactor", "perf", "test", "chore", "build", "ci", "revert", "security"]
  },
  "pre-commit": {
    "protected_branches": ["develop", "master", "micro-qa", "micro-qa-adhoc"],
    "checks": {
      "conflict_markers": { "enabled": true, "blocking": true },
      "debug_statements": {
        "enabled": true,
        "blocking": false,
        "patterns": ["console\\.log", "debugger", "print\\(", "var_dump", "dd\\(", "dump\\("]
      },
      "todo_comments": {
        "enabled": true,
        "blocking": false,
        "patterns": ["TODO", "FIXME", "XXX", "HACK"]
      },
      "large_files": {
        "enabled": true,
        "blocking": false,
        "max_size_bytes": 5242880
      },
      "sensitive_data": {
        "enabled": true,
        "blocking": false,
        "patterns": ["password", "api_key", "secret", "token", "private_key"]
      },
      "trailing_whitespace": { "enabled": true, "blocking": false }
    }
  }
}

Configuration Options

Option Description Default
jira_project Jira project code CDE
min_message_length Min chars after ticket 10
max_subject_length Max subject length 72
require_type Require commit type true
allowed_types List of valid commit types ["feat", "fix", "hotfix", ...]
protected_branches Branches to protect ["develop", "master", "micro-qa", "micro-qa-adhoc"]
enabled Enable/disable check true
blocking Block commit on failure true/false
patterns Detection patterns Varies by check
max_size_bytes Max file size 5242880 (5MB)

Rules & Checks

1. Commit Message Validation

Format Required: CDE-XXXXX: type: Your commit message

Rules:

  • Must start with Jira ticket (e.g., CDE-123:)
  • Must include commit type (e.g., feat:, fix:, hotfix:)
  • Minimum 10 characters after ticket and type
  • Maximum 72 characters for subject line (warning)
  • First letter should be capitalized (warning)
  • Use imperative mood (warning)
  • No period at end of subject (warning)

Commit Types:

Type Description Example
feat New feature CDE-123: feat: Add user authentication
fix Bug fix CDE-456: fix: Resolve login timeout
hotfix Critical production fix CDE-789: hotfix: Fix payment crash
docs Documentation CDE-101: docs: Update API docs
style Code formatting CDE-202: style: Format with prettier
refactor Code refactoring CDE-303: refactor: Simplify auth logic
perf Performance CDE-404: perf: Optimize queries
test Tests CDE-505: test: Add auth unit tests
chore Maintenance CDE-606: chore: Update dependencies
build Build system CDE-707: build: Update webpack
ci CI/CD CDE-808: ci: Add GitHub Actions
revert Revert commit CDE-909: revert: Revert commit abc123
security Security fix CDE-111: security: Fix XSS

✅ Valid Examples:

CDE-123: feat: Add user authentication
CDE-456: fix: Resolve login validation bug
CDE-789: docs: Update API documentation
CDE-101: hotfix: Fix critical payment issue
CDE-202: refactor: Simplify database queries

❌ Invalid Examples:

Add feature                         # Missing Jira ticket
CDE-123 Add feature                # Missing colon
CDE-123: Add feature               # Missing type
CDE-123: feature: Add auth         # Invalid type (use 'feat')
CDE-123: fix: bug                  # Too short (< 10 chars)
CDE-123: FIX: Resolve bug          # Type must be lowercase

Disable Type Requirement:

If you don't want to enforce commit types, set require_type: false in config:

{
  "commit-msg": {
    "jira_project": "CDE",
    "require_type": false
  }
}

Then format becomes: CDE-123: Your commit message

2. Protected Branch Check

Blocks direct commits to:

  • develop
  • master
  • micro-qa
  • micro-qa-adhoc

Solution: Create a feature branch

git checkout -b feature/CDE-123-description

3. Merge Conflict Markers

Detects: <<<<<<<, =======, >>>>>>>

Blocking: ✅ Yes

Example Output:

✗ Merge conflict markers found in 1 file(s):

  • src/app.js

4. Debug Statements

Detects: console.log, debugger, print(), var_dump, dd(), dump()

Blocking: ⚠️ No (warning only)

Example Output:

⚠ Warning: Debug statements found in 2 file(s):

  • src/app.js
  • src/utils.py

Consider removing them before committing

5. TODO/FIXME Comments

Detects: TODO, FIXME, XXX, HACK

Blocking: ⚠️ No (warning only)

Example Output:

⚠ Warning: Found 3 new TODO/FIXME comment(s) in 2 file(s):

  • src/app.js (2 comment(s))
  • src/utils.py (1 comment(s))

Make sure they are tracked in your issue tracker

6. Large Files

Detects: Files larger than 5MB

Blocking: ⚠️ No (warning only)

Example Output:

⚠ Warning: Large files detected (1 file(s)):

  • assets/video.mp4 (10.5MiB)

Consider using Git LFS for large files

7. Sensitive Data

Detects: password, api_key, secret, token, private_key, aws_access_key_id, aws_secret_access_key

Blocking: ⚠️ Configurable (default: warning)

Example Output:

⚠ Warning: Potential sensitive data found in 2 file(s):

File: config.js
+const api_key = "sk_live_abc123xyz789"

File: auth.py
+password = "mySecretPass123"

Please review and remove any hardcoded credentials!

8. Empty Files

Detects: Files with zero bytes

Blocking: ⚠️ No (warning only)

Example Output:

⚠ Warning: Empty files detected (1 file(s)):

  • empty.txt

9. Trailing Whitespace

Detects: Spaces/tabs at end of lines

Blocking: ⚠️ No (warning only)

Example Output:

⚠ Warning: Found trailing whitespace in 2 file(s) (5 line(s)):

  • src/app.js
  • src/utils.py

Run: git diff --cached --check

Usage Examples

Normal Workflow

# 1. Create feature branch
git checkout -b feature/CDE-123-user-auth

# 2. Make changes
vim src/auth.js

# 3. Stage changes
git add src/auth.js

# 4. Commit with proper format (with type)
git commit -m "CDE-123: feat: Add JWT authentication"

# Output:
# 🚀 Running pre-commit checks...
# ✓ No conflict markers found
# ✓ No debug statements found
# ✓ All checks passed!
# 🔍 Validating commit message...
# ✓ Commit message validated successfully!
# Ticket: CDE-123
# Type: feat
# Message: Add JWT authentication

Handling Warnings

# If you get warnings, you can still commit
git commit -m "CDE-456: Add feature with TODO"

# Output:
# ⚠ Warning: Found 1 new TODO/FIXME comment(s)
# ✅ All pre-commit checks passed!

Handling Errors

# Error 1: Missing Jira ticket
git commit -m "Add feature"
# Output: ✗ Commit message must start with Jira ticket format: CDE-XXXXX:

# Error 2: Missing commit type
git commit -m "CDE-123: Add feature"
# Output: ✗ Commit message must include a type
# Allowed types: feat, fix, hotfix, docs, style, refactor, perf, test, chore, build, ci, revert, security

# Error 3: Invalid commit type
git commit -m "CDE-123: feature: Add auth"
# Output: ✗ Invalid commit type 'feature'
# Allowed types: feat, fix, hotfix, docs, ...

# Fix and retry
git commit -m "CDE-123: feat: Add user authentication"
# Output: ✅ Commit message validated successfully!

Testing

Test Commit Message Validation

# Test 1: Missing Jira ticket (should fail)
git commit --allow-empty -m "Add feature"
# Expected: ❌ Rejected - Missing Jira ticket

# Test 2: Missing type (should fail)
git commit --allow-empty -m "CDE-123: Add feature"
# Expected: ❌ Rejected - Missing commit type

# Test 3: Invalid type (should fail)
git commit --allow-empty -m "CDE-123: feature: Add auth"
# Expected: ❌ Rejected - Invalid type

# Test 4: Valid format (should pass)
git commit --allow-empty -m "CDE-123: feat: Add feature"
# Expected: ✅ Accepted

# Test 5: Different types (should pass)
git commit --allow-empty -m "CDE-456: fix: Resolve bug"
git commit --allow-empty -m "CDE-789: docs: Update README"
git commit --allow-empty -m "CDE-101: hotfix: Fix critical issue"
# Expected: ✅ All accepted

Test Protected Branch

# Test on master (should fail)
git checkout master
git commit --allow-empty -m "CDE-123: Test"
# Expected: ❌ Blocked

# Test on feature branch (should pass)
git checkout -b feature/test
git commit --allow-empty -m "CDE-123: Test"
# Expected: ✅ Accepted

Test Debug Statement Detection

# Create file with debug statement
echo 'console.log("test");' > test.js
git add test.js
git commit -m "CDE-123: Test debug detection"
# Expected: ⚠️ Warning shown, commit allowed

Test Sensitive Data Detection

# Create file with sensitive data
echo 'const api_key = "sk_live_abc123xyz789";' > config.js
git add config.js
git commit -m "CDE-123: Test sensitive data"
# Expected: ⚠️ Warning shown (or ❌ blocked if configured)

Test Large File Detection

# Create large file (6MB)
dd if=/dev/zero of=large.bin bs=1m count=6
git add large.bin
git commit -m "CDE-123: Test large file"
# Expected: ⚠️ Warning shown

Test Trailing Whitespace

# Create file with trailing whitespace
echo "line with spaces   " > test.txt
git add test.txt
git commit -m "CDE-123: Test whitespace"
# Expected: ⚠️ Warning shown

Test TODO Comments

# Create file with TODO
echo "// TODO: Fix this later" > test.js
git add test.js
git commit -m "CDE-123: Test TODO detection"
# Expected: ⚠️ Warning shown

Customization

Change Jira Project

{
  "commit-msg": {
    "jira_project": "PROJ",
    "min_message_length": 10,
    "max_subject_length": 72,
    "require_type": true,
    "allowed_types": ["feat", "fix", "hotfix", "docs"]
  }
}

Now commits must use: PROJ-123: type: Message

Disable Commit Type Requirement

{
  "commit-msg": {
    "jira_project": "CDE",
    "require_type": false
  }
}

Now commits can use: CDE-123: Message (without type)

Customize Allowed Types

{
  "commit-msg": {
    "require_type": true,
    "allowed_types": ["feat", "fix", "hotfix", "docs", "wip"]
  }
}

Now only these types are allowed: feat, fix, hotfix, docs, wip

Add More Protected Branches

{
  "pre-commit": {
    "protected_branches": ["develop", "master", "staging", "production"]
  }
}

Make Sensitive Data Blocking

{
  "sensitive_data": {
    "enabled": true,
    "blocking": true,
    "patterns": ["password", "api_key", "secret"]
  }
}

Add Custom Debug Patterns

{
  "debug_statements": {
    "enabled": true,
    "blocking": false,
    "patterns": ["console\\.log", "debugger", "alert\\(", "System\\.out\\.println"]
  }
}

Disable Specific Checks

{
  "trailing_whitespace": {
    "enabled": false,
    "blocking": false
  }
}

Change File Size Limit

{
  "large_files": {
    "enabled": true,
    "blocking": false,
    "max_size_bytes": 10485760
  }
}

This sets the limit to 10MB (10 * 1024 * 1024 bytes).


Troubleshooting

Hooks Not Running

# Check if hooks are executable
ls -la .git/hooks/commit-msg
ls -la .git/hooks/pre-commit

# Make them executable
chmod +x .git/hooks/commit-msg
chmod +x .git/hooks/pre-commit

Config Not Being Read

# Verify config file exists
cat .githooks-config.json

# Verify JSON is valid
python -m json.tool .githooks-config.json

False Positives

If a check incorrectly flags your code:

  1. Review the pattern in .githooks-config.json
  2. Adjust or remove the pattern

Team Setup

Since Git hooks are local and not tracked by Git:

  1. Add to onboarding docs: Include hook setup in new developer onboarding
  2. Run setup script: Each team member must run ./setup-hooks.sh
  3. Keep templates updated: Commit changes to hooks-templates/ directory

Files Structure

.
├── .githooks-config.json       # Configuration file
├── .gitignore                  # Git ignore rules
├── setup-hooks.sh              # Installation script
├── hooks-templates/            # Hook templates (git-trackable)
│   ├── commit-msg              # Commit message validator
│   └── pre-commit              # Pre-commit quality checks
└── README.md                   # This file

FAQ

Q: Do hooks run on git merge?
A: The commit-msg hook skips merge commits automatically.

Q: Can I use a different Jira project?
A: Yes, change jira_project in .githooks-config.json.

Q: What if I don't use Jira?
A: You can modify the commit-msg hook to use a different format.

Q: Are hooks shared with the team?
A: No, each team member must run the setup script.

Q: Can I make warnings blocking?
A: Yes, set "blocking": true for any check in the config.

Q: How do I update hooks?
A: Pull latest changes and run ./setup-hooks.sh again.


License

MIT License - Free to use and modify for your projects.


Support

For issues or questions:

  1. Check this README
  2. Review the hook output messages (they're designed to be helpful)
  3. Check .githooks-config.json for configuration issues
  4. Review hook files in hooks-templates/ for logic

Built with ❤️ for better code quality and security

About

Git hooks enforcing Jira ticket format with conventional commit types and code quality checks

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages