Skip to content

Instantly share code, notes, and snippets.

@fry69
Forked from karpathy/add_to_zshrc.sh
Last active October 8, 2024 14:18
Show Gist options
  • Save fry69/4e86172691a30cfb9fb77047026a0d61 to your computer and use it in GitHub Desktop.
Save fry69/4e86172691a30cfb9fb77047026a0d61 to your computer and use it in GitHub Desktop.
Git Commit Message AI
# -----------------------------------------------------------------------------
# Enhanced AI-powered Git Commit Function with Optimizations and UX Improvements
# Add this to your ~/.bashrc or ~/.zshrc to utilize the `gcm` command.
# Features:
# 1) Validates required dependencies.
# 2) Checks for staged changes.
# 3) Allows customizable exclusion patterns.
# 4) Generates commit messages using an LLM with an extended prompt.
# 5) Provides user-friendly prompts with color-coded messages.
# 6) Handles errors gracefully with informative feedback.
# Rewritten by o1-mini on 2024-09-18, see reply transcript here ->
# https://gist.github.com/fry69/06379fd3deb8c1db960b0270420087b9
# -----------------------------------------------------------------------------
gcm2 () {
# Define color codes for enhanced readability
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Check for required commands
if ! command -v git &> /dev/null; then
echo -e "${RED}Error: git is not installed. Please install git to use the gcm function.${NC}"
return 1
fi
if ! command -v llm &> /dev/null; then
echo -e "${RED}Error: llm CLI tool is not installed. Please install it from https://llm.datasette.io/en/stable/${NC}"
return 1
fi
# Check for staged changes
if git diff --cached --quiet; then
echo -e "${YELLOW}No staged changes to commit.${NC}"
return 1
fi
# Define exclusion patterns
GCM_EXCLUDED_PATTERNS=( ':!pnpm-lock.yaml' ':!package-lock.json' ':!yarn.lock' )
if [ -n "$GCM_EXCLUDED_PATTERNS_USER" ]; then
IFS=';' read -r -a USER_EXCLUSIONS <<< "$GCM_EXCLUDED_PATTERNS_USER"
GCM_EXCLUDED_PATTERNS+=( "${USER_EXCLUSIONS[@]}" )
fi
# Function to generate commit message
generate_commit_message() {
git diff --cached -- . "${GCM_EXCLUDED_PATTERNS[@]}" | llm --no-log --model "${GCM_LLM_MODEL:-claude-3-haiku}" --system "
You are a helpful assistant that generates concise, one-line Git commit messages based on the provided diffs.
Below is a diff of all staged changes, derived from the command:
\`\`\`
git diff --cached
\`\`\`
Please generate a clear, concise, and descriptive one-line commit message that appropriately categorizes the changes using one of the following prefixes:
- **feat:** new feature for the user
- **fix:** bug fix
- **docs:** documentation changes
- **style:** code style changes (e.g., formatting, missing semi-colons)
- **refactor:** code changes that neither fix a bug nor add a feature
- **perf:** performance improvements
- **test:** adding or modifying tests
- **ci:** changes to CI configuration files and scripts
- **build:** changes that affect the build system or external dependencies
- **chore:** maintenance tasks that do not modify src or test files
- **revert:** to revert previous commits
Ensure the commit message:
- Starts with the appropriate prefix.
- Is in the imperative mood (e.g., \"Add feature\" not \"Added feature\" or \"Adding feature\").
- Does not exceed 72 characters.
Reply only with the one-line commit message, without any additional text, explanations, or line breaks."
}
# Function to read user input compatibly with both Bash and Zsh
read_input () {
prompt="$1"
if [ -n "$ZSH_VERSION" ] || [ -n "$BASH_VERSION" ]; then
read -p "$prompt" -r REPLY
else
# Fallback for other shells
echo -n "$prompt"
IFS= read -r REPLY
fi
}
# Log file
GCM_LOG_FILE="${GCM_LOG_FILE:-"$HOME/.gcm.log"}"
# Main script
echo -e "${CYAN}Generating AI-powered commit message...${NC}"
echo "$(date) - Generating commit message..." >> "$GCM_LOG_FILE"
commit_message=$(generate_commit_message 2>> "$GCM_LOG_FILE")
# Check if commit_message was successfully generated
if [ $? -ne 0 ] || [ -z "$commit_message" ]; then
echo -e "${RED}Error: Failed to generate commit message using LLM.${NC}"
echo "$(date) - Failed to generate commit message." >> "$GCM_LOG_FILE"
return 1
fi
while true; do
echo -e "\n${YELLOW}Proposed commit message:${NC}"
echo -e "${GREEN}$commit_message${NC}"
read_input "Do you want to (a)ccept, (e)dit, (r)egenerate, (m)anual, or (c)ancel? [a/e/r/m/c]: "
choice=$REPLY
case "$choice" in
a|A )
# Escape commit message
escaped_message=$(printf '%q' "$commit_message")
if git commit -m "$escaped_message"; then
echo -e "${GREEN}✔ Changes committed successfully!${NC}"
echo "$(date) - Committed with message: $commit_message" >> "$GCM_LOG_FILE"
return 0
else
echo -e "${RED}✖ Commit failed. Please check your changes and try again.${NC}"
echo "$(date) - Commit failed." >> "$GCM_LOG_FILE"
return 1
fi
;;
e|E )
read_input "Enter your commit message: "
commit_message=$REPLY
if [ -n "$commit_message" ]; then
escaped_message=$(printf '%q' "$commit_message")
if git commit -m "$escaped_message"; then
echo -e "${GREEN}✔ Changes committed successfully with your message!${NC}"
echo "$(date) - Committed with user-provided message: $commit_message" >> "$GCM_LOG_FILE"
return 0
else
echo -e "${RED}✖ Commit failed. Please check your message and try again.${NC}"
echo "$(date) - Commit failed with user message." >> "$GCM_LOG_FILE"
return 1
fi
else
echo -e "${RED}✖ Empty commit message. Please try again.${NC}"
fi
;;
r|R )
echo -e "${CYAN}Regenerating commit message...${NC}"
echo "$(date) - Regenerating commit message..." >> "$GCM_LOG_FILE"
commit_message=$(generate_commit_message 2>> "$GCM_LOG_FILE")
if [ $? -ne 0 ] || [ -z "$commit_message" ]; then
echo -e "${RED}Error: Failed to regenerate commit message using LLM.${NC}"
echo "$(date) - Failed to regenerate commit message." >> "$GCM_LOG_FILE"
return 1
fi
;;
m|M )
echo -e "${CYAN}Opening your default editor to compose a commit message...${NC}"
git commit
return $?
;;
c|C )
echo -e "${YELLOW}Commit cancelled.${NC}"
echo "$(date) - Commit cancelled by user." >> "$GCM_LOG_FILE"
return 1
;;
* )
echo -e "${RED}Invalid choice. Please try again.${NC}"
;;
esac
done
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment