A CLI tool for managing git worktrees in a bare repository structure.
After setup, a project looks like this:
my-project/
.bare/ Bare git repository
.envrc Sets GIT_DIR=.bare for direnv
.worktree-copy Files to copy into new worktrees
.worktree-run Commands to run in new worktrees
<default-branch>/ Default worktree checkout (e.g. main, master)
The root .envrc sets GIT_DIR=.bare so git commands work from the project root. Each worktree has its own .envrc that unsets GIT_DIR so git operates on the worktree normally.
Clone a repository as a bare repo and create the worktree directory structure. If the directory is omitted, it is derived from the clone URL (e.g. repo.git becomes repo).
worktree setup git@github.com:user/repo.git
worktree setup git@github.com:user/repo.git my-project
This will:
- Clone the repo as a bare repository into
<directory>/.bare - Configure remote tracking refs (
refs/remotes/origin/*) and setorigin/HEAD - Create a
.envrcthat setsGIT_DIR=.bareand rundirenv allow - Create empty
.worktree-copyand.worktree-runconfig files - Add
.envrc,.worktree-copy, and.worktree-runto.bare/info/exclude - Check out the default branch as a worktree
Add a worktree for a new or existing branch. Must be run from within a bare repo setup.
worktree add my-feature
worktree add my-feature --from release-1.0
Branch resolution:
- If a local branch exists, the worktree is created for it
- If a remote branch (
origin/<branch>) exists, a local tracking branch is created - Otherwise, a new branch is created from the default branch (or from
--fromif specified)
After creating the worktree:
- Copy files listed in
.worktree-copyfrom the default branch worktree - Copy
.envrcfrom the default branch worktree and rundirenv allow - Run any commands listed in
.worktree-runinside the new worktree
| Flag | Description |
|---|---|
--from |
Create the new branch from this starting point instead of the default branch |
--no-copy |
Skip copying files from .worktree-copy |
--no-run |
Skip running commands from .worktree-run |
Open a worktree directory in your editor. Uses $EDITOR or $VISUAL.
worktree open my-feature
Run an arbitrary command in each worktree directory. By default, runs in all worktrees except the default branch.
worktree run "git pull"
worktree run "npm install" my-feature other-branch
worktree run --all "git status"
Pass worktree names as additional arguments to target specific worktrees. The command continues through failures and reports all failed worktrees at the end.
| Flag | Description |
|---|---|
--all |
Include the default branch worktree |
Show a summary of all worktrees including uncommitted changes and ahead/behind status relative to remote tracking branches.
worktree status
Example output:
feature-a feature-a (1 uncommitted change)
feature-b feature-b (ahead 1)
feature-c feature-c (clean, up to date)
hotfix hotfix (no remote)
Does not fetch from the remote — run worktree fetch first to ensure tracking information is current.
Fetch from the remote and show which worktrees are ahead of or behind their remote tracking branches.
worktree fetch
worktree fetch --no-fetch
This will:
- Run
git fetch --pruneonce in the bare repo - Display ahead/behind counts for each worktree branch relative to
origin
| Flag | Description |
|---|---|
--no-fetch |
Skip fetching and just show tracking status |
Remove a worktree. Must be run from within a bare repo setup.
worktree remove my-feature
worktree remove --include-branch my-feature
worktree remove --force --include-branch my-feature
| Flag | Description |
|---|---|
--include-branch |
Also delete the branch (uses git branch -d) |
--force |
Force remove worktree (even with uncommitted changes) and use git branch -D if --include-branch is set |
- direnv - Used to automatically set/unset
GIT_DIRwhen entering worktree directories. Must be installed and hooked into your shell.
A list of files, directories, or symlinks (one per line) to copy from the default branch worktree into each new worktree. Lines starting with # and blank lines are ignored. For example:
.env
config/local.yaml
A list of shell commands (one per line) to run inside each new worktree after creation. Lines starting with # and blank lines are ignored. For example:
npm install
cp .env.example .env
Security note: This tool is designed for personal dev environments, not shared ones. .worktree-copy and .worktree-run are local configuration files and should not be committed or shared. Commands in .worktree-run are executed via sh -c with no sandboxing.