#!/bin/bash # Git Worktree Setup Script # Generated by git-worktree-setup skill # # This script automates the creation of a git worktree with development environment setup. # # Usage: # ./worktree-setup.sh [worktree-path] [--no-install] set -euo pipefail # ============================================================================ # Configuration # ============================================================================ BRANCH_NAME="${1:-}" WORKTREE_PATH="${2:-}" SKIP_INSTALL=false # Parse flags for arg in "$@"; do case $arg in --no-install) SKIP_INSTALL=true shift ;; esac done # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # ============================================================================ # Helper Functions # ============================================================================ print_success() { echo -e "${GREEN}✓${NC} $1" } print_error() { echo -e "${RED}✗${NC} $1" >&2 } print_warning() { echo -e "${YELLOW}⚠${NC} $1" } print_info() { echo -e "${BLUE}ℹ${NC} $1" } print_header() { echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "$1" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" } # ============================================================================ # Prerequisite Checks # ============================================================================ check_prerequisites() { print_header "Checking Prerequisites" # Check if in git repository if ! git rev-parse --is-inside-work-tree &>/dev/null; then print_error "Not in a git repository" exit 1 fi print_success "Git repository detected" # Get repository info REPO_NAME=$(basename "$(git rev-parse --show-toplevel)") REPO_ROOT=$(git rev-parse --show-toplevel) CURRENT_BRANCH=$(git branch --show-current) print_info "Repository: $REPO_NAME" print_info "Current branch: $CURRENT_BRANCH" # Check for branch name if [ -z "$BRANCH_NAME" ]; then print_error "Branch name required" echo "Usage: $0 [worktree-path] [--no-install]" exit 1 fi # Set default worktree path if not provided if [ -z "$WORKTREE_PATH" ]; then WORKTREE_PATH="$(dirname "$REPO_ROOT")/$REPO_NAME-$BRANCH_NAME" fi print_info "Target branch: $BRANCH_NAME" print_info "Worktree path: $WORKTREE_PATH" } check_working_directory() { # Check for uncommitted changes if [ -n "$(git status --porcelain)" ]; then print_warning "You have uncommitted changes in current worktree" git status --short echo "" read -p "Continue anyway? (yes/no): " -r if [[ ! $REPLY =~ ^[Yy]es$ ]]; then print_info "Aborted by user" exit 0 fi else print_success "Working directory is clean" fi } check_branch_status() { # Check if branch exists if git show-ref --verify "refs/heads/$BRANCH_NAME" &>/dev/null; then BRANCH_TYPE="existing" print_info "Branch exists: $BRANCH_NAME" else BRANCH_TYPE="new" print_info "Will create new branch: $BRANCH_NAME" # Check if exists on remote if git show-ref --verify "refs/remotes/origin/$BRANCH_NAME" &>/dev/null; then print_info "Branch exists on remote, will track it" BRANCH_TYPE="remote" fi fi } check_directory_conflict() { if [ -d "$WORKTREE_PATH" ]; then print_error "Directory already exists: $WORKTREE_PATH" echo "" read -p "Remove and continue? (yes/no): " -r if [[ $REPLY =~ ^[Yy]es$ ]]; then rm -rf "$WORKTREE_PATH" print_success "Removed existing directory" else print_info "Aborted by user" exit 0 fi else print_success "Target directory available" fi } # ============================================================================ # Worktree Creation # ============================================================================ create_worktree() { print_header "Creating Worktree" case $BRANCH_TYPE in new) print_info "Creating new branch: $BRANCH_NAME" if git worktree add "$WORKTREE_PATH" -b "$BRANCH_NAME"; then print_success "Worktree created with new branch" else print_error "Failed to create worktree" exit 1 fi ;; existing) print_info "Checking out existing branch: $BRANCH_NAME" if git worktree add "$WORKTREE_PATH" "$BRANCH_NAME"; then print_success "Worktree created from existing branch" else print_error "Failed to create worktree" exit 1 fi ;; remote) print_info "Tracking remote branch: origin/$BRANCH_NAME" if git worktree add "$WORKTREE_PATH" -b "$BRANCH_NAME" --track "origin/$BRANCH_NAME"; then print_success "Worktree created tracking remote branch" else print_error "Failed to create worktree" exit 1 fi ;; esac } verify_worktree() { print_header "Verifying Worktree" # Check if worktree appears in list if git worktree list | grep -q "$WORKTREE_PATH"; then print_success "Worktree appears in git worktree list" else print_error "Worktree not in git worktree list" exit 1 fi # Check if directory exists if [ -d "$WORKTREE_PATH" ]; then print_success "Worktree directory exists" else print_error "Worktree directory not found" exit 1 fi # Check if .git file exists if [ -f "$WORKTREE_PATH/.git" ]; then print_success "Git metadata configured" else print_error "Missing .git file in worktree" exit 1 fi # Check if has files if [ -n "$(ls -A "$WORKTREE_PATH")" ]; then print_success "Worktree populated with files" else print_error "Worktree directory is empty" exit 1 fi } # ============================================================================ # Development Environment Setup # ============================================================================ detect_package_manager() { cd "$WORKTREE_PATH" if [ -f "pnpm-lock.yaml" ]; then PKG_MANAGER="pnpm" INSTALL_CMD="pnpm install" elif [ -f "yarn.lock" ]; then PKG_MANAGER="yarn" INSTALL_CMD="yarn install" elif [ -f "bun.lockb" ]; then PKG_MANAGER="bun" INSTALL_CMD="bun install" elif [ -f "package-lock.json" ]; then PKG_MANAGER="npm" INSTALL_CMD="npm install" elif [ -f "package.json" ]; then PKG_MANAGER="npm" INSTALL_CMD="npm install" else PKG_MANAGER="none" INSTALL_CMD="" fi if [ "$PKG_MANAGER" != "none" ]; then print_info "Detected package manager: $PKG_MANAGER" fi } install_dependencies() { if [ "$SKIP_INSTALL" = true ]; then print_info "Skipping dependency installation (--no-install flag)" return 0 fi if [ "$PKG_MANAGER" = "none" ]; then print_info "No package.json found, skipping dependency installation" return 0 fi print_header "Installing Dependencies" cd "$WORKTREE_PATH" print_info "Running: $INSTALL_CMD" if $INSTALL_CMD; then print_success "Dependencies installed successfully" else print_warning "Dependency installation failed" print_info "You can manually install later with: cd $WORKTREE_PATH && $INSTALL_CMD" return 1 fi } copy_environment_files() { if [ "$SKIP_INSTALL" = true ]; then return 0 fi if [ -f "$REPO_ROOT/.env" ]; then print_info "Found .env file in repository root" read -p "Copy .env to worktree? (yes/no): " -r if [[ $REPLY =~ ^[Yy]es$ ]]; then cp "$REPO_ROOT/.env" "$WORKTREE_PATH/.env" print_success "Copied .env file" fi fi # Copy other common env files for env_file in .env.local .env.development .env.test; do if [ -f "$REPO_ROOT/$env_file" ]; then read -p "Copy $env_file to worktree? (yes/no): " -r if [[ $REPLY =~ ^[Yy]es$ ]]; then cp "$REPO_ROOT/$env_file" "$WORKTREE_PATH/$env_file" print_success "Copied $env_file" fi fi done } # ============================================================================ # Summary and Next Steps # ============================================================================ print_summary() { print_header "Worktree Created Successfully" echo "Location: $WORKTREE_PATH" echo "Branch: $BRANCH_NAME ($BRANCH_TYPE)" if [ "$PKG_MANAGER" != "none" ] && [ "$SKIP_INSTALL" = false ]; then echo "Dev Setup: ✓ Complete ($PKG_MANAGER)" else echo "Dev Setup: ⊘ Skipped" fi echo "" print_header "Next Steps" echo "1. Navigate to worktree:" echo " ${BLUE}cd $WORKTREE_PATH${NC}" echo "" echo "2. Start Claude Code:" echo " ${BLUE}claude${NC}" echo "" echo "3. Begin development on $BRANCH_NAME" echo "" print_header "All Worktrees" git worktree list echo "" print_header "Quick Reference" echo "List worktrees: git worktree list" echo "Remove worktree: git worktree remove $WORKTREE_PATH" echo "Navigate: cd $WORKTREE_PATH" echo "Return to main: cd $REPO_ROOT" echo "" } # ============================================================================ # Main Execution # ============================================================================ main() { print_header "Git Worktree Setup" # Phase 0: Prerequisites check_prerequisites check_working_directory check_branch_status check_directory_conflict # Phase 1: Create worktree create_worktree verify_worktree # Phase 2: Setup development environment detect_package_manager install_dependencies copy_environment_files # Phase 3: Summary print_summary print_success "Setup complete!" } # Run main function main "$@"