Uncategorized

Streamlining Small Fixes with Git Aliases & GitHub CLI

Streamlining Small Fixes with Git Aliases & GitHub CLI

A Faster Workflow for Quick Edits at Ecenica

If you’re making small edits to your codebase, the traditional Git workflow can feel unnecessarily heavy. Switching branches, creating feature branches, pushing, opening PRs, reviewing, merging…it’s a lot of ritual for updating a README or fixing a typo.

At Ecenica, we focus on speed and simplicity. That’s why we redesigned our workflow for small fixes using two simple Git aliases powered by the GitHub CLI.

The Problem

For tiny edits like fixing spelling, updating docs, or tweaking a config file, the standard workflow pulls you into a long sequence:

  1. Switch to develop
  2. Pull latest
  3. Create feature branch
  4. Edit files
  5. Stage changes
  6. Commit
  7. Push
  8. Open PR
  9. Review
  10. Merge
  11. Delete branch
  12. Switch back
  13. Pull updates

That’s a lot of steps for a one-line fix.

The Solution: Two Git Aliases That Do Everything

By combining Git + GitHub CLI + GitHub Copilot (optional), we condensed the entire flow into:

git start

git finish

Just two commands.

Step 1 – Create Your Git Tools Directory

mkdir -p ~/.git-tools

Step 2 – Create git-start

Create the file:

nano ~/.git-tools/git-start

Paste:

#!/usr/bin/env bash
set -euo pipefail

# -------------------------------------------------------
# git start — Create a properly named feature/fix branch
# Supports:
#    git start feat/login-page
#    git start feat login-page
#    git start fix bug-123
# -------------------------------------------------------

# --- Normalize input ---
# Convert "feat/foo-bar" → ("feat" "foo-bar")
if [[ $# -eq 1 && "$1" == */* ]]; then
  TYPE_PART="${1%%/*}"
  DESC_PART="${1#*/}"
  set -- "$TYPE_PART" "$DESC_PART"
fi

# --- Validate argument count ---
if [[ $# -lt 2 ]]; then
  echo "❌ Usage:"
  echo "   git start <type> <description>"
  echo "   git start <type>/<description>"
  echo
  echo "Valid types: feat, fix, docs, style, refactor, test, chore"
  exit 1
fi

TYPE="$1"
DESC="$2"

# --- Validate branch type ---
VALID_TYPES="feat fix docs style refactor test chore"
if ! echo "$VALID_TYPES" | grep -qw "$TYPE"; then
  echo "❌ Invalid branch type: '$TYPE'"
  echo "Valid types: $VALID_TYPES"
  exit 1
fi

# --- Sanitize description ---
# lowercase + replace spaces with hyphens
DESC=$(echo "$DESC" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')

BRANCH="${TYPE}/${DESC}"

# --- Ensure we're on develop/main before branching ---
CURRENT_BRANCH=$(git branch --show-current)
if [[ "$CURRENT_BRANCH" != "develop" && "$CURRENT_BRANCH" != "main" ]]; then
  echo "⚠️  You are on '$CURRENT_BRANCH'"
  read -rp "Switch to 'develop' before creating a branch? (Y/n) " REPLY
  if [[ -z "$REPLY" || "$REPLY" =~ ^[Yy]$ ]]; then
    git checkout develop
    git pull --rebase
  else
    echo "❌ Aborted."
    exit 1
  fi
fi

# --- Create the branch ---
echo "🌱 Creating branch: $BRANCH"
git checkout -b "$BRANCH"

echo "⬆️  Pushing upstream..."
git push -u origin "$BRANCH"

echo "✅ Branch ready!"
echo "   → $BRANCH"
echo "   You can now begin committing."

Make executable:

chmod +x ~/.git-tools/git-start

Register alias:

git config --global alias.start '!~/.git-tools/git-start'

Step 3 – Create git-finish

Create:

nano ~/.git-tools/git-finish

Paste:

#!/usr/bin/env bash

COMMIT_MSG=""

# ---- Parse flags ----
while [ "$#" -gt 0 ]; do
  case "$1" in
    -m|--message)
      COMMIT_MSG="$2"
      shift
      ;;
    *)
      echo "❌ Unknown option: $1"
      echo "Usage: git finish [-m message]"
      exit 1
      ;;
  esac
  shift
done

# ---- Dependency check ----
if ! command -v gh >/dev/null 2>&1; then
  echo "⚠️ GitHub CLI missing — install with: brew install gh"
  exit 1
fi

CURRENT_BRANCH=$(git branch --show-current) || exit 1

# ---- Branch format check ----
if ! echo "$CURRENT_BRANCH" | grep -qE '^(fix|feat|docs|style|refactor|test|chore)/'; then
  echo "⚠️ Warning: Branch does not follow conventional format (type/description)"
  echo "Current branch: $CURRENT_BRANCH"
  read -p "Continue anyway? (y/N) " -n 1 -r
  echo
  [[ ! $REPLY =~ ^[Yy]$ ]] && exit 1
fi

# ---- Check for changes ----
if git diff-index --quiet HEAD --; then
  echo "✨ Nothing to commit — working tree clean"
  echo "📖 Opening existing PR..."
else
  # ---- Generate commit message if needed ----
  if [ -z "$COMMIT_MSG" ]; then
    if command -v copilot >/dev/null 2>&1; then
      echo "🧠 Generating commit message with Copilot..."
      COMMIT_MSG=$(
        copilot \
          -p "suggest a conventional commit message for these git changes" \
          --allow-all-tools 2>/dev/null |
          grep -E '^(feat|fix|docs|style|refactor|test|chore):' |
          head -1
      )

      [ -z "$COMMIT_MSG" ] && COMMIT_MSG="chore: update"

      echo "💬 Generated: $COMMIT_MSG"
    else
      echo "⚠️ Copilot CLI not installed — using default commit message."
      BRANCH_TYPE=$(echo "$CURRENT_BRANCH" | cut -d'/' -f1)
      COMMIT_MSG="${BRANCH_TYPE}: update"
    fi
  fi

  git add -A &&
  git commit -m "$COMMIT_MSG" &&
  git push -u origin "$CURRENT_BRANCH" || exit 1
fi

# ---- PR handling ----
if gh pr view &>/dev/null; then
  echo "📖 PR already exists — opening..."
else
  echo "📝 Creating PR..."
  gh pr create --base develop --fill || exit 1
fi

read -p "Press Enter to open PR..."
gh pr view --web

read -p "Press Enter after reviewing to merge..."
gh pr merge --squash --delete-branch

git checkout develop &&
git pull &&
echo "✅ Merged and back on develop!"

Make executable:

chmod +x ~/.git-tools/git-finish

Register alias:

git config --global alias.finish '!~/.git-tools/git-finish'

Usage

git start fix readme-typo
git finish

What Happens Behind the Scenes

When you run git finish:

  1. Branch validation — Checks if your branch follows conventional format (type/description)
  2. Smart commit handling — If working tree is clean, skips commit and goes straight to PR
  3. Intelligent commit message generation — If you don’t provide a message with -m, Copilot analyses your changes using programmatic mode (copilot -p) and suggests an appropriate conventional commit message. Falls back to extracting the type from your branch name if Copilot is unavailable.
  4. Automatic staging & commit — All changes are staged and committed (if needed)
  5. Push & PR creation — Your branch is pushed and a PR is automatically opened against develop (or opens existing PR if one already exists)
  6. Manual review — The PR opens in your browser so you can review the changes yourself
  7. One-click merge — After reviewing, press Enter to squash merge and delete the branch
  8. Clean return — Automatically switches back to develop and pulls the latest changes

Requirements

  • Git
  • GitHub CLI
    brew install gh
    
  • GitHub Copilot CLI (optional, but recommended for auto-generated commit messages)
    npm install -g @github/copilot
    
  • GitHub Authentication
    gh auth login
     Select GitHub.com
     Select SSH
     Select key
     Authenticate with GitHub
    gh auth setup-git
    

Note: We use the new @github/copilot CLI (installed via npm) which replaced the deprecated gh-copilot extension in October 2025.

If you encounter the error ‘No ‘origin’ remote found in this repo’, run ‘git remote -v’ to check your configured remote names. This script assumes a remote named ‘origin’ exists. If your remote has a different name, either rename it to ‘origin’ or modify the script accordingly.

How We Use This at Ecenica

We’re constantly building and enhancing our services, from WordPress hosting infrastructure to client management tools. Our development flow demands both speed and quality, which is why these aliases have become essential to our daily workflow.

Whether we’re:

  • Fixing bugs in production services (git start fix api-timeout)
  • Building new features for client dashboards (git start feat billing-alerts)
  • Updating documentation for our internal APIs (git start docs webhook-endpoints)
  • Refactoring legacy code for better performance (git start refactor database-queries)

…we use git start and git finish dozens of times per day across our team.

The result? Our engineers spend less time wrestling with Git mechanics and more time focused on what matters: delivering reliable, high-quality services to our clients. Quick documentation updates no longer require 10 minutes of workflow overhead. Small bug fixes get deployed faster. Code review becomes the focus, not the Git ceremony around it.

Why This Matters

Small changes shouldn’t require heavyweight workflows.

With auto-generated commit messages, smart handling of existing PRs, and instant merging, this workflow reduces mental load and saves valuable engineering time. Instead of context-switching through 13 steps, you get two commands that handle everything intelligently.

At Ecenica, speed and simplicity drive our development culture and these small improvements add up quickly. When you’re managing hosting infrastructure, client services, and continuous deployments, every minute saved on workflow friction is a minute gained for building better products.

Power your business with Ecenica Hosting

Built for WordPress and serious websites. Fast, secure and supported by real people in the UK.

Ecenica hosting services represented by a connected red route across London