Skip to content

Instantly share code, notes, and snippets.

@davej
Created July 8, 2025 09:17
Show Gist options
  • Save davej/a43caf453bcba02ae56041f190a7601e to your computer and use it in GitHub Desktop.
Save davej/a43caf453bcba02ae56041f190a7601e to your computer and use it in GitHub Desktop.
`wtree` function to create and manage git worktrees
# Function to create and manage git worktrees
# 1. If the the current projects folder doesn't contain a subdirectory named "worktrees" then create it and add it to gitignore in the current project.
# 2. Create a git worktree and branch named feature-name (which was passed via the wtree alias argument) from the main project folder and save it inside the worktrees folder.
# 3. If there is a .env, prod.env or dev.env in the main project folder then copy it over to the worktrees folder.
# 4. Open the new feature-name worktree folder in a new window using Cursor.
wtree() {
# Check if a feature name was provided as an argument
if [ -z "$1" ]; then
# Print error message if no argument was provided
echo "Error: Please provide a feature name"
# Print usage instructions
echo "Usage: wtree <feature-name>"
# Exit with error code 1
return 1
fi
# Store the feature name from the first argument
local feature_name="$1"
# Check if we're in a git repository
if ! git rev-parse --git-dir > /dev/null 2>&1; then
# Print error message if not in a git repository
echo "Error: Not in a git repository"
# Exit with error code 1
return 1
fi
# Get the root directory of the git repository
local git_root=$(git rev-parse --show-toplevel)
# Define the worktrees directory path
local worktrees_dir="$git_root/worktrees"
# Check if the worktrees directory doesn't exist
if [ ! -d "$worktrees_dir" ]; then
# Create the worktrees directory
mkdir -p "$worktrees_dir"
# Print confirmation message
echo "Created worktrees directory at $worktrees_dir"
# Define the path to the .gitignore file
local gitignore_path="$git_root/.gitignore"
# Check if 'worktrees/' is already in .gitignore
if ! grep -q "^worktrees/$" "$gitignore_path" 2>/dev/null; then
# Add a newline before 'worktrees/' to ensure it's on its own line
echo -e "\nworktrees/" >> "$gitignore_path"
# Print confirmation message
echo "Added worktrees/ to .gitignore"
fi
fi
# Define the path for the new worktree
local worktree_path="$worktrees_dir/$feature_name"
# Check if a worktree with this name already exists
if [ -d "$worktree_path" ]; then
# Print error message if worktree already exists
echo "Error: Worktree '$feature_name' already exists"
# Exit with error code 1
return 1
fi
# Get the default branch name (could be main or master)
local default_branch=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@')
# If we couldn't determine the default branch, try common defaults
if [ -z "$default_branch" ]; then
# Check if 'main' branch exists
if git show-ref --verify --quiet refs/heads/main; then
# Set default branch to 'main'
default_branch="main"
# Check if 'master' branch exists
elif git show-ref --verify --quiet refs/heads/master; then
# Set default branch to 'master'
default_branch="master"
else
# Print error message if no default branch found
echo "Error: Could not determine default branch"
# Exit with error code 1
return 1
fi
fi
# Create the git worktree with a new branch based on the default branch
echo "Creating worktree '$feature_name' from branch '$default_branch'..."
# Execute git worktree add command with the new branch
git worktree add -b "$feature_name" "$worktree_path" "$default_branch"
# Check if the worktree creation was successful
if [ $? -ne 0 ]; then
# Print error message if worktree creation failed
echo "Error: Failed to create worktree"
# Exit with error code 1
return 1
fi
# Array of environment files to copy
local env_files=(".env" "prod.env" "dev.env")
# Loop through each environment file
for env_file in "${env_files[@]}"; do
# Define the source path for the environment file
local src_env="$git_root/$env_file"
# Check if the environment file exists in the main project
if [ -f "$src_env" ]; then
# Copy the environment file to the new worktree
cp "$src_env" "$worktree_path/$env_file"
# Print confirmation message
echo "Copied $env_file to worktree"
fi
done
# Check if Cursor is available in the system
if command -v cursor &> /dev/null; then
# Open the new worktree in Cursor
echo "Opening worktree in Cursor..."
# Execute cursor command with the worktree path
cursor "$worktree_path"
else
# Print warning if Cursor is not found
echo "Warning: Cursor command not found. Please open manually: $worktree_path"
fi
# Print success message
echo "Successfully created worktree '$feature_name' at $worktree_path"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment