Skip to content

Instantly share code, notes, and snippets.

@simbo1905
Created December 11, 2025 21:27
Show Gist options
  • Select an option

  • Save simbo1905/22accc8dc39583672aa6f0483a800429 to your computer and use it in GitHub Desktop.

Select an option

Save simbo1905/22accc8dc39583672aa6f0483a800429 to your computer and use it in GitHub Desktop.
Setup git worktree script

Setup Git Worktree Script

This repository contains a helper script setup-git-worktree.sh that automates the creation of a bare Git repository with adjacent worktree directories, following the flat worktree architecture described in Tom Ups' article:

Overview

The layout created by the script looks like this:

project/
├── .bare/          # Bare repository (the actual Git database)
├── .git            # Text file with "gitdir: ./.bare"
├── main/           # Primary worktree (checked out `main` branch)
└── gitworktree.sh  # Helper to add additional worktrees

Key characteristics:

  • Zero nesting – each worktree is a sibling of the others; no worktree lives inside another.
  • Shared object database – all worktrees share the same .bare repository, keeping disk usage low.
  • Convenient helpergitworktree.sh creates new worktrees adjacent to main, preserving any slashes in the branch name (e.g., feat/awesome creates feat/awesome/).

Usage

1. Create the initial structure

chmod +x setup-git-worktree.sh
./setup-git-worktree.sh <git-url>

Replace <git-url> with either an HTTPS URL (https://github.com/org/repo) or an SSH URL (git@github.com:org/repo.git).

The script will:

  1. Parse the organization and repository name.
  2. Create the directory $ORG/$REPO.
  3. Clone the repository as a bare repo into .bare.
  4. Write a .git file that points to .bare.
  5. Add a main worktree.
  6. Generate gitworktree.sh for future worktree creation.

2. Add additional worktrees

cd $ORG/$REPO
./gitworktree.sh <branch-name>
  • <branch-name> can contain slashes, e.g., feat/new-feature → creates feat/new-feature/.
  • The script validates the branch name and runs git worktree add.

3. List worktrees

git worktree list

Reference Article

The script implements the "Worktrees level 2: bare repo" approach from Tom Ups' article, which explains how to keep a clean, flat directory structure while using multiple worktrees.


Feel free to open issues or submit pull requests if you have improvements!

#!/usr/bin/env sh
# setup-git-worktree.sh - Initialize a git worktree setup with bare repo
set -e
if [ -z "$1" ]; then
echo "Usage: $0 <git-url>"
echo "Examples:"
echo " $0 https://github.com/org/repo"
echo " $0 git@github.com:org/repo.git"
exit 1
fi
GIT_URL="$1"
# Parse org and repo from various git URL formats
parse_git_url() {
local url="$1"
# Remove trailing .git if present
url="${url%.git}"
# Handle SSH format: git@github.com:org/repo
if echo "$url" | grep -q "^git@"; then
echo "$url" | sed 's|^git@[^:]*:||'
return
fi
# Handle HTTPS format: https://github.com/org/repo
if echo "$url" | grep -q "^https://"; then
echo "$url" | sed 's|^https://[^/]*/||'
return
fi
# Handle HTTP format: http://github.com/org/repo
if echo "$url" | grep -q "^http://"; then
echo "$url" | sed 's|^http://[^/]*/||'
return
fi
echo "Error: Unrecognized git URL format" >&2
exit 1
}
ORG_REPO=$(parse_git_url "$GIT_URL")
ORG=$(echo "$ORG_REPO" | cut -d'/' -f1)
REPO=$(echo "$ORG_REPO" | cut -d'/' -f2)
echo "Organization: $ORG"
echo "Repository: $REPO"
echo "Creating directory structure at: $ORG/$REPO"
# Create directory structure
mkdir -p "$ORG/$REPO"
cd "$ORG/$REPO"
# Clone as bare repository
echo "Cloning bare repository..."
git clone --bare "$GIT_URL" .bare
# Create .git file pointing to .bare
echo "Creating .git reference file..."
echo "gitdir: ./.bare" > .git
# Configure remote fetch for bare repo
echo "Configuring remote fetch..."
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
# Create main worktree
echo "Creating main worktree..."
git worktree add main
# Create the gitworktree.sh helper script
echo "Creating gitworktree.sh helper script..."
cat > gitworktree.sh << 'HELPER_EOF'
#!/usr/bin/env sh
# gitworktree.sh - Create new git worktrees adjacent to main
set -e
# Check that we're in the right directory
if [ ! -d ".bare" ] || [ ! -f ".git" ]; then
echo "Error: .bare directory or .git file not found in current directory"
echo "This script must be run from the git worktree project root"
exit 1
fi
# Check for branch name argument
if [ -z "$1" ]; then
echo "Usage: $0 <branch-name>"
echo ""
echo "Examples:"
echo " $0 feature-x # Creates folder: feature-x/"
echo " $0 feat/whatever # Creates folder: feat/whatever/"
echo " $0 hotfix/bug-123 # Creates folder: hotfix/bug-123/"
echo ""
echo "Current worktrees:"
git worktree list
exit 1
fi
BRANCH_NAME="$1"
# Validate branch name characters
if ! echo "$BRANCH_NAME" | grep -qE '^[a-zA-Z0-9/_.-]+$'; then
echo "Error: Branch name contains invalid characters"
echo "Allowed: letters, numbers, dash, underscore, forward slash, dot"
exit 1
fi
# Create the worktree (folder will match branch name, preserving slashes)
echo "Creating worktree for branch: $BRANCH_NAME"
git worktree add "$BRANCH_NAME"
echo ""
echo "Worktree created successfully!"
echo "To switch to it: cd $BRANCH_NAME"
echo ""
echo "Current worktrees:"
git worktree list
HELPER_EOF
# Make the helper script executable
chmod +x gitworktree.sh
echo ""
echo "========================================="
echo "Setup complete!"
echo "========================================="
echo ""
echo "Directory structure:"
echo " $ORG/$REPO/"
echo " ├── .bare/ # Git database"
echo " ├── .git # Reference to .bare"
echo " ├── main/ # Main worktree"
echo " └── gitworktree.sh # Helper script"
echo ""
echo "To create new worktrees:"
echo " cd $ORG/$REPO"
echo " ./gitworktree.sh feature-name"
echo " ./gitworktree.sh feat/whatever"
echo ""
echo "Current worktrees:"
git worktree list
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment