#!/usr/bin/env bash # Conventional commit helper # Usage: gc [type] [message] [-s scope] [-b] [-B body] # gc (interactive mode) set -o errexit set -o nounset TYPES="feat fix docs style refactor test chore perf ci build" usage() { echo "Usage: gc [type] [message] [-s scope] [-b] [-B body]" echo " gc (interactive mode)" echo "" echo "Options:" echo " -s, --scope Scope of the change" echo " -b, --breaking Mark as breaking change (!)" echo " -B, --body Commit body (longer description)" echo "" echo "Types: $TYPES" echo "" echo "Examples:" echo " gc feat 'add user auth'" echo " gc fix 'resolve crash' -s api # fix(api): resolve crash" echo " gc feat 'new api' -b # feat!: new api" echo " gc feat 'new api' -s auth -b # feat(auth)!: new api" echo " gc feat 'big change' -B 'Details here'" exit 1 } build_message() { local type="$1" local scope="$2" local breaking="$3" local msg="$4" local body="$5" local commit_msg="$type" if [ -n "$scope" ]; then commit_msg+="($scope)" fi if [ "$breaking" = "true" ]; then commit_msg+="!" fi commit_msg+=": $msg" if [ -n "$body" ]; then commit_msg+=$'\n\n'"$body" fi echo "$commit_msg" } # Interactive mode if no args if [ $# -eq 0 ]; then echo "Types: $TYPES" printf "Type: " read -r type printf "Scope (optional): " read -r scope printf "Breaking change? [y/N]: " read -r breaking_input printf "Message: " read -r msg printf "Body (optional, enter for none): " read -r body breaking="false" if [[ $breaking_input =~ ^[Yy] ]]; then breaking="true" fi commit_msg=$(build_message "$type" "$scope" "$breaking" "$msg" "$body") git commit -m "$commit_msg" exit 0 fi # Parse arguments type="" msg="" scope="" breaking="false" body="" while [ $# -gt 0 ]; do case "$1" in -s | --scope) scope="$2" shift 2 ;; -b | --breaking) breaking="true" shift ;; -B | --body) body="$2" shift 2 ;; -h | --help) usage ;; *) if [ -z "$type" ]; then type="$1" else msg="$1" fi shift ;; esac done # Validate type if ! echo "$TYPES" | grep -qw "$type"; then echo "Invalid type: $type" echo "Valid types: $TYPES" exit 1 fi if [ -z "$msg" ]; then echo "Message required" usage fi commit_msg=$(build_message "$type" "$scope" "$breaking" "$msg" "$body") git commit -m "$commit_msg"