Skip to content

Instantly share code, notes, and snippets.

@joncardasis
Last active March 3, 2026 17:26
Show Gist options
  • Select an option

  • Save joncardasis/a08f2d5d4f2e576dc703b0638ef81218 to your computer and use it in GitHub Desktop.

Select an option

Save joncardasis/a08f2d5d4f2e576dc703b0638ef81218 to your computer and use it in GitHub Desktop.
Organizing Git Worktrees

Organizing Git Worktrees with Colocation

Colocated (or "bare repo + worktrees") pattern is one of the most popular and cleanest way to organize git worktrees. Here's how it works:

The Structure

myproject/              # Parent directory (not a checkout itself)
├── .bare/              # The bare git repo (the actual .git data)
├── .git                # A file (not dir) pointing to .bare
├── main/               # worktree checked out to main
├── feature-xyz/        # worktree for a feature branch
├── bugfix-123/         # worktree for a bugfix
└── review-pr-456/      # worktree for reviewing a PR

Setup Steps

1. Clone as a bare repo

mkdir myproject && cd myproject
git clone --bare git@github.com:user/repo.git .bare

2. Create a .git file pointing to .bare

echo "gitdir: ./.bare" > .git

3. Fix the fetch refspec (bare clones default to a refspec which won't track remote branches properly)

# Inside myproject/
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
git fetch origin

4. Add worktrees as siblings

git worktree add main main
git worktree add feature-xyz feature-xyz
# Or create a new branch:
git worktree add my-new-feature -b my-new-feature

Why This Pattern?

Benefit Explanation
Clean sibling layout All worktrees are peers in one directory — easy to ls and navigate
No "primary" checkout The bare repo has no working tree, so every branch is equal
Shared object store All worktrees share .bare/objects, so it's space-efficient
IDE-friendly Open each worktree folder independently in your editor
Easy cleanup git worktree remove feature-xyz and the folder is gone

Tips & Best Practices

Name folders after branches

# Slash branches? Use a flat name:
git worktree add fix-auth -b user/fix-auth

Use a helper function (shell alias)

# Add to .bashrc / .zshrc
gwa() {
  branch="$1"
  dir="${2:-$1}"
  git worktree add "$dir" -B "$branch"
}
# Usage: gwa my-feature

Keep a persistent main worktree

Always keep a main (or master) worktree around — it's useful for quick diffs, rebasing, or as a reference.

Ignore worktree dirs in your global gitignore

If your tooling gets confused, add the parent-level dirs to a local .gitignore (it won't be tracked since the bare repo has no working tree).

Cleanup stale worktrees

git worktree prune

Quick Reference

git worktree list          # See all active worktrees
git worktree add <dir> <branch>   # Add a new worktree
git worktree remove <dir>  # Remove a worktree
git worktree prune         # Clean up stale references

This colocated bare-repo approach is widely considered the "gold standard" for worktree organization — it avoids the messiness of having one "special" primary checkout while keeping everything uniform.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment