#!/bin/bash
# GitFlow Guardian - Post-checkout Hook
# Provides helpful reminders when switching branches
# Get the directory where this hook is located
HOOK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Load configuration if it exists
CONFIG_FILE="$HOOK_DIR/config"
if [ -f "$CONFIG_FILE" ]; then
source "$CONFIG_FILE"
else
# Default configuration
USE_COLORS=true
SHOW_CHECKOUT_MESSAGES=true
MAX_DISPLAY_LENGTH=50
fi
# Exit early if messages are disabled
if [ "$SHOW_CHECKOUT_MESSAGES" != "true" ]; then
exit 0
fi
# Colors (only if enabled)
if [ "$USE_COLORS" = "true" ]; then
RED='\033[0;31m'
YELLOW='\033[1;33m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'
else
RED=''
YELLOW=''
GREEN=''
BLUE=''
CYAN=''
NC=''
fi
# Get the branch we just switched to
BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null)
# Check if this is actually a branch switch (not a file checkout)
# $3 is 1 for branch checkout, 0 for file checkout
if [ "$3" != "1" ]; then
exit 0
fi
# Get the previous and new commit hashes
PREV_HEAD=$1
NEW_HEAD=$2
# Function to check if a branch was just created
is_new_branch() {
# Check if the previous HEAD is the same as the current branch's parent
# and if we're on a feature branch
if [[ "$BRANCH" == feature/* ]] || [[ "$BRANCH" == fix/* ]] || [[ "$BRANCH" == bugfix/* ]]; then
# Get the parent branch (where this branch was created from)
PARENT_BRANCH=$(git show-branch -a 2>/dev/null |
grep '\*' |
grep -v "\[$BRANCH" |
head -n1 |
sed 's/.*\[\(.*\)\].*/\1/' |
sed 's/[\^~].*//')
# Alternative method: check if this is the first commit on the branch
BRANCH_BASE=$(git merge-base HEAD main 2>/dev/null)
DEVELOP_BASE=$(git merge-base HEAD develop 2>/dev/null)
# If the branch base is the same as main's HEAD, it was created from main
MAIN_HEAD=$(git rev-parse main 2>/dev/null)
if [ "$BRANCH_BASE" = "$MAIN_HEAD" ] && [ "$BRANCH_BASE" != "$DEVELOP_BASE" ]; then
return 0 # Branch was created from main
fi
fi
return 1 # Not a new branch from main
}
# Check if this is a new feature branch created from main
if is_new_branch; then
echo -e "${RED}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${RED}║ ⚠️ WARNING ⚠️ ║${NC}"
echo -e "${RED}╠════════════════════════════════════════════════════════════════╣${NC}"
echo -e "${RED}║ ║${NC}"
echo -e "${RED}║ This feature branch appears to be created from MAIN! ║${NC}"
echo -e "${RED}║ ║${NC}"
echo -e "${RED}║ Feature branches should be created from DEVELOP: ║${NC}"
echo -e "${RED}║ ║${NC}"
echo -e "${RED}║ To fix this: ║${NC}"
echo -e "${RED}║ 1. ${YELLOW}git checkout develop${RED} ║${NC}"
echo -e "${RED}║ 2. ${YELLOW}git checkout -b $BRANCH${RED} ║${NC}"
echo -e "${RED}║ 3. Cherry-pick your commits if needed ║${NC}"
echo -e "${RED}║ ║${NC}"
echo -e "${RED}║ GitFlow workflow: ║${NC}"
echo -e "${RED}║ • feature/* branches → from develop ║${NC}"
echo -e "${RED}║ • hotfix/* branches → from main ║${NC}"
echo -e "${RED}║ • release/* branches → from develop ║${NC}"
echo -e "${RED}║ ║${NC}"
echo -e "${RED}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""
fi
# Provide helpful messages based on branch
case "$BRANCH" in
main|master)
echo -e "${RED}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${RED}║ 📍 You are now on the MAIN branch ║${NC}"
echo -e "${RED}╠════════════════════════════════════════════════════════════════╣${NC}"
echo -e "${RED}║ ║${NC}"
echo -e "${RED}║ ⚠️ This is the PRODUCTION branch! ║${NC}"
echo -e "${RED}║ ║${NC}"
echo -e "${RED}║ You should rarely need to be on this branch. ║${NC}"
echo -e "${RED}║ ║${NC}"
echo -e "${RED}║ Common tasks and where to do them: ║${NC}"
echo -e "${RED}║ • New features → ${GREEN}git checkout develop${RED} ║${NC}"
echo -e "${RED}║ • Bug fixes → ${GREEN}git checkout develop${RED} ║${NC}"
echo -e "${RED}║ • Hotfixes → ${YELLOW}git checkout -b hotfix/issue-name${RED} ║${NC}"
echo -e "${RED}║ ║${NC}"
echo -e "${RED}║ Remember: ║${NC}"
echo -e "${RED}║ • DO NOT commit directly here ║${NC}"
echo -e "${RED}║ • DO NOT create feature branches from here ║${NC}"
echo -e "${RED}║ • Only merge from release/* or hotfix/* branches ║${NC}"
echo -e "${RED}║ ║${NC}"
echo -e "${RED}╚════════════════════════════════════════════════════════════════╝${NC}"
;;
develop)
echo -e "${YELLOW}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${YELLOW}║ 📍 You are now on the DEVELOP branch ║${NC}"
echo -e "${YELLOW}╠════════════════════════════════════════════════════════════════╣${NC}"
echo -e "${YELLOW}║ ║${NC}"
echo -e "${YELLOW}║ This is the integration branch for new features. ║${NC}"
echo -e "${YELLOW}║ ║${NC}"
echo -e "${YELLOW}║ Remember: ║${NC}"
echo -e "${YELLOW}║ • Create feature branches for new work: ║${NC}"
echo -e "${YELLOW}║ ${GREEN}git checkout -b feature/your-feature${YELLOW} ║${NC}"
echo -e "${YELLOW}║ • Don't commit directly unless it's a merge ║${NC}"
echo -e "${YELLOW}║ • Keep this branch stable for other developers ║${NC}"
echo -e "${YELLOW}║ ║${NC}"
echo -e "${YELLOW}╚════════════════════════════════════════════════════════════════╝${NC}"
;;
feature/*)
# Truncate long branch names to fit in the box
if [ ${#BRANCH} -gt $MAX_DISPLAY_LENGTH ]; then
TRUNCATE_LENGTH=$((MAX_DISPLAY_LENGTH - 3))
DISPLAY_BRANCH="${BRANCH:0:$TRUNCATE_LENGTH}..."
else
DISPLAY_BRANCH="$BRANCH"
fi
echo -e "${GREEN}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ ✅ You are on a FEATURE branch ║${NC}"
echo -e "${GREEN}╠════════════════════════════════════════════════════════════════╣${NC}"
echo -e "${GREEN}║ ║${NC}"
echo -e "${GREEN}║ Branch: ${CYAN}$DISPLAY_BRANCH${GREEN}${NC}"
echo -e "${GREEN}║ ║${NC}"
echo -e "${GREEN}║ You can safely commit and experiment here! ║${NC}"
echo -e "${GREEN}║ ║${NC}"
echo -e "${GREEN}║ When ready: ║${NC}"
echo -e "${GREEN}║ 1. Push your branch: ${CYAN}git push -u origin $BRANCH${GREEN} ║${NC}"
echo -e "${GREEN}║ 2. Create a PR: ${CYAN}gh pr create${GREEN} ║${NC}"
echo -e "${GREEN}║ ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════════════════════════════╝${NC}"
;;
fix/*|bugfix/*)
# Truncate long branch names to fit in the box
if [ ${#BRANCH} -gt $MAX_DISPLAY_LENGTH ]; then
TRUNCATE_LENGTH=$((MAX_DISPLAY_LENGTH - 3))
DISPLAY_BRANCH="${BRANCH:0:$TRUNCATE_LENGTH}..."
else
DISPLAY_BRANCH="$BRANCH"
fi
echo -e "${BLUE}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ 🔧 You are on a FIX branch ║${NC}"
echo -e "${BLUE}╠════════════════════════════════════════════════════════════════╣${NC}"
echo -e "${BLUE}║ ║${NC}"
echo -e "${BLUE}║ Branch: ${CYAN}$DISPLAY_BRANCH${BLUE}${NC}"
echo -e "${BLUE}║ ║${NC}"
echo -e "${BLUE}║ Good practices for fixes: ║${NC}"
echo -e "${BLUE}║ • Keep changes focused on the specific bug ║${NC}"
echo -e "${BLUE}║ • Add tests to prevent regression ║${NC}"
echo -e "${BLUE}║ • Update documentation if needed ║${NC}"
echo -e "${BLUE}║ ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}"
;;
hotfix/*)
# Truncate long branch names to fit in the box
if [ ${#BRANCH} -gt $MAX_DISPLAY_LENGTH ]; then
TRUNCATE_LENGTH=$((MAX_DISPLAY_LENGTH - 3))
DISPLAY_BRANCH="${BRANCH:0:$TRUNCATE_LENGTH}..."
else
DISPLAY_BRANCH="$BRANCH"
fi
echo -e "${RED}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${RED}║ 🚨 You are on a HOTFIX branch ║${NC}"
echo -e "${RED}╠════════════════════════════════════════════════════════════════╣${NC}"
echo -e "${RED}║ ║${NC}"
echo -e "${RED}║ Branch: ${CYAN}$DISPLAY_BRANCH${RED}${NC}"
echo -e "${RED}║ ║${NC}"
echo -e "${RED}║ This is for URGENT production fixes only! ║${NC}"
echo -e "${RED}║ ║${NC}"
echo -e "${RED}║ Remember to: ║${NC}"
echo -e "${RED}║ • Fix ONLY the critical issue ║${NC}"
echo -e "${RED}║ • Test thoroughly ║${NC}"
echo -e "${RED}║ • Merge to both main AND develop ║${NC}"
echo -e "${RED}║ ║${NC}"
echo -e "${RED}╚════════════════════════════════════════════════════════════════╝${NC}"
;;
release/*)
# Truncate long branch names to fit in the box
if [ ${#BRANCH} -gt $MAX_DISPLAY_LENGTH ]; then
TRUNCATE_LENGTH=$((MAX_DISPLAY_LENGTH - 3))
DISPLAY_BRANCH="${BRANCH:0:$TRUNCATE_LENGTH}..."
else
DISPLAY_BRANCH="$BRANCH"
fi
echo -e "${CYAN}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${CYAN}║ 📦 You are on a RELEASE branch ║${NC}"
echo -e "${CYAN}╠════════════════════════════════════════════════════════════════╣${NC}"
echo -e "${CYAN}║ ║${NC}"
echo -e "${CYAN}║ Branch: ${CYAN}$DISPLAY_BRANCH${CYAN}${NC}"
echo -e "${CYAN}║ ║${NC}"
echo -e "${CYAN}║ Only bug fixes and release prep allowed here! ║${NC}"
echo -e "${CYAN}║ ║${NC}"
echo -e "${CYAN}║ No new features! ║${NC}"
echo -e "${CYAN}║ ║${NC}"
echo -e "${CYAN}╚════════════════════════════════════════════════════════════════╝${NC}"
;;
esac
# Show current status
echo ""
git status -sb