Added comprehensive safety features to prevent accidental commits and ensure user review of all generated commit messages: Safety enhancements: - Added mandatory review warning with clear visual indicators - Implemented double confirmation for all commit operations - Added option to regenerate commit message if not satisfied - Shows edited message for review after modifications - Added explicit "no auto-push" reminders after commits - Created ~/.claude-commit.conf for safety preferences Documentation updates: - Updated CLAUDE.md with clear commit workflow for Claude Code - Added safety features section to tool documentation - Clarified that manual review is always required - Documented the review-approve-commit-push workflow These changes ensure users always have full control over commit messages and prevent accidental commits or pushes without explicit approval.
174 lines
No EOL
5.5 KiB
Bash
Executable file
174 lines
No EOL
5.5 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
# Claude Commit Message Generator - Global Version
|
|
# Automatically generates Conventional Commit messages using git diff
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Check if we're in a git repository
|
|
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
echo -e "${RED}Not in a git repository${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Check if there are changes to commit
|
|
if [[ -z $(git status -s) ]]; then
|
|
echo -e "${RED}No changes to commit${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Get the diff of staged changes (or all changes if nothing staged)
|
|
if [[ -n $(git diff --cached --name-only) ]]; then
|
|
DIFF=$(git diff --cached)
|
|
FILES=$(git diff --cached --name-only)
|
|
echo -e "${GREEN}Analyzing staged changes...${NC}"
|
|
else
|
|
DIFF=$(git diff)
|
|
FILES=$(git diff --name-only)
|
|
echo -e "${YELLOW}No staged changes. Analyzing all modified files...${NC}"
|
|
echo -e "${YELLOW}Run 'git add' first to stage specific changes${NC}"
|
|
fi
|
|
|
|
# Get project name from git remote or directory name
|
|
PROJECT_NAME=$(basename "$(git rev-parse --show-toplevel)")
|
|
REMOTE_URL=$(git config --get remote.origin.url 2>/dev/null)
|
|
if [[ -n "$REMOTE_URL" ]]; then
|
|
PROJECT_NAME=$(basename -s .git "$REMOTE_URL")
|
|
fi
|
|
|
|
# Create a prompt for Claude
|
|
PROMPT="Based on the following git diff from the '$PROJECT_NAME' project, generate a Conventional Commit message.
|
|
|
|
REQUIREMENTS:
|
|
1. Use Conventional Commit format: <type>(<scope>): <description>
|
|
2. Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore
|
|
3. Keep first line under 72 characters
|
|
4. Use imperative mood (e.g., 'add' not 'added')
|
|
5. Include a detailed body explaining the purpose and impact
|
|
6. Note any breaking changes with 'BREAKING CHANGE:' prefix
|
|
7. Reference any issue numbers if apparent from the code
|
|
|
|
FILES CHANGED:
|
|
$FILES
|
|
|
|
GIT DIFF (showing first 500 lines):
|
|
$(echo "$DIFF" | head -n 500)
|
|
|
|
Generate ONLY the commit message, no explanations or markdown formatting."
|
|
|
|
# Call Claude API (using claude CLI)
|
|
echo -e "${GREEN}Generating commit message with Claude...${NC}"
|
|
|
|
# Save the prompt to a temporary file to avoid shell escaping issues
|
|
TEMP_PROMPT=$(mktemp)
|
|
echo "$PROMPT" > "$TEMP_PROMPT"
|
|
|
|
# Generate the commit message
|
|
COMMIT_MSG=$(claude code --no-markdown < "$TEMP_PROMPT" 2>/dev/null)
|
|
|
|
# Clean up temp file
|
|
rm "$TEMP_PROMPT"
|
|
|
|
# Check if message was generated
|
|
if [[ -z "$COMMIT_MSG" ]]; then
|
|
echo -e "${RED}Failed to generate commit message${NC}"
|
|
echo "Falling back to standard git commit..."
|
|
git commit
|
|
exit 1
|
|
fi
|
|
|
|
# Display the generated message
|
|
echo ""
|
|
echo -e "${GREEN}Generated commit message:${NC}"
|
|
echo "========================================"
|
|
echo "$COMMIT_MSG"
|
|
echo "========================================"
|
|
echo ""
|
|
|
|
# ALWAYS require explicit review
|
|
echo -e "${YELLOW}⚠️ REVIEW REQUIRED${NC}"
|
|
echo -e "${YELLOW}Please review the commit message above carefully.${NC}"
|
|
echo ""
|
|
echo -e "${YELLOW}What would you like to do?${NC}"
|
|
echo " ${GREEN}1)${NC} Use this message AS-IS"
|
|
echo " ${GREEN}2)${NC} EDIT this message first"
|
|
echo " ${GREEN}3)${NC} Generate a NEW message"
|
|
echo " ${RED}4)${NC} CANCEL (no commit)"
|
|
echo ""
|
|
read -p "Your choice [1-4]: " choice
|
|
|
|
case $choice in
|
|
1)
|
|
# Final confirmation before committing
|
|
echo -e "${YELLOW}Ready to commit with the message above.${NC}"
|
|
read -p "Confirm commit? [y/N]: " confirm
|
|
|
|
if [[ "$confirm" =~ ^[Yy]$ ]]; then
|
|
# Stage all changes if nothing is staged
|
|
if [[ -z $(git diff --cached --name-only) ]]; then
|
|
git add -A
|
|
fi
|
|
# Commit with the generated message
|
|
git commit -m "$COMMIT_MSG"
|
|
echo -e "${GREEN}✓ Committed successfully${NC}"
|
|
echo -e "${YELLOW}📝 Note: Changes are committed locally only${NC}"
|
|
echo -e "${YELLOW} Run 'git push' manually when ready to push${NC}"
|
|
else
|
|
echo -e "${YELLOW}Commit cancelled${NC}"
|
|
exit 0
|
|
fi
|
|
;;
|
|
2)
|
|
# Save message to temp file and open in editor
|
|
TEMP_MSG=$(mktemp)
|
|
echo "$COMMIT_MSG" > "$TEMP_MSG"
|
|
|
|
echo -e "${YELLOW}Opening editor to modify the message...${NC}"
|
|
${EDITOR:-vim} "$TEMP_MSG"
|
|
|
|
# Show the edited message
|
|
echo ""
|
|
echo -e "${GREEN}Edited commit message:${NC}"
|
|
echo "========================================"
|
|
cat "$TEMP_MSG"
|
|
echo "========================================"
|
|
echo ""
|
|
|
|
read -p "Commit with this edited message? [y/N]: " confirm
|
|
|
|
if [[ "$confirm" =~ ^[Yy]$ ]]; then
|
|
# Stage all changes if nothing is staged
|
|
if [[ -z $(git diff --cached --name-only) ]]; then
|
|
git add -A
|
|
fi
|
|
|
|
# Commit with edited message
|
|
git commit -F "$TEMP_MSG"
|
|
rm "$TEMP_MSG"
|
|
echo -e "${GREEN}✓ Committed with edited message${NC}"
|
|
echo -e "${YELLOW}📝 Note: Changes are committed locally only${NC}"
|
|
echo -e "${YELLOW} Run 'git push' manually when ready to push${NC}"
|
|
else
|
|
rm "$TEMP_MSG"
|
|
echo -e "${YELLOW}Commit cancelled${NC}"
|
|
exit 0
|
|
fi
|
|
;;
|
|
3)
|
|
echo -e "${YELLOW}Regenerating commit message...${NC}"
|
|
# Re-run the script
|
|
exec "$0" "$@"
|
|
;;
|
|
4)
|
|
echo -e "${RED}✗ Commit cancelled by user${NC}"
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo -e "${RED}Invalid choice. Commit cancelled${NC}"
|
|
exit 1
|
|
;;
|
|
esac |