Skip to content

Instantly share code, notes, and snippets.

@drnic
Created September 18, 2025 00:36
Show Gist options
  • Save drnic/8c18d4edc3829512f52f89afefc793d3 to your computer and use it in GitHub Desktop.
Save drnic/8c18d4edc3829512f52f89afefc793d3 to your computer and use it in GitHub Desktop.
bin/worktree to create/list/destroy worktrees where 1) bin/setup expects to setup databases; 2) some .gitignored files copied over; etc
#!/usr/bin/env bash
set -euo pipefail
# Usage/help
usage() {
echo "Usage: bin/worktree <branch-name>"
echo " bin/worktree --destroy <branch-name>"
echo " bin/worktree -d <branch-name>"
echo ""
echo "Creates or destroys a git worktree and sets up Rails environment with unique database names."
exit 1
}
LIST_MODE=false
DESTROY_MODE=false
if [ $# -eq 0 ]; then
usage
fi
if [ $# -gt 0 ] && { [ "$1" = "--list" ] || [ "$1" = "-l" ]; }; then
LIST_MODE=true
shift
fi
if [ $# -gt 0 ] && { [ "$1" = "--destroy" ] || [ "$1" = "-d" ]; }; then
DESTROY_MODE=true
shift
fi
ROOT_FOLDER=$(basename "$(pwd)")
WORKTREES_PARENT="../${ROOT_FOLDER}-worktrees"
CURRENT_DIR=$(pwd)
if [ "$LIST_MODE" = true ]; then
echo "πŸ“‹ Listing git worktrees:"
git worktree list
exit 0
fi
if [ $# -eq 0 ]; then
usage
fi
BRANCH_NAME="$1"
FLATTENED_BRANCH_NAME="${BRANCH_NAME//\//_}"
WORKTREE_DIR="$WORKTREES_PARENT/$FLATTENED_BRANCH_NAME"
# Clean branch name for database naming (replace special chars)
DB_SUFFIX=$(echo "$FLATTENED_BRANCH_NAME" | sed 's/[^a-zA-Z0-9]/_/g' | tr '[:upper:]' '[:lower:]')
if [ "$DESTROY_MODE" = true ]; then
echo "⚠️ Destroying worktree for branch: $BRANCH_NAME"
if [ ! -d "$WORKTREE_DIR" ]; then
echo "❌ Worktree directory does not exist: $WORKTREE_DIR"
exit 1
fi
cd "$WORKTREE_DIR"
echo "πŸ—„οΈ Dropping Rails databases for branch..."
# Drop development DB
if bin/rails db:drop; then
echo "βœ… Dropped development database"
else
echo "⚠️ Could not drop development database (may not exist)"
fi
# Drop test DB
if bin/rails db:drop RAILS_ENV=test; then
echo "βœ… Dropped test database"
else
echo "⚠️ Could not drop test database (may not exist)"
fi
cd "$CURRENT_DIR"
echo "πŸ—‘οΈ Removing worktree directory..."
if git worktree remove "$WORKTREE_DIR" --force; then
echo "βœ… Removed git worktree"
else
echo "⚠️ Failed to remove git worktree (may not be registered)"
fi
if rm -rf "$WORKTREE_DIR"; then
echo "βœ… Deleted worktree directory"
else
echo "⚠️ Failed to delete worktree directory"
fi
echo "🌿 Deleting branch..."
if git branch -D "$BRANCH_NAME" 2>/dev/null; then
echo "βœ… Deleted branch: $BRANCH_NAME"
else
echo "⚠️ Failed to delete branch (may not exist locally or may be current branch)"
fi
echo "πŸŽ‰ Worktree destruction complete!"
exit 0
fi
echo "Creating git worktree for branch: $BRANCH_NAME"
# Create worktrees directory if it doesn't exist
mkdir -p "../${ROOT_FOLDER}-worktrees"
# Create the git worktree
# Determine if branch exists locally or remotely
if git rev-parse --verify "$BRANCH_NAME" >/dev/null 2>&1; then
# Branch exists, add worktree normally
if git worktree add "$WORKTREE_DIR" "$BRANCH_NAME"; then
echo "βœ… Git worktree created at: $WORKTREE_DIR"
else
echo "❌ Failed to create git worktree"
exit 1
fi
else
# Branch does not exist, create it with -b flag
if git worktree add "$WORKTREE_DIR" -b "$BRANCH_NAME"; then
echo "βœ… Git worktree created (new branch) at: $WORKTREE_DIR"
else
echo "❌ Failed to create git worktree (new branch)"
exit 1
fi
fi
echo "πŸ“ Copying important Rails configuration files..."
# Copy other important gitignored files that might exist
for file in .env CLAUDE.md .claude .cursorrules .cursor .developer.rb LogConfig.yml .mcp.json .vscode ; do
if [ -e "$file" ]; then
cp -r "$file" "$WORKTREE_DIR/"
echo "βœ… Copied $file"
fi
done
# Copy Rails credentials
if [ -d "config/credentials" ]; then
cp -r "config/credentials" "$WORKTREE_DIR/config/"
echo "βœ… Copied Rails credentials"
fi
echo "πŸ—„οΈ Setting up unique database configuration..."
# Append database environment variables to .env
cat >> "$WORKTREE_DIR/.env" << EOF
# Worktree-specific database configuration
BRANCH_DATABASE=true
PGDATABASE=$(echo "sc_coregem_dev_${DB_SUFFIX}" | cut -c1-63)
TEST_ENV_NUMBER=_${DB_SUFFIX}
EOF
echo "βœ… Added unique database configuration to .env"
# Change to the worktree directory and run setup
cd "$WORKTREE_DIR"
echo "πŸ”§ Running bin/setup in worktree with mise exec..."
if command -v mise >/dev/null 2>&1; then
if mise exec -- bin/setup; then
echo "βœ… Setup completed successfully"
else
echo "⚠️ Setup encountered issues - you may need to run it manually"
fi
else
if ./bin/setup; then
echo "βœ… Setup completed successfully"
else
echo "⚠️ Setup encountered issues - you may need to run it manually"
fi
fi
# Return to original directory
cd "$CURRENT_DIR"
echo ""
echo "πŸŽ‰ Worktree setup complete!"
echo ""
echo "To change into the new worktree directory, run:"
if command -v direnv >/dev/null 2>&1; then
echo "cd $WORKTREE_DIR; direnv allow"
else
echo "cd $WORKTREE_DIR"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment