Git Auto Commit On Stop - Hooks
Automatically commits all changes with a summary when Claude Code session ends.
Open the source and read safety notes before installing.
Safety notes
- Runs automatically at session end and stages all unignored repository changes with git add -A.
- Creates a local commit when changes are present unless SKIP_AUTO_COMMIT=true is set.
- Only warns on sensitive-looking filenames and does not block the commit by default.
Privacy notes
- Reads git status, branch name, staged diff statistics, and changed file names to build the commit message.
- Can commit newly created or modified local files, including private work, when they are not excluded by .gitignore.
- Commit metadata uses the locally configured git user name and email.
Schema details
- Install type
- cli
- Reading time
- 1 min
- Difficulty score
- 0
- Troubleshooting
- Yes
- Breaking changes
- No
- Trigger
- Stop
- Script language
- bash
Script body
#!/usr/bin/env bash
echo "💾 Checking for changes to auto-commit..." >&2
# Check if we're in a git repository
if ! git rev-parse --git-dir > /dev/null 2>&1; then
echo "⚠️ Not in a git repository - skipping auto-commit" >&2
exit 0
fi
# Check if git is configured
if ! git config user.email > /dev/null 2>&1 || ! git config user.name > /dev/null 2>&1; then
echo "⚠️ Git user not configured - skipping auto-commit" >&2
echo "💡 Run: git config --global user.email 'your@email.com'" >&2
echo "💡 Run: git config --global user.name 'Your Name'" >&2
exit 0
fi
# Get current timestamp
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
ISO_TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date +"%Y-%m-%d %H:%M:%S UTC")
# Get current branch
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
# Check for uncommitted changes
if [ -z "$(git status --porcelain 2>/dev/null)" ]; then
echo "✨ No changes to commit - repository is clean" >&2
exit 0
fi
echo "📊 Analyzing changes for auto-commit..." >&2
# Get status information
UNTRACKED_FILES=$(git status --porcelain 2>/dev/null | grep '^??' | wc -l | xargs)
MODIFIED_FILES=$(git status --porcelain 2>/dev/null | grep '^.M' | wc -l | xargs)
ADDED_FILES=$(git status --porcelain 2>/dev/null | grep '^A' | wc -l | xargs)
DELETED_FILES=$(git status --porcelain 2>/dev/null | grep '^.D' | wc -l | xargs)
RENAMED_FILES=$(git status --porcelain 2>/dev/null | grep '^R' | wc -l | xargs)
echo "📋 Change summary:" >&2
echo " Branch: $CURRENT_BRANCH" >&2
echo " Untracked: $UNTRACKED_FILES files" >&2
echo " Modified: $MODIFIED_FILES files" >&2
echo " Added: $ADDED_FILES files" >&2
echo " Deleted: $DELETED_FILES files" >&2
echo " Renamed: $RENAMED_FILES files" >&2
# Check for sensitive files before committing
echo "🔒 Checking for sensitive files..." >&2
SENSITIVE_PATTERNS=(
"\.env"
"\.env\.*"
"*secret*"
"*password*"
"*key*"
"id_rsa"
"id_ed25519"
"*.pem"
"*.p12"
"*.pfx"
)
SENSITIVE_FOUND=false
for pattern in "${SENSITIVE_PATTERNS[@]}"; do
if git status --porcelain 2>/dev/null | grep -q "$pattern"; then
SENSITIVE_FOUND=true
echo "⚠️ Potentially sensitive file detected: $pattern" >&2
fi
done
# Check if .gitignore exists and is respected
if [ ! -f ".gitignore" ]; then
echo "💡 Consider creating a .gitignore file to exclude unwanted files" >&2
fi
# Option to skip auto-commit if environment variable is set
if [ "$SKIP_AUTO_COMMIT" = "true" ]; then
echo "⏭️ Auto-commit skipped (SKIP_AUTO_COMMIT=true)" >&2
exit 0
fi
# Warn about sensitive files but don't block (user choice)
if [ "$SENSITIVE_FOUND" = true ]; then
echo "⚠️ Sensitive files detected - proceeding with caution" >&2
echo "💡 Set SKIP_AUTO_COMMIT=true to disable auto-commits" >&2
fi
# Add all changes (respecting .gitignore)
echo "📥 Staging changes for commit..." >&2
git add -A
# Double-check that we have staged changes
if [ -z "$(git diff --cached --name-only)" ]; then
echo "ℹ️ No changes staged after git add - nothing to commit" >&2
exit 0
fi
# Calculate detailed statistics
echo "📊 Calculating commit statistics..." >&2
FILES_CHANGED=$(git diff --cached --numstat | wc -l | xargs)
INSERTIONS=0
DELETIONS=0
# Calculate insertions and deletions more reliably
if command -v awk &> /dev/null; then
STATS=$(git diff --cached --numstat | awk '{insertions+=$1; deletions+=$2} END {print insertions " " deletions}')
read -r INSERTIONS DELETIONS <<< "$STATS"
else
# Fallback method
INSERTIONS=$(git diff --cached --stat | grep -oE '[0-9]+ insertion' | grep -oE '[0-9]+' | paste -sd+ | bc 2>/dev/null || echo '0')
DELETIONS=$(git diff --cached --stat | grep -oE '[0-9]+ deletion' | grep -oE '[0-9]+' | paste -sd+ | bc 2>/dev/null || echo '0')
fi
# Generate commit message
COMMIT_MSG="🤖 Claude Code auto-commit: Session ended"
# Add detailed commit body
COMMIT_BODY=$(cat <<EOF
Session Summary:
- Branch: $CURRENT_BRANCH
- Files changed: $FILES_CHANGED
- Insertions: +$INSERTIONS
- Deletions: -$DELETIONS
- Timestamp: $TIMESTAMP
Changes by type:
- Modified files: $MODIFIED_FILES
- New files: $UNTRACKED_FILES
- Deleted files: $DELETED_FILES
- Renamed files: $RENAMED_FILES
🤖 Generated with Claude Code
EOF
)
# Show what will be committed
echo "📝 Files to be committed:" >&2
git diff --cached --name-status | head -10 | while read status file; do
case $status in
A) echo " ✅ Added: $file" >&2 ;;
M) echo " ✏️ Modified: $file" >&2 ;;
D) echo " ❌ Deleted: $file" >&2 ;;
R*) echo " 🔄 Renamed: $file" >&2 ;;
*) echo " 📄 $status: $file" >&2 ;;
esac
done
if [ "$FILES_CHANGED" -gt 10 ]; then
echo " ... and $((FILES_CHANGED - 10)) more files" >&2
fi
echo "" >&2
echo "💾 Creating auto-commit..." >&2
# Create the commit
if echo "$COMMIT_BODY" | git commit -F -; then
echo "✅ Auto-commit successful!" >&2
# Show commit info
COMMIT_HASH=$(git rev-parse --short HEAD)
echo "📝 Commit: $COMMIT_HASH" >&2
echo "🌿 Branch: $CURRENT_BRANCH" >&2
# Check if we should push (optional)
if [ "$AUTO_PUSH" = "true" ]; then
echo "📤 Auto-pushing to remote..." >&2
if git push 2>/dev/null; then
echo "✅ Pushed to remote successfully" >&2
else
echo "⚠️ Push failed - commit created locally" >&2
echo "💡 Run 'git push' manually when ready" >&2
fi
else
echo "💡 Set AUTO_PUSH=true to automatically push commits" >&2
fi
else
echo "❌ Auto-commit failed" >&2
echo "💡 You may need to resolve conflicts or check git status" >&2
exit 1
fi
echo "" >&2
echo "📋 Auto-Commit Summary:" >&2
echo " ✅ $FILES_CHANGED files committed" >&2
echo " 📈 +$INSERTIONS insertions, -$DELETIONS deletions" >&2
echo " ⏰ $TIMESTAMP" >&2
echo "" >&2
echo "💡 Git Auto-Commit Tips:" >&2
echo " • Set SKIP_AUTO_COMMIT=true to disable" >&2
echo " • Set AUTO_PUSH=true to auto-push commits" >&2
echo " • Review commits with 'git log --oneline'" >&2
echo " • Use .gitignore to exclude sensitive files" >&2
exit 0Full copyable content
{
"hooks": {
"stop": {
"script": "./.claude/hooks/git-auto-commit-on-stop.sh"
}
}
}About this resource
Features
- Automatic git commit creation when session ends with comprehensive change detection including untracked files, modified files, added files, deleted files, and renamed files with detailed status analysis
- Detailed commit statistics (files changed, insertions, deletions) with accurate line count calculations using git diff --numstat and awk for reliable statistics across all file types including binary files
- Smart commit message generation with timestamps including ISO 8601 timestamps, session summaries, branch information, file change breakdowns, and customizable commit message templates with environment variable support
- Pre-commit validation and safety checks including sensitive file detection (.env, secrets, keys, certificates) with pattern matching, Git configuration validation (user.name, user.email), and repository state verification
- Branch and repository state verification with current branch detection, Git repository validation, clean repository detection, and branch state checking before commit creation
- Customizable commit message templates with environment variable overrides (SKIP_AUTO_COMMIT, AUTO_PUSH) and support for custom commit message formats with detailed session summaries and change breakdowns
- Untracked file handling and gitignore respect with automatic .gitignore validation, untracked file detection, and proper handling of ignored files with recommendations for .gitignore creation when missing
- Error handling with informative feedback including commit failure recovery, Git configuration error messages, repository state error handling, and push failure recovery with manual push recommendations
Use Cases
- Automatic version control for development sessions providing seamless Git integration without manual commit creation and comprehensive session tracking with detailed change summaries
- Backup and history preservation of work progress automatically preserving all development work with timestamped commits and detailed change tracking for progress recovery and session history
- Collaborative development with session tracking enabling team members to track development sessions with automatic commits and detailed change summaries for collaboration and code review
- CI/CD integration with automated commits automatically committing changes for CI/CD pipeline integration with detailed commit messages and statistics for build tracking and deployment automation
- Project milestone and progress documentation providing automatic documentation of development milestones with timestamped commits and detailed change summaries for project progress tracking
- Development workflow integration seamlessly integrating automatic Git commits into development workflows without manual Git operations or separate version control tools
Installation
- Create hooks directory: mkdir -p .claude/hooks
- Create hook file: touch .claude/hooks/git-auto-commit-on-stop.sh
- Make executable: chmod +x .claude/hooks/git-auto-commit-on-stop.sh
- Add configuration from Hook Configuration section above to .claude/settings.json or ~/.claude/settings.json
- Alternative: Use the interactive /hooks command in Claude Code
Config paths
- Local (not committed):
.claude/settings.local.json - User settings (global):
~/.claude/settings.json - Project-wide (committed):
.claude/settings.json
Requirements
- Claude Code CLI installed
- Project directory initialized
- Git repository initialized
- Git configured (user.name and user.email)
- Bash shell available
- Standard Unix utilities: awk (for parsing git diff --numstat), grep (for sensitive file detection), and Git write access for commit and push operations
Hook Configuration
{
"hooks": {
"stop": {
"script": "./.claude/hooks/git-auto-commit-on-stop.sh"
}
}
}
Hook Script
#!/usr/bin/env bash
echo "💾 Checking for changes to auto-commit..." >&2
# Check if we're in a git repository
if ! git rev-parse --git-dir > /dev/null 2>&1; then
echo "⚠️ Not in a git repository - skipping auto-commit" >&2
exit 0
fi
# Check if git is configured
if ! git config user.email > /dev/null 2>&1 || ! git config user.name > /dev/null 2>&1; then
echo "⚠️ Git user not configured - skipping auto-commit" >&2
echo "💡 Run: git config --global user.email 'your@email.com'" >&2
echo "💡 Run: git config --global user.name 'Your Name'" >&2
exit 0
fi
# Get current timestamp
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
ISO_TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date +"%Y-%m-%d %H:%M:%S UTC")
# Get current branch
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
# Check for uncommitted changes
if [ -z "$(git status --porcelain 2>/dev/null)" ]; then
echo "✨ No changes to commit - repository is clean" >&2
exit 0
fi
echo "📊 Analyzing changes for auto-commit..." >&2
# Get status information
UNTRACKED_FILES=$(git status --porcelain 2>/dev/null | grep '^??' | wc -l | xargs)
MODIFIED_FILES=$(git status --porcelain 2>/dev/null | grep '^.M' | wc -l | xargs)
ADDED_FILES=$(git status --porcelain 2>/dev/null | grep '^A' | wc -l | xargs)
DELETED_FILES=$(git status --porcelain 2>/dev/null | grep '^.D' | wc -l | xargs)
RENAMED_FILES=$(git status --porcelain 2>/dev/null | grep '^R' | wc -l | xargs)
echo "📋 Change summary:" >&2
echo " Branch: $CURRENT_BRANCH" >&2
echo " Untracked: $UNTRACKED_FILES files" >&2
echo " Modified: $MODIFIED_FILES files" >&2
echo " Added: $ADDED_FILES files" >&2
echo " Deleted: $DELETED_FILES files" >&2
echo " Renamed: $RENAMED_FILES files" >&2
# Check for sensitive files before committing
echo "🔒 Checking for sensitive files..." >&2
SENSITIVE_PATTERNS=(
"\.env"
"\.env\.*"
"*secret*"
"*password*"
"*key*"
"id_rsa"
"id_ed25519"
"*.pem"
"*.p12"
"*.pfx"
)
SENSITIVE_FOUND=false
for pattern in "${SENSITIVE_PATTERNS[@]}"; do
if git status --porcelain 2>/dev/null | grep -q "$pattern"; then
SENSITIVE_FOUND=true
echo "⚠️ Potentially sensitive file detected: $pattern" >&2
fi
done
# Check if .gitignore exists and is respected
if [ ! -f ".gitignore" ]; then
echo "💡 Consider creating a .gitignore file to exclude unwanted files" >&2
fi
# Option to skip auto-commit if environment variable is set
if [ "$SKIP_AUTO_COMMIT" = "true" ]; then
echo "⏭️ Auto-commit skipped (SKIP_AUTO_COMMIT=true)" >&2
exit 0
fi
# Warn about sensitive files but don't block (user choice)
if [ "$SENSITIVE_FOUND" = true ]; then
echo "⚠️ Sensitive files detected - proceeding with caution" >&2
echo "💡 Set SKIP_AUTO_COMMIT=true to disable auto-commits" >&2
fi
# Add all changes (respecting .gitignore)
echo "📥 Staging changes for commit..." >&2
git add -A
# Double-check that we have staged changes
if [ -z "$(git diff --cached --name-only)" ]; then
echo "ℹ️ No changes staged after git add - nothing to commit" >&2
exit 0
fi
# Calculate detailed statistics
echo "📊 Calculating commit statistics..." >&2
FILES_CHANGED=$(git diff --cached --numstat | wc -l | xargs)
INSERTIONS=0
DELETIONS=0
# Calculate insertions and deletions more reliably
if command -v awk &> /dev/null; then
STATS=$(git diff --cached --numstat | awk '{insertions+=$1; deletions+=$2} END {print insertions " " deletions}')
read -r INSERTIONS DELETIONS <<< "$STATS"
else
# Fallback method
INSERTIONS=$(git diff --cached --stat | grep -oE '[0-9]+ insertion' | grep -oE '[0-9]+' | paste -sd+ | bc 2>/dev/null || echo '0')
DELETIONS=$(git diff --cached --stat | grep -oE '[0-9]+ deletion' | grep -oE '[0-9]+' | paste -sd+ | bc 2>/dev/null || echo '0')
fi
# Generate commit message
COMMIT_MSG="🤖 Claude Code auto-commit: Session ended"
# Add detailed commit body
COMMIT_BODY=$(cat <<EOF
Session Summary:
- Branch: $CURRENT_BRANCH
- Files changed: $FILES_CHANGED
- Insertions: +$INSERTIONS
- Deletions: -$DELETIONS
- Timestamp: $TIMESTAMP
Changes by type:
- Modified files: $MODIFIED_FILES
- New files: $UNTRACKED_FILES
- Deleted files: $DELETED_FILES
- Renamed files: $RENAMED_FILES
🤖 Generated with Claude Code
EOF
)
# Show what will be committed
echo "📝 Files to be committed:" >&2
git diff --cached --name-status | head -10 | while read status file; do
case $status in
A) echo " ✅ Added: $file" >&2 ;;
M) echo " ✏️ Modified: $file" >&2 ;;
D) echo " ❌ Deleted: $file" >&2 ;;
R*) echo " 🔄 Renamed: $file" >&2 ;;
*) echo " 📄 $status: $file" >&2 ;;
esac
done
if [ "$FILES_CHANGED" -gt 10 ]; then
echo " ... and $((FILES_CHANGED - 10)) more files" >&2
fi
echo "" >&2
echo "💾 Creating auto-commit..." >&2
# Create the commit
if echo "$COMMIT_BODY" | git commit -F -; then
echo "✅ Auto-commit successful!" >&2
# Show commit info
COMMIT_HASH=$(git rev-parse --short HEAD)
echo "📝 Commit: $COMMIT_HASH" >&2
echo "🌿 Branch: $CURRENT_BRANCH" >&2
# Check if we should push (optional)
if [ "$AUTO_PUSH" = "true" ]; then
echo "📤 Auto-pushing to remote..." >&2
if git push 2>/dev/null; then
echo "✅ Pushed to remote successfully" >&2
else
echo "⚠️ Push failed - commit created locally" >&2
echo "💡 Run 'git push' manually when ready" >&2
fi
else
echo "💡 Set AUTO_PUSH=true to automatically push commits" >&2
fi
else
echo "❌ Auto-commit failed" >&2
echo "💡 You may need to resolve conflicts or check git status" >&2
exit 1
fi
echo "" >&2
echo "📋 Auto-Commit Summary:" >&2
echo " ✅ $FILES_CHANGED files committed" >&2
echo " 📈 +$INSERTIONS insertions, -$DELETIONS deletions" >&2
echo " ⏰ $TIMESTAMP" >&2
echo "" >&2
echo "💡 Git Auto-Commit Tips:" >&2
echo " • Set SKIP_AUTO_COMMIT=true to disable" >&2
echo " • Set AUTO_PUSH=true to auto-push commits" >&2
echo " • Review commits with 'git log --oneline'" >&2
echo " • Use .gitignore to exclude sensitive files" >&2
exit 0
Examples
Git Auto Commit On Stop Hook Script
Complete hook script that performs automatic Git commit when development session ends
#!/usr/bin/env bash
echo "💾 Checking for changes to auto-commit..." >&2
if ! git rev-parse --git-dir > /dev/null 2>&1; then
echo "⚠️ Not in a git repository - skipping auto-commit" >&2
exit 0
fi
if [ -z "$(git status --porcelain 2>/dev/null)" ]; then
echo "✨ No changes to commit - repository is clean" >&2
exit 0
fi
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
git add -A
FILES_CHANGED=$(git diff --cached --numstat | wc -l | xargs)
COMMIT_MSG="🤖 Claude Code auto-commit: Session ended at $TIMESTAMP"
if git commit -m "$COMMIT_MSG" -m "Branch: $CURRENT_BRANCH" -m "Files changed: $FILES_CHANGED"; then
echo "✅ Auto-commit successful!" >&2
else
echo "❌ Auto-commit failed" >&2
exit 1
fi
exit 0
Sensitive File Detection and Skip Control
Enhanced hook script for sensitive file detection and environment variable skip control
#!/usr/bin/env bash
if [ "$SKIP_AUTO_COMMIT" = "true" ]; then
echo "⏭️ Auto-commit skipped (SKIP_AUTO_COMMIT=true)" >&2
exit 0
fi
if ! git rev-parse --git-dir > /dev/null 2>&1; then
exit 0
fi
if [ -z "$(git status --porcelain 2>/dev/null)" ]; then
exit 0
fi
SENSITIVE_PATTERNS=(".env" ".env.*" "*secret*" "*password*" "*key*" "id_rsa" "id_ed25519" "*.pem")
SENSITIVE_FOUND=false
for pattern in "${SENSITIVE_PATTERNS[@]}"; do
if git status --porcelain 2>/dev/null | grep -q "$pattern"; then
SENSITIVE_FOUND=true
echo "⚠️ Potentially sensitive file detected: $pattern" >&2
fi
done
if [ "$SENSITIVE_FOUND" = true ]; then
echo "⚠️ Sensitive files detected - proceeding with caution" >&2
echo "💡 Set SKIP_AUTO_COMMIT=true to disable auto-commits" >&2
fi
git add -A
git commit -m "Auto-commit: $(date +'%Y-%m-%d %H:%M:%S')"
exit 0
Detailed Commit Statistics
Enhanced hook script for detailed commit statistics with accurate line count calculations
#!/usr/bin/env bash
if ! git rev-parse --git-dir > /dev/null 2>&1; then
exit 0
fi
if [ -z "$(git status --porcelain 2>/dev/null)" ]; then
exit 0
fi
FILES_CHANGED=$(git status --porcelain 2>/dev/null | wc -l | xargs)
MODIFIED_FILES=$(git status --porcelain 2>/dev/null | grep '^.M' | wc -l | xargs)
ADDED_FILES=$(git status --porcelain 2>/dev/null | grep '^A' | wc -l | xargs)
DELETED_FILES=$(git status --porcelain 2>/dev/null | grep '^.D' | wc -l | xargs)
if command -v awk &> /dev/null; then
STATS=$(git diff --cached --numstat 2>/dev/null | awk '{insertions+=$1; deletions+=$2} END {print insertions " " deletions}')
read -r INSERTIONS DELETIONS <<< "$STATS"
else
INSERTIONS=0
DELETIONS=0
fi
COMMIT_MSG="Auto-commit: $(date +'%Y-%m-%d %H:%M:%S')"
COMMIT_BODY="Files changed: $FILES_CHANGED
Modified: $MODIFIED_FILES
Added: $ADDED_FILES
Deleted: $DELETED_FILES
Insertions: +$INSERTIONS
Deletions: -$DELETIONS"
git add -A
git commit -m "$COMMIT_MSG" -m "$COMMIT_BODY"
exit 0
Automatic Push to Remote
Enhanced hook script for automatic push to remote repository with error handling
#!/usr/bin/env bash
if ! git rev-parse --git-dir > /dev/null 2>&1; then
exit 0
fi
if [ -z "$(git status --porcelain 2>/dev/null)" ]; then
exit 0
fi
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
git add -A
git commit -m "Auto-commit: $(date +'%Y-%m-%d %H:%M:%S')" -m "Branch: $CURRENT_BRANCH"
if [ "$AUTO_PUSH" = "true" ]; then
echo "📤 Auto-pushing to remote..." >&2
if git push 2>/dev/null; then
echo "✅ Pushed to remote successfully" >&2
else
echo "⚠️ Push failed - commit created locally" >&2
echo "💡 Run 'git push' manually when ready" >&2
fi
fi
exit 0
Troubleshooting
Hook creates commits even when no meaningful changes made
git status --porcelain check shows temp files. Update .gitignore excluding: '.DS_Store', '.swp', 'node_modules/'. Or add file count threshold: 'if [ "$MODIFIED_FILES" -lt 2 ]; then exit 0; fi'. Verify .gitignore patterns match temporary files. Use git status --ignored to check ignored files.
Sensitive files (.env) committed despite pattern detection warnings
Pattern match non-blocking by design. Add hard block: 'if [ "$SENSITIVE_FOUND" = true ]; then exit 1; fi' before git add. Or use git-secrets: 'git secrets --scan' pre-commit. Update .gitignore to exclude sensitive file patterns. Use git-secrets or similar tools for automatic detection.
Auto-commit fails with empty commit message or malformed body
COMMIT_BODY uses cat with EOF delimiter requiring proper quoting. Replace with: 'git commit -m "Auto-commit: $TIMESTAMP" -m "Files: $FILES_CHANGED" -m "Branch: $CURRENT_BRANCH"' avoiding heredoc issues. Verify commit message variables are not empty. Use git commit with multiple -m flags for multi-line messages.
SKIP_AUTO_COMMIT environment variable ignored when set
Variable not exported to subprocess. Use: 'export SKIP_AUTO_COMMIT=true' before Claude session. Or add to shell profile: 'echo "export SKIP_AUTO_COMMIT=true" >> ~/.bashrc'. Verify: 'env | grep SKIP'. Check environment variable is set in correct shell context. Use export command to ensure variable is available to subprocesses.
Statistics show zero insertions/deletions despite file changes
git diff --stat fails on binary files or first commit. Add: '--ignore-all-space --ignore-blank-lines' flags. Or use: 'git diff --numstat | awk "{add+=$1; del+=$2} END {print add, del}"' for accurate counts. Verify files are staged before calculating statistics. Check for binary file detection issues.
Auto-commit fails on detached HEAD state
Hook doesn't check for detached HEAD. Add check: 'if git symbolic-ref -q HEAD > /dev/null 2>&1; then echo "On branch"; else echo "Detached HEAD - skipping commit"; exit 0; fi'. Verify repository is on a valid branch before committing. Use git checkout to switch to a branch if needed.
AUTO_PUSH fails with authentication errors
Git push requires authentication. Configure Git credentials: 'git config --global credential.helper store'. Or use SSH keys: 'ssh-keygen -t ed25519 -C "your@email.com"'. Verify remote URL is correct: 'git remote -v'. Check SSH key is added to Git provider. Use credential helper for HTTPS authentication.
Commit messages don't include expected information
Verify commit message generation logic. Check timestamp format: 'date +"%Y-%m-%d %H:%M:%S"'. Verify branch detection: 'git branch --show-current'. Check file statistics calculation. Use git commit with multiple -m flags for structured commit messages. Verify all variables are properly set before commit creation.
- Features
- Use Cases
- Installation
- Config paths
- Requirements
- Hook Configuration
- Hook Script
- Examples
- Git Auto Commit On Stop Hook Script
- Sensitive File Detection and Skip Control
- Detailed Commit Statistics
- Automatic Push to Remote
- Troubleshooting
- Hook creates commits even when no meaningful changes made
- Sensitive files (.env) committed despite pattern detection warnings
- Auto-commit fails with empty commit message or malformed body
Source citations
Signals
Loading live community signals…
A short, calm digest of reviewed Claude resources. Unsubscribe any time.