Setup — Git Hook Collection¶
Create the project structure and verify ShellCheck is available.
Directory Structure¶
mkdir -p ~/projects/git-hooks
cd ~/projects/git-hooks
# Create hook files (will write content in implementation)
touch pre-commit commit-msg pre-push install.sh
chmod +x pre-commit commit-msg pre-push install.sh
Your project:
~/projects/git-hooks/
├── pre-commit ← ShellCheck + whitespace check
├── commit-msg ← conventional commit format validator
├── pre-push ← main branch protection
└── install.sh ← symlinks hooks into .git/hooks/
Install ShellCheck¶
ShellCheck is a static analysis tool for shell scripts. Install it before writing the pre-commit hook.
# Debian/Ubuntu
sudo apt install shellcheck
# macOS
brew install shellcheck
# Fedora/RHEL
sudo dnf install ShellCheck
# Verify
shellcheck --version
ShellCheck - shell script analysis tool
version: 0.9.0
Create a Test Git Repository¶
You need a git repo to test hooks against:
mkdir -p /tmp/hook_test_repo
cd /tmp/hook_test_repo
git init
git config user.email "test@example.com"
git config user.name "Test User"
Understand Staged Files¶
The pre-commit hook must inspect only staged files (not all files):
scripts/deploy.sh
scripts/backup.sh
scripts/deploy.sh
scripts/backup.sh
The --diff-filter=ACM flag includes Added, Copied, and Modified files — it excludes Deleted files that you wouldn't want to check.
Read the commit-msg Argument¶
Git passes the path to the commit message file as $1 to the commit-msg hook:
Test this manually:
Read pre-push Arguments¶
The pre-push hook receives the remote name and URL on stdin and as arguments:
# In pre-push hook:
REMOTE="$1"
URL="$2"
echo "Pushing to remote: $REMOTE ($URL)"
# Reads lines: <local_ref> <local_sha1> <remote_ref> <remote_sha1>
while IFS=' ' read -r local_ref local_sha remote_ref remote_sha; do
echo "Ref: $local_ref → $remote_ref"
done