Skip to content

Instantly share code, notes, and snippets.

@joncardasis
Last active September 8, 2026 18:32
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.

@sdrik

sdrik commented Jul 12, 2026

Copy link
Copy Markdown

Nice recipe !

Why cloning the bare repo to .bare and linking it with .git file instead of directly cloning it into .git ?

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