Git Worktree Script
A bash script for creating git worktrees quickly and efficiently for parallel development.
Installation
Quick Setup (3 steps)
-
Create the script file:
mkdir -p ~/bin nano ~/bin/worktree -
Copy the script content from the bottom of this page, paste it into the editor, then save (Ctrl+X, Y, Enter)
-
Make it available globally:
chmod +x ~/bin/worktree echo 'export PATH="$HOME/bin:$PATH"' >> ~/.zshrc # For macOS echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc # For Linux source ~/.zshrc # or source ~/.bashrc
Alternative: System-wide Installation
For system-wide access (all users):
sudo nano /usr/local/bin/worktree
# Copy script content and save
sudo chmod +x /usr/local/bin/worktreeVerify Installation
Test in any git repository:
which worktree
worktree feature-testTroubleshooting:
- If command not found: restart terminal or run
source ~/.zshrc - If permission denied: run
chmod +x ~/bin/worktree
Usage
Navigate to any git repository and run:
worktree {branch-name}Examples
# Create a feature branch worktree
worktree feature-login-improvements
# Create a bug fix worktree
worktree fix-dashboard-calculation
# Create a hotfix worktree
worktree hotfix-security-vulnerability
# Create a refactor worktree
worktree refactor-auth-serviceWhat It Does
- Validates inputs - Checks branch name is provided and target directory doesn't exist
- Checks environment - Ensures you're in a git repository
- Fetches latest branches - Gets all remote branch information
- Intelligently handles branches:
- π‘ Remote branch exists: Checks out existing remote branch
- π» Local branch exists: Checks out existing local branch
- π New branch: Creates new branch from
origin/development
- Sets up upstream tracking - Automatically configures proper upstream tracking for all branch types
- Creates worktree - Makes a new directory
../{project-name}-{branch-name} - Verifies upstream tracking - Confirms proper upstream configuration and warns about potential issues
- Copies environment - Automatically copies
.envfile if it exists - Installs dependencies - Runs
npm installifpackage.jsonexists - Auto-navigation - Opens new shell in the worktree directory
Directory Structure
The script creates worktrees in parallel directories:
/path/to/projects/
βββ myproject/ # Main repository
βββ myproject-feature-login-improvements/ # Worktree 1
βββ myproject-fix-dashboard-calculation/ # Worktree 2
βββ myproject-hotfix-security/ # Worktree 3Branch Naming Conventions
- Features:
feature-{description} - Bug fixes:
fix-{description} - Hotfixes:
hotfix-{description} - Refactoring:
refactor-{description}
Managing Worktrees
List all worktrees
git worktree listSwitch to a worktree
cd ../myproject-feature-nameRemove a completed worktree
# First ensure work is committed and pushed
git worktree remove ../myproject-feature-nameClean up after merge
# Delete remote branch (if merged)
git push origin --delete feature-name
# Delete local branch reference
git branch -d feature-nameIntelligent Branch Handling
The script automatically detects and handles different branch scenarios:
π‘ Remote Branch Exists
worktree feature-existing-remote
# Output: Branch 'feature-existing-remote' exists on remote, checking out existing remote branchπ» Local Branch Exists
worktree feature-existing-local
# Output: Branch 'feature-existing-local' exists locally, checking out existing local branchπ New Branch Creation
worktree feature-brand-new
# Output: Branch 'feature-brand-new' doesn't exist, creating new branch from origin/development
# Output: π Setting up upstream tracking for new branch...
# Output: β
Branch pushed and upstream tracking configured!Automatic Setup Features
- π Upstream Tracking: Automatically configures upstream tracking for all branch types:
- New branches: Pushes to origin and sets upstream tracking
- Remote branches: Sets upstream tracking to existing remote branch
- Local branches: Checks for remote and pushes if needed, or sets upstream to existing remote
- π Verification: Confirms upstream tracking is properly configured and warns about potential issues
- π Environment Variables: Copies
.envfile from main repository - π¦ Dependencies: Runs
npm installautomatically ifpackage.jsonexists - π Ready to Code: Opens new shell in worktree directory
Error Handling
The script checks for:
- β Branch name provided
- β Inside git repository
- β Target directory doesn't exist
- β Can fetch from remote origin
Requirements
- Git repository with
origin/developmentbranch - Bash shell
- Git configured with origin remote
Troubleshooting
"Not in a git repository"
- Make sure you're inside a git project directory
"Failed to fetch origin/development"
- Ensure your repository has a
developmentbranch on origin - Check your internet connection and git credentials
"Branch already exists"
- Choose a different branch name or delete the existing branch
"Directory already exists"
- Remove the existing directory or choose a different branch name
What Happens Automatically
After running the script, you'll be automatically placed in the new worktree with:
- β Upstream tracking configured: Proper git upstream tracking set up for your branch type
- β
Environment ready:
.envfile copied (if exists) - β
Dependencies installed:
npm installcompleted (ifpackage.jsonexists) - β Safety checks: Verification that upstream tracking is working correctly
- β New shell opened: Ready to start coding immediately
The script provides clear feedback about what type of branch you're working with and shows the tracking configuration for safety.
Next Steps
- Start development server:
npm run dev,npm start, etc. - Begin development: Make your changes and commits
- Push changes:
git push(upstream already configured automatically)
No manual setup required! The script shows you exactly which upstream branch you're tracking for safety.
Safety Features
The script includes several safety features:
- π‘ Safety reminders: Clear information about what branch you're tracking
- β οΈ Warning system: Alerts if branches are tracking unexpected remotes (like development)
- π Upstream verification: Confirms tracking is configured properly
- π Current tracking display: Shows exactly where your pushes will go
Always check the output to confirm your branch is tracking the expected remote!
Advanced Usage
Manual worktree commands
# Create worktree manually
git worktree add ../project-branch -b branch-name origin/development
# Create from specific commit
git worktree add ../project-temp --detach commit-hash
# Repair broken worktree links
git worktree repair
# Clean up stale worktrees
git worktree pruneThis script automates the common worktree workflow while maintaining best practices for branch naming and directory organization.
The Script
#!/bin/bash
# Git Worktree Creation Script
# Creates a new worktree with branch from origin/development
# Get branch name as first argument
BRANCH_NAME="$1"
PROJECT_NAME=$(basename "$PWD")
# Validate inputs
if [ -z "$BRANCH_NAME" ]; then
echo "Error: Branch name is required"
echo "Usage: worktree {branch-name}"
echo ""
echo "Examples:"
echo " worktree feature-login-improvements"
echo " worktree fix-dashboard-calculation"
echo " worktree hotfix-security-vulnerability"
exit 1
fi
# Check if we're in a git repository
if ! git rev-parse --is-inside-work-tree > /dev/null 2>&1; then
echo "Error: Not in a git repository"
exit 1
fi
# Check if target directory already exists
TARGET_DIR="../${PROJECT_NAME}-${BRANCH_NAME}"
if [ -d "$TARGET_DIR" ]; then
echo "Error: Directory '$TARGET_DIR' already exists"
exit 1
fi
# Fetch all branches to get latest info
echo "Fetching latest branches..."
git fetch origin
# Check if branch exists locally
LOCAL_BRANCH_EXISTS=$(git show-ref --verify --quiet refs/heads/$BRANCH_NAME && echo "true" || echo "false")
# Check if branch exists on remote
REMOTE_BRANCH_EXISTS=$(git show-ref --verify --quiet refs/remotes/origin/$BRANCH_NAME && echo "true" || echo "false")
# Determine the worktree creation strategy
if [ "$REMOTE_BRANCH_EXISTS" = "true" ]; then
echo "π‘ Branch '$BRANCH_NAME' exists on remote, checking out existing remote branch"
WORKTREE_CMD="git worktree add \"$TARGET_DIR\" -b \"$BRANCH_NAME\" origin/$BRANCH_NAME"
BRANCH_SOURCE="origin/$BRANCH_NAME"
NEEDS_UPSTREAM_SETUP="remote"
elif [ "$LOCAL_BRANCH_EXISTS" = "true" ]; then
echo "π» Branch '$BRANCH_NAME' exists locally, checking out existing local branch"
WORKTREE_CMD="git worktree add \"$TARGET_DIR\" \"$BRANCH_NAME\""
BRANCH_SOURCE="local branch"
NEEDS_UPSTREAM_SETUP="local"
else
echo "π Branch '$BRANCH_NAME' doesn't exist, creating new branch from origin/development"
if ! git fetch origin development; then
echo "Error: Failed to fetch origin/development"
echo "Make sure 'development' branch exists on origin"
exit 1
fi
WORKTREE_CMD="git worktree add \"$TARGET_DIR\" -b \"$BRANCH_NAME\" origin/development"
BRANCH_SOURCE="origin/development"
NEEDS_UPSTREAM_SETUP="new"
fi
# Create worktree
echo "Creating worktree for branch: $BRANCH_NAME"
echo "Target directory: $TARGET_DIR"
echo "Source: $BRANCH_SOURCE"
if eval $WORKTREE_CMD; then
echo ""
echo "β
Worktree created successfully!"
echo "π Location: $TARGET_DIR"
echo "πΏ Branch: $BRANCH_NAME (from $BRANCH_SOURCE)"
# Navigate to new worktree
cd "$TARGET_DIR"
# Set up proper upstream tracking for all branches
echo ""
echo "π Setting up upstream tracking..."
case "$NEEDS_UPSTREAM_SETUP" in
"new")
echo "Setting up upstream tracking for new branch..."
git push -u origin "$BRANCH_NAME"
echo "β
Branch pushed and upstream tracking configured!"
;;
"remote")
echo "Setting up upstream tracking for existing remote branch..."
git branch --set-upstream-to=origin/"$BRANCH_NAME" "$BRANCH_NAME"
echo "β
Upstream tracking configured to origin/$BRANCH_NAME!"
;;
"local")
echo "Checking upstream tracking for existing local branch..."
# Check if remote branch exists for this local branch
if git show-ref --verify --quiet refs/remotes/origin/"$BRANCH_NAME"; then
echo "Remote branch exists, setting upstream tracking..."
git branch --set-upstream-to=origin/"$BRANCH_NAME" "$BRANCH_NAME"
echo "β
Upstream tracking configured to origin/$BRANCH_NAME!"
else
echo "No remote branch found. Pushing local branch to origin..."
git push -u origin "$BRANCH_NAME"
echo "β
Branch pushed and upstream tracking configured!"
fi
;;
esac
# Verify upstream tracking
echo ""
echo "π Verifying upstream tracking..."
UPSTREAM_INFO=$(git branch -vv | grep "^\*" | grep -o '\[.*\]' | tr -d '[]' || echo "none")
if [ "$UPSTREAM_INFO" != "none" ]; then
echo "β
Upstream tracking verified: $UPSTREAM_INFO"
# Additional safety check - warn if tracking unexpected branch
if [[ "$UPSTREAM_INFO" == *"development"* ]] && [ "$BRANCH_NAME" != "development" ]; then
echo "β οΈ WARNING: Branch '$BRANCH_NAME' is tracking development branch!"
echo "β οΈ This might cause accidental pushes to development."
fi
else
echo "β οΈ WARNING: No upstream tracking configured!"
echo "β οΈ You may need to run 'git push -u origin $BRANCH_NAME' manually."
fi
# Copy .env file if it exists in the original repository
if [ -f "../${PROJECT_NAME}/.env" ]; then
echo ""
echo "π Found .env file, copying to new worktree..."
cp "../${PROJECT_NAME}/.env" .env
echo "β
Environment file copied successfully!"
fi
# Check for package.json and run npm install if it exists
if [ -f "package.json" ]; then
echo ""
echo "π¦ Found package.json, installing dependencies..."
if npm install; then
echo "β
Dependencies installed successfully!"
else
echo "β οΈ Failed to install dependencies. You may need to run 'npm install' manually."
fi
fi
echo ""
echo "π Ready to start development!"
echo "π Current branch tracking: $(git branch -vv | grep "^\*" | grep -o '\[.*\]' | tr -d '[]' || echo 'none')"
echo ""
echo "π‘ Safety reminders:"
echo " β’ 'git push' will push to the tracked remote branch shown above"
echo " β’ Always verify your current branch with 'git branch'"
echo " β’ Use 'git push origin $BRANCH_NAME' to be explicit about destination"
echo ""
echo "To list all worktrees:"
echo " git worktree list"
echo ""
echo "To remove this worktree later:"
echo " git worktree remove $TARGET_DIR"
echo ""
echo "Navigating to new worktree..."
# Start a new shell in the worktree directory
exec bash -c "cd '$TARGET_DIR' && exec \$SHELL"
else
echo "β Failed to create worktree"
exit 1
fi