Skip to content

Instantly share code, notes, and snippets.

@programaker
Last active May 28, 2026 10:51
Show Gist options
  • Select an option

  • Save programaker/37cac1aaabce5a6c80777b290b8a1c6c to your computer and use it in GitHub Desktop.

Select an option

Save programaker/37cac1aaabce5a6c80777b290b8a1c6c to your computer and use it in GitHub Desktop.
Script to clone or init a repository in a git-worktree setup
#!/bin/zsh
# Usage:
# gitwt -c <git-uri> Clone an existing repo into a worktree setup
# gitwt -n <project-name> Create a new project from scratch with worktree setup
# gitwt -b <branch-name> [<base-branch>] Create a new worktree with a new branch (run from project root)
# Optionally base the new branch on <base-branch>. Pass it exactly as you
# want git to resolve it (e.g. 'develop' for the local branch, or
# 'origin/develop' for the remote-tracking ref). If omitted, git's default
# behavior applies (branch from HEAD).
# gitwt <branch-name> Create a worktree for an existing branch (run from project root)
#
# Examples:
# gitwt -c git@github.com:commercetools/the-repo-i-want-to-clone.git
# gitwt -n my-new-project
# gitwt -b my-feature-branch
# gitwt -b my-feature-branch develop
# gitwt -b my-feature-branch origin/develop
# gitwt some-existing-branch
set -euo pipefail
function usage() {
echo "Usage:"
echo " gitwt -c <git-uri> Clone a repo into a worktree setup"
echo " gitwt -n <project-name> Create a new project with worktree setup"
echo " gitwt -b <branch-name> [<base-branch>] Create a new worktree with a new branch"
echo " (optionally based on <base-branch>, passed as-is to git;"
echo " if omitted, git branches from HEAD)"
echo " gitwt <branch-name> Create a worktree for an existing branch"
echo ""
echo "Examples:"
echo " gitwt -c git@github.com:org/repo.git"
echo " gitwt -n my-new-project"
echo " gitwt -b my-feature-branch"
echo " gitwt -b my-feature-branch develop"
echo " gitwt -b my-feature-branch origin/develop"
echo " gitwt some-existing-branch"
}
function check_dir() {
local name="$1"
if [[ -d "$name" ]]; then
echo "Error: directory '$name' already exists"
exit 1
fi
}
function link_bare() {
echo "gitdir: ./.bare" > .git
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
}
function create_project() {
local project_name="$1"
local default_branch="main"
local worktree_dir="${project_name}_${default_branch}"
check_dir "$project_name"
echo "Creating new worktree project '$project_name'..."
mkdir "$project_name"
cd "$project_name"
git init --bare .bare
link_bare
git worktree add "$worktree_dir" -b "$default_branch"
echo ""
echo "Done! Your worktree project is ready:"
echo " $project_name/"
echo " .bare/ (git database)"
echo " .git (pointer to .bare)"
echo " $worktree_dir/ (worktree on $default_branch branch)"
echo ""
echo "Next steps:"
echo " cd $project_name/$worktree_dir"
echo " have fun!"
}
function clone_repo() {
local uri="$1"
# Extract repo name from URI
# Handles both SSH (git@github.com:org/repo.git) and HTTPS (https://github.com/org/repo.git)
local repo_name="${uri:t:r}"
if [[ -z "$repo_name" ]]; then
echo "Error: could not extract repository name from '$uri'"
exit 1
fi
check_dir "$repo_name"
echo "Setting up bare worktree repo for '$repo_name'..."
mkdir "$repo_name"
cd "$repo_name"
git clone --bare "$uri" .bare
link_bare
local default_branch=$(git -C .bare symbolic-ref --short HEAD)
local worktree_dir="${repo_name}_${default_branch}"
git worktree add "$worktree_dir" "$default_branch"
git branch --set-upstream-to="origin/$default_branch" "$default_branch"
echo ""
echo "Done! Your worktree repo is ready:"
echo " $repo_name/"
echo " .bare/ (git database)"
echo " .git (pointer to .bare)"
echo " $worktree_dir/ (worktree on $default_branch branch)"
echo ""
echo "Next steps:"
echo " cd $repo_name/$worktree_dir"
echo " have fun!"
}
function create_branch_worktree() {
local branch_name="$1"
local base_branch="${2:-}"
if [[ ! -d ".bare" ]]; then
echo "Error: not inside a gitwt project (no .bare directory found)"
exit 1
fi
local worktree_dir="${branch_name}"
check_dir "$worktree_dir"
echo "Fetching origin..."
git fetch origin
if [[ -n "$base_branch" ]]; then
echo "Creating worktree for branch '$branch_name' based on '$base_branch'..."
git worktree add "$worktree_dir" -b "$branch_name" "$base_branch"
else
echo "Creating worktree for branch '$branch_name'..."
git worktree add "$worktree_dir" -b "$branch_name"
fi
echo ""
echo "Done! New worktree ready:"
if [[ -n "$base_branch" ]]; then
echo " $worktree_dir/ (worktree on $branch_name branch, based on $base_branch)"
else
echo " $worktree_dir/ (worktree on $branch_name branch)"
fi
}
function checkout_branch_worktree() {
local branch_name="$1"
if [[ ! -d ".bare" ]]; then
echo "Error: not inside a gitwt project (no .bare directory found)"
exit 1
fi
local worktree_dir="${branch_name}"
check_dir "$worktree_dir"
echo "Fetching origin..."
git fetch origin
echo "Creating worktree for existing branch '$branch_name'..."
git worktree add "$worktree_dir" "$branch_name"
echo ""
echo "Done! New worktree ready:"
echo " $worktree_dir/ (worktree on $branch_name branch)"
}
# --- Main ---
if [[ $# -eq 2 && "$1" == "-b" ]]; then
create_branch_worktree "$2"
elif [[ $# -eq 3 && "$1" == "-b" ]]; then
create_branch_worktree "$2" "$3"
elif [[ $# -eq 2 && "$1" == "-n" ]]; then
create_project "$2"
elif [[ $# -eq 2 && "$1" == "-c" ]]; then
clone_repo "$2"
elif [[ $# -eq 1 && "$1" != -* ]]; then
checkout_branch_worktree "$1"
else
usage
exit 1
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment