<style> :root { --neon-cyan: #0ff; --neon-magenta: #f0f; --neon-yellow: #ff0; --neon-green: #0f0; --bg-color: #0d0d0d; --text-color: #e0e0e0; } body { background-color: var(--bg-color) !important; color: var(--text-color) !important; font-family: 'Fira Code', 'Courier New', Courier, monospace !important; } #doc.markdown-body { background-color: var(--bg-color) !important; color: var(--text-color) !important; } h1, h2, h3 { color: var(--neon-cyan) !important; text-shadow: 0 0 5px var(--neon-cyan), 0 0 10px var(--neon-cyan) !important; border-bottom: 1px solid var(--neon-magenta) !important; } a { color: var(--neon-magenta) !important; text-decoration: none !important; } a:hover { text-shadow: 0 0 5px var(--neon-magenta) !important; } code { background-color: #1a1a1a !important; color: var(--neon-yellow) !important; border: 1px solid var(--neon-yellow) !important; } pre { background-color: #121212 !important; border-left: 5px solid var(--neon-green) !important; box-shadow: 0 0 10px rgba(0, 255, 0, 0.2) !important; } blockquote { border-left: 5px solid var(--neon-cyan) !important; background-color: rgba(0, 255, 255, 0.05) !important; color: var(--neon-cyan) !important; } strong { color: var(--neon-magenta) !important; } hr { border-top: 1px solid var(--neon-cyan) !important; opacity: 0.5; } table { border-collapse: collapse !important; width: 100% !important; background-color:var(--bg-color) !important; border: 1px solid var(--neon-cyan) !important; } th { background-color:var(--bg-color) !important; color: var(--neon-cyan) !important; } td, th { border: 1px solid var(--neon-cyan) !important; background-color:var(--bg-color) !important; padding: 8px !important; } /* Scrollbar */ ::-webkit-scrollbar { width: 10px; } ::-webkit-scrollbar-track { background: #000; } ::-webkit-scrollbar-thumb { background: var(--neon-cyan); border-radius: 5px; } </style> # Git Worktree Complete Guide ## What is Git Worktree? Git worktree lets you check out **multiple branches** from the same repository into **separate directories** simultaneously. Each worktree is an independent working copy with its own branch, staging area, and working files. ### Why Use It? - Work on a **bugfix** while keeping your feature branch intact - Review someone **else's** PR without stashing your changes - Run two branches side-by-side for comparison - Build/test different branches in parallel - No need to stash or commit incomplete work to switch branches --- ## How It Works ``` .git/ ← Single shared repository (objects, refs, config) ├── worktrees/ ← Metadata for each linked worktree │ ├── branch-a/ │ └── branch-b/ ├── HEAD ← Points to the MAIN worktree's branch ├── refs/ └── config ../project-main/ ← Main worktree (on branch: main) ../project-feature/ ← Linked worktree (on branch: feature-x) ../project-hotfix/ ← Linked worktree (on branch: hotfix-y) ``` All worktrees share the same `.git/objects` database — no duplication of history. --- ## Commands ### 1. Create a Worktree ```bash # Create and check out a new branch git worktree add <path> <branch> # Create and check out an existing branch git worktree add <path> <existing-branch> # Create a new branch and check it out git worktree add -b <new-branch> <path> # Create with detached HEAD git worktree add --detach <path> # Create with specific commit git worktree add <path> <commit-hash> ``` **Examples:** ```bash # New branch "feature/auth" at ../project-feature git worktree add ../project-feature -b feature/auth # Check out existing branch "main" at ../project-main-review git worktree add ../project-main-review main # Detached HEAD at a specific commit git worktree add --detach ../project-review abc1234 ``` ### 2. List Worktrees ```bash git worktree list ``` **Output:** ``` /path/to/project-main a1b2c3d [main] /path/to/project-feature e4f5g6h [feature/auth] /path/to/project-hotfix i7j8k9l [hotfix/login] ``` ### 3. Remove a Worktree ```bash # Remove (must be clean — no uncommitted changes) git worktree remove <path> # Force remove (discards uncommitted changes) git worktree remove --force <path> # Prune stale worktree entries (if directory was deleted manually) git worktree prune ``` **Examples:** ```bash git worktree remove ../project-feature git worktree remove -f ../project-hotfix ``` ### 4. Lock / Unlock a Worktree Locking prevents a worktree from being pruned or accidentally removed. ```bash # Lock a worktree git worktree lock <path> # Lock with a reason git worktree lock --reason "In use for production debugging" <path> # Unlock a worktree git worktree unlock <path> ``` ### 5. Move a Worktree ```bash # Move to a new location git worktree move <path> <new-path> ``` **Example:** ```bash git worktree move ../project-feature ../new-location/project-feature ``` ### 6. Repair a Worktree If the link between a worktree and the main `.git` directory is broken: ```bash git worktree repair ``` ### 7. Clean Up Stale Entries If you deleted a worktree directory manually (without `git worktree remove`): ```bash git worktree prune ``` --- ## Common Workflows ### Workflow 1: Quick Bugfix While Working on a Feature ```bash # You're on feature/auth, need to fix a production bug git worktree add ../project-hotfix main cd ../project-hotfix git checkout -b hotfix/critical-bug # ... make fix, commit, push ... cd ../project-main git worktree remove ../project-hotfix ``` ### Workflow 2: Review a Pull Request ```bash # Fetch the PR branch git fetch origin pull/123/head:pr-123 # Create a worktree to review it git worktree add ../project-pr-review pr-123 cd ../project-pr-review # Review, test, etc. cd ../project-main git worktree remove ../project-pr-review git branch -D pr-123 ``` ### Workflow 3: Parallel Builds / Tests ```bash # Main worktree on main branch git worktree add ../project-bench -b benchmark/experiment cd ../project-bench # Run benchmarks while continuing development in main worktree ``` ### Workflow 4: Bisect Without Losing Your Place ```bash # Start bisect in a separate worktree git worktree add ../project-bisect cd ../project-bisect git bisect start git bisect bad <commit> git bisect good <commit> # ... test commits ... git bisect reset cd ../project-main git worktree remove ../project-bisect ``` --- ## Rules and Limitations 1. **Same branch cannot be checked out in multiple worktrees** (unless using `--force`) 2. **Bare repositories** are recommended as the main repo when using many worktrees 3. **Git submodules** have limited support in worktrees 4. **Ignored files**: Each worktree has its own `.git/info/exclude` but shares `.gitignore` 5. **Hooks**: All worktrees share the same hooks from the main `.git/hooks/` 6. **Config**: Shared across all worktrees (use `git worktree config` for per-worktree settings) --- ## Per-Worktree Configuration ```bash # Set a config value for a specific worktree git worktree config set <key> <value> # Example: different user.email per worktree git worktree config set user.email "review@company.com" ``` --- ## Bare Repository Pattern (Recommended for Heavy Use) If you use worktrees frequently, convert your repo to bare: ```bash # Clone as bare git clone --bare git@github.com:user/repo.git ~/projects/repo.git # Create worktrees from bare repo cd ~/projects/repo.git git worktree add ../main main git worktree add ../feature -b feature/new-ui # Structure: # ~/projects/repo.git/ ← bare repo (no working files) # ~/projects/main/ ← worktree on main # ~/projects/feature/ ← worktree on feature/new-ui ``` --- ## Troubleshooting ### "branch is already checked out" Another worktree has this branch. Use a different branch or: ```bash git worktree add --force <path> <branch> ``` ### Stale worktree entries after manual deletion ```bash git worktree prune ``` ### Broken worktree links ```bash git worktree repair ``` ### Cannot remove worktree with uncommitted changes Commit or stash first, or force remove: ```bash git worktree remove --force <path> ``` --- ## Quick Reference Card | Command | Description | | :--- | :--- | | `git worktree add` | Create a new worktree | | `git worktree add -b` | Create + new branch | | `git worktree add --detach` | Create with detached HEAD | | `git worktree list` | Show all worktrees | | `git worktree remove` | Delete a worktree | | `git worktree remove -f` | Force delete a worktree | | `git worktree lock` | Lock a worktree | | `git worktree unlock` | Unlock a worktree | | `git worktree move` | Move a worktree | | `git worktree prune` | Clean stale entries | | `git worktree repair` | Fix broken links | --- ## Tips - Use **absolute paths** or paths **outside** the main repo directory - Name worktree directories clearly (e.g., `../project-hotfix`, not `../wt1`) - Combine with `git stash` if you need to share uncommitted changes between worktrees - IDE support: most IDEs (VS Code, WebStorm) handle worktrees well — just open the worktree directory as a separate window