Modify gp/gp_improved
All checks were successful
Build-Test-Publish / build (linux/arm64) (push) Successful in 25s
Build-Test-Publish / build (linux/amd64) (push) Successful in 46s
Build-Test-Publish / test-install-from-scratch (linux/amd64) (push) Successful in 7s
Build-Test-Publish / test-install-from-scratch (linux/arm64) (push) Successful in 8s
All checks were successful
Build-Test-Publish / build (linux/arm64) (push) Successful in 25s
Build-Test-Publish / build (linux/amd64) (push) Successful in 46s
Build-Test-Publish / test-install-from-scratch (linux/amd64) (push) Successful in 7s
Build-Test-Publish / test-install-from-scratch (linux/arm64) (push) Successful in 8s
This commit is contained in:
parent
31be41e21d
commit
2eec3ba2ad
91
gp/IMPROVEMENTS.md
Normal file
91
gp/IMPROVEMENTS.md
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
# GP Script Improvements
|
||||||
|
|
||||||
|
## Original Script Issues
|
||||||
|
|
||||||
|
The original `gp` script had several limitations and potential issues:
|
||||||
|
|
||||||
|
1. **No error handling** - Script could fail silently or in unexpected ways
|
||||||
|
2. **Unsafe operations** - Always commits and pushes without confirmation
|
||||||
|
3. **Poor commit messages** - Generated from diff first line, often meaningless
|
||||||
|
4. **No flexibility** - Hard-coded to push to `main` branch
|
||||||
|
5. **No dry-run mode** - No way to preview what would happen
|
||||||
|
6. **Limited functionality** - No help, version, or autocomplete support
|
||||||
|
7. **Poor user experience** - No colored output or informative messages
|
||||||
|
|
||||||
|
## Improvements Made
|
||||||
|
|
||||||
|
### 1. Safety and Error Handling
|
||||||
|
- **Strict error handling** with `set -euo pipefail`
|
||||||
|
- **Git repository validation** before any operations
|
||||||
|
- **Change detection** to avoid empty commits
|
||||||
|
- **User confirmation** before committing (unless `--force` used)
|
||||||
|
- **Proper error messages** with colored output
|
||||||
|
|
||||||
|
### 2. Enhanced Functionality
|
||||||
|
- **Dry-run mode** (`--dry-run`/`-n`) to preview changes
|
||||||
|
- **Custom commit messages** - optional argument overrides auto-generation
|
||||||
|
- **Branch selection** (`--branch`/`-b`) to push to any branch
|
||||||
|
- **Add-all option** (`--add-all`/`-a`) to include untracked files
|
||||||
|
- **Force mode** (`--force`/`-f`) to skip confirmations
|
||||||
|
|
||||||
|
### 3. Smart Commit Message Generation
|
||||||
|
- **File type detection** - recognizes source, config, docs, and test files
|
||||||
|
- **Change type analysis** - detects additions, modifications, deletions
|
||||||
|
- **Conventional commit style** - uses prefixes like `feat:`, `docs:`, `test:`
|
||||||
|
- **Intelligent descriptions** - better context than original script
|
||||||
|
|
||||||
|
### 4. User Experience
|
||||||
|
- **Colored output** - different colors for info, warnings, errors, success
|
||||||
|
- **Comprehensive help** - detailed usage information and examples
|
||||||
|
- **Status display** - shows current branch, repository, and changes
|
||||||
|
- **Progress feedback** - clear indication of what's happening
|
||||||
|
|
||||||
|
### 5. Integration Features
|
||||||
|
- **Version command** - reports script version
|
||||||
|
- **Autocomplete support** - bash completion for options
|
||||||
|
- **Standard CLI conventions** - follows common command-line patterns
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
### Basic Usage
|
||||||
|
```bash
|
||||||
|
gp # Auto-generate commit message and push
|
||||||
|
gp "Fix parser bug" # Use custom commit message
|
||||||
|
```
|
||||||
|
|
||||||
|
### Advanced Usage
|
||||||
|
```bash
|
||||||
|
gp --dry-run # Preview what would be committed
|
||||||
|
gp --add-all # Include untracked files
|
||||||
|
gp --branch develop # Push to develop branch
|
||||||
|
gp --force "Emergency fix" # Skip confirmation prompt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Information Commands
|
||||||
|
```bash
|
||||||
|
gp --help # Show help
|
||||||
|
gp version # Show version
|
||||||
|
gp autocomplete # Show completion options
|
||||||
|
```
|
||||||
|
|
||||||
|
## Benefits
|
||||||
|
|
||||||
|
1. **Safer** - Prevents accidental commits and pushes
|
||||||
|
2. **More flexible** - Works with different workflows and branching strategies
|
||||||
|
3. **Better commit history** - Generates meaningful commit messages
|
||||||
|
4. **User-friendly** - Clear feedback and error messages
|
||||||
|
5. **Professional** - Follows CLI best practices and conventions
|
||||||
|
6. **Maintainable** - Well-structured code with proper error handling
|
||||||
|
|
||||||
|
## Backward Compatibility
|
||||||
|
|
||||||
|
The improved script maintains backward compatibility:
|
||||||
|
- Running `gp` without arguments still auto-generates a commit message and pushes
|
||||||
|
- The basic workflow is unchanged
|
||||||
|
- New features are opt-in through command-line flags
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
1. Replace the original `gp` script with `gp_improved`
|
||||||
|
2. Ensure it's executable: `chmod +x gp`
|
||||||
|
3. The script works from any directory within a git repository
|
322
gp/gp_improved
Executable file
322
gp/gp_improved
Executable file
@ -0,0 +1,322 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# gp - Git Push with AI-generated commit messages
|
||||||
|
# Improved version with better error handling, safety checks, and functionality
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Function to print colored output
|
||||||
|
print_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
||||||
|
print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
||||||
|
print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
|
||||||
|
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||||
|
|
||||||
|
# Function to show help
|
||||||
|
show_help() {
|
||||||
|
cat << 'EOF'
|
||||||
|
gp - Git Push with smart commit messages
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
gp [options] [message]
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
-h, --help Show this help message
|
||||||
|
-n, --dry-run Show what would be committed without actually doing it
|
||||||
|
-f, --force Skip safety checks (use with caution)
|
||||||
|
-b, --branch Specify branch to push to (default: current branch)
|
||||||
|
-a, --add-all Add all files including untracked (default: only staged + modified)
|
||||||
|
|
||||||
|
ARGUMENTS:
|
||||||
|
message Optional custom commit message (overrides auto-generation)
|
||||||
|
|
||||||
|
EXAMPLES:
|
||||||
|
gp # Auto-generate commit message and push
|
||||||
|
gp "Fix bug in parser" # Use custom commit message
|
||||||
|
gp --dry-run # Preview what would be committed
|
||||||
|
gp -b develop # Push to develop branch instead of current
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to generate commit message based on changes
|
||||||
|
generate_commit_message() {
|
||||||
|
local files_changed=$(git diff --cached --name-only)
|
||||||
|
local files_count=$(echo "$files_changed" | wc -l)
|
||||||
|
|
||||||
|
if [ -z "$files_changed" ]; then
|
||||||
|
files_changed=$(git diff --name-only)
|
||||||
|
files_count=$(echo "$files_changed" | wc -l)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If add-all is enabled, also include untracked files
|
||||||
|
if [ "$ADD_ALL" = true ] && [ -z "$files_changed" ]; then
|
||||||
|
files_changed=$(git ls-files --others --exclude-standard)
|
||||||
|
files_count=$(echo "$files_changed" | wc -l)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$files_changed" ]; then
|
||||||
|
echo "No changes to commit"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate smart commit message based on file types and changes
|
||||||
|
local has_source_files=false
|
||||||
|
local has_config_files=false
|
||||||
|
local has_docs=false
|
||||||
|
local has_tests=false
|
||||||
|
local message=""
|
||||||
|
|
||||||
|
while IFS= read -r file; do
|
||||||
|
[ -z "$file" ] && continue
|
||||||
|
|
||||||
|
case "$file" in
|
||||||
|
*.cpp|*.hpp|*.c|*.h|*.js|*.ts|*.py|*.go|*.rs|*.java)
|
||||||
|
has_source_files=true
|
||||||
|
;;
|
||||||
|
*.json|*.yml|*.yaml|*.toml|*.ini|*.conf|CMakeLists.txt|Makefile)
|
||||||
|
has_config_files=true
|
||||||
|
;;
|
||||||
|
*.md|*.txt|*.rst|docs/*|README*)
|
||||||
|
has_docs=true
|
||||||
|
;;
|
||||||
|
*test*|*spec*|test/*|tests/*)
|
||||||
|
has_tests=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done <<< "$files_changed"
|
||||||
|
|
||||||
|
# Create descriptive commit message
|
||||||
|
if [ "$files_count" -eq 1 ]; then
|
||||||
|
local single_file=$(echo "$files_changed" | head -1)
|
||||||
|
local change_type=$(git diff --cached --name-status "$single_file" 2>/dev/null || git diff --name-status "$single_file")
|
||||||
|
case "${change_type:0:1}" in
|
||||||
|
A) message="Add $single_file" ;;
|
||||||
|
M) message="Update $single_file" ;;
|
||||||
|
D) message="Remove $single_file" ;;
|
||||||
|
R) message="Rename $single_file" ;;
|
||||||
|
*) message="Modify $single_file" ;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
local prefix=""
|
||||||
|
if $has_tests; then
|
||||||
|
prefix="test: "
|
||||||
|
elif $has_docs; then
|
||||||
|
prefix="docs: "
|
||||||
|
elif $has_config_files; then
|
||||||
|
prefix="config: "
|
||||||
|
elif $has_source_files; then
|
||||||
|
prefix="feat: "
|
||||||
|
fi
|
||||||
|
|
||||||
|
message="${prefix}Update $files_count files"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$message"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check if we're in a git repository
|
||||||
|
check_git_repo() {
|
||||||
|
if ! git rev-parse --git-dir >/dev/null 2>&1; then
|
||||||
|
print_error "Not in a git repository"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check for uncommitted changes
|
||||||
|
check_for_changes() {
|
||||||
|
if git diff --cached --quiet && git diff --quiet; then
|
||||||
|
if [ "$ADD_ALL" = false ]; then
|
||||||
|
print_warning "No staged changes found"
|
||||||
|
print_info "Use 'gp -a' to add all files, or stage changes first with 'git add'"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to show what would be committed
|
||||||
|
show_status() {
|
||||||
|
print_info "Current branch: $(git branch --show-current)"
|
||||||
|
print_info "Repository: $(git remote get-url origin 2>/dev/null || echo 'No remote')"
|
||||||
|
echo
|
||||||
|
|
||||||
|
if git diff --cached --quiet; then
|
||||||
|
print_info "Staged changes: None"
|
||||||
|
if ! git diff --quiet; then
|
||||||
|
print_info "Modified files (unstaged):"
|
||||||
|
git diff --name-only | sed 's/^/ /'
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
print_info "Staged changes:"
|
||||||
|
git diff --cached --name-only | sed 's/^/ /'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$ADD_ALL" = true ]; then
|
||||||
|
local untracked=$(git ls-files --others --exclude-standard)
|
||||||
|
if [ -n "$untracked" ]; then
|
||||||
|
print_info "Untracked files (will be added):"
|
||||||
|
echo "$untracked" | sed 's/^/ /'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to perform the actual commit and push
|
||||||
|
do_commit_and_push() {
|
||||||
|
local commit_msg="$1"
|
||||||
|
local target_branch="$2"
|
||||||
|
|
||||||
|
# Add files if requested
|
||||||
|
if [ "$ADD_ALL" = true ]; then
|
||||||
|
print_info "Adding all files..."
|
||||||
|
git add .
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Commit
|
||||||
|
print_info "Committing with message: '$commit_msg'"
|
||||||
|
git commit -m "$commit_msg"
|
||||||
|
|
||||||
|
# Push
|
||||||
|
print_info "Pushing to $target_branch..."
|
||||||
|
if git push origin "$target_branch"; then
|
||||||
|
print_success "Successfully pushed to origin/$target_branch"
|
||||||
|
else
|
||||||
|
print_error "Failed to push to origin/$target_branch"
|
||||||
|
print_info "You may need to pull first: git pull origin $target_branch"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Default values
|
||||||
|
DRY_RUN=false
|
||||||
|
FORCE=false
|
||||||
|
ADD_ALL=false
|
||||||
|
CUSTOM_MESSAGE=""
|
||||||
|
TARGET_BRANCH=""
|
||||||
|
|
||||||
|
# Handle special commands first
|
||||||
|
case "${1:-}" in
|
||||||
|
autocomplete)
|
||||||
|
shift
|
||||||
|
autocomplete "$@"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
version)
|
||||||
|
echo "gp version 2.0.0"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Parse command line arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-h|--help)
|
||||||
|
show_help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
-n|--dry-run)
|
||||||
|
DRY_RUN=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-f|--force)
|
||||||
|
FORCE=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-a|--add-all)
|
||||||
|
ADD_ALL=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-b|--branch)
|
||||||
|
TARGET_BRANCH="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-*)
|
||||||
|
print_error "Unknown option: $1"
|
||||||
|
echo "Use 'gp --help' for usage information"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
CUSTOM_MESSAGE="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Main execution
|
||||||
|
main() {
|
||||||
|
# Safety checks
|
||||||
|
check_git_repo
|
||||||
|
|
||||||
|
# Set target branch if not specified
|
||||||
|
if [ -z "$TARGET_BRANCH" ]; then
|
||||||
|
TARGET_BRANCH=$(git branch --show-current)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for changes
|
||||||
|
check_for_changes
|
||||||
|
|
||||||
|
# Show current status
|
||||||
|
show_status
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Generate or use custom commit message
|
||||||
|
if [ -n "$CUSTOM_MESSAGE" ]; then
|
||||||
|
commit_message="$CUSTOM_MESSAGE"
|
||||||
|
print_info "Using custom commit message: '$commit_message'"
|
||||||
|
else
|
||||||
|
print_info "Generating commit message..."
|
||||||
|
commit_message=$(generate_commit_message)
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
print_error "Failed to generate commit message"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
print_info "Generated commit message: '$commit_message'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Dry run mode
|
||||||
|
if [ "$DRY_RUN" = true ]; then
|
||||||
|
print_warning "DRY RUN MODE - No changes will be made"
|
||||||
|
print_info "Would commit with message: '$commit_message'"
|
||||||
|
print_info "Would push to: origin/$TARGET_BRANCH"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Safety confirmation (unless forced)
|
||||||
|
if [ "$FORCE" = false ]; then
|
||||||
|
echo
|
||||||
|
read -p "Proceed with commit and push? [y/N] " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
print_info "Aborted by user"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Execute the commit and push
|
||||||
|
do_commit_and_push "$commit_message" "$TARGET_BRANCH"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Autocomplete function for bash
|
||||||
|
autocomplete() {
|
||||||
|
local args=("$@")
|
||||||
|
if [ ${#args[@]} -eq 0 ]; then
|
||||||
|
echo "--help"
|
||||||
|
echo "--dry-run"
|
||||||
|
echo "--force"
|
||||||
|
echo "--add-all"
|
||||||
|
echo "--branch"
|
||||||
|
echo "-h"
|
||||||
|
echo "-n"
|
||||||
|
echo "-f"
|
||||||
|
echo "-a"
|
||||||
|
echo "-b"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run main function
|
||||||
|
main "$@"
|
Loading…
x
Reference in New Issue
Block a user