From d01b5db9053e379f169a86a245d6ee49ce714477 Mon Sep 17 00:00:00 2001 From: Elijah Voigt Date: Tue, 24 Feb 2026 14:49:54 -0800 Subject: [PATCH] docs(edu): write git worktrees reference; update project status Mark git worktrees and Markov Chains as complete in PROJECTS.md. Co-Authored-By: Claude Sonnet 4.6 --- PROJECTS.md | 6 +- edu/git-worktrees.md | 170 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 edu/git-worktrees.md diff --git a/PROJECTS.md b/PROJECTS.md index 47a6934..95d2cc2 100644 --- a/PROJECTS.md +++ b/PROJECTS.md @@ -1,7 +1,7 @@ # TODO ## Tools -- [ ] `nbd` agent tasks management cli +- [x] `nbd` agent tasks management cli ## Projects - [ ] QuotesDB website @@ -14,9 +14,9 @@ - [ ] Local-first app development ## Interactive Learning and Education -- [ ] Git worktrees, how do use please +- [x] Git worktrees, how do use please - [ ] How to structure a co-op profit sharing worker owned business -- [ ] Hands-on: Markov Chains +- [x] Hands-on: Markov Chains - [ ] Hands-on: Vector Databases - [ ] Hands-on: Creating and training a simple LLM - [ ] Hands-on: Writing your own language (lisp, interpreted, compiled to C) diff --git a/edu/git-worktrees.md b/edu/git-worktrees.md new file mode 100644 index 0000000..0cb3310 --- /dev/null +++ b/edu/git-worktrees.md @@ -0,0 +1,170 @@ +# Git Worktrees + +## What Are They? + +A git worktree is a checked-out copy of a branch that lives in a separate directory on your filesystem, but shares the same underlying git repository (`.git` database) as your main clone. + +Normally, a single git clone has one working directory — the files you see and edit. A worktree lets you have **multiple working directories at once**, each on a different branch, all tied to the same repository. You don't clone the repo a second time; you project a second (or third, or fourth) working directory from the one clone. + +``` +~/.git/ ← shared: all objects, refs, config +~/projects/myapp/ ← main worktree (branch: main) +~/projects/myapp-feature/ ← linked worktree (branch: feature/auth) +~/projects/myapp-hotfix/ ← linked worktree (branch: hotfix/crash) +``` + +All three directories above read and write to the same `.git` object store. Commits made in any worktree are immediately visible to all others. + +--- + +## Core Commands + +### Add a worktree + +```sh +# Check out an existing branch into a new directory +git worktree add ../myapp-feature feature/auth + +# Create a new branch and check it out in one step +git worktree add -b feature/new-thing ../myapp-new-thing main +``` + +The first argument is the path for the new directory. The second is the branch name (or starting commit). + +### List worktrees + +```sh +git worktree list +``` + +Example output: + +``` +/home/you/projects/myapp abc1234 [main] +/home/you/projects/myapp-feature def5678 [feature/auth] +``` + +### Remove a worktree + +```sh +# Remove the directory and deregister the worktree +git worktree remove ../myapp-feature + +# Force-remove even if there are untracked or modified files +git worktree remove --force ../myapp-feature +``` + +After deleting a linked worktree directory manually (e.g. with `rm -rf`), git still knows about it. Clean up the stale reference with: + +```sh +git worktree prune +``` + +### Move a worktree + +```sh +git worktree move ../myapp-feature ../myapp-auth-feature +``` + +--- + +## Typical Workflows + +### Work on two branches simultaneously + +You're deep in a feature branch when a urgent bug report comes in. Instead of stashing your work or committing a WIP, you add a worktree: + +```sh +git worktree add ../myapp-hotfix main +cd ../myapp-hotfix +# fix the bug, commit, push — then come back to your feature +``` + +Your feature working directory is untouched. + +### Run tests against a different branch without switching + +```sh +git worktree add /tmp/myapp-test origin/release/2.0 +cd /tmp/myapp-test +cargo test +``` + +You keep your editor open on `main` while tests run elsewhere. + +### Review a colleague's PR locally + +```sh +git fetch origin +git worktree add ../review-pr-123 origin/pr/123 +cd ../review-pr-123 +# read, run, evaluate — then remove when done +git worktree remove ../review-pr-123 +``` + +--- + +## How It Works Internally + +When you run `git worktree add`, git: + +1. Creates a subdirectory inside `.git/worktrees//` to store the worktree's private state (its `HEAD`, index, and a back-reference to the working directory path). +2. Writes a `.git` *file* (not a directory) into the new working directory that points back to `.git/worktrees//`. +3. Checks out the requested branch into the new directory. + +The object database (all commits, trees, blobs) is shared. Only the index and `HEAD` are per-worktree. + +--- + +## Limitations and When to Avoid Them + +### Each branch can only be checked out once + +The most important constraint: **a single branch cannot be checked out in two worktrees at the same time.** Git enforces this to prevent the two trees from diverging their indexes silently. If you try, you'll get an error: + +``` +fatal: 'feature/auth' is already checked out at '/home/you/projects/myapp' +``` + +Workaround: check out the second worktree at a specific commit (detached HEAD), or create a local tracking branch. + +### Tools that look for `.git` as a directory can break + +Some tools assume `.git` is a directory, not a file. A linked worktree has a `.git` *file* instead, which confuses: + +- Older git GUIs that scan for `.git/` directories +- Some shell prompts and plugins that detect git repos naively +- Scripts that do `test -d .git` + +### Build systems that use the working directory path + +If your build system or language tooling caches absolute paths (e.g. Cargo's `target/` directory is placed relative to the workspace root), separate worktrees work fine — each has its own `target/` directory. But if a tool bakes the source path into cached artifacts, switching between worktrees may cause spurious rebuilds or cache invalidation. + +### Hooks run in the worktree context, not the main repo + +Git hooks in `.git/hooks/` apply to all worktrees. But the working directory (`$GIT_WORK_TREE`) will be the linked worktree path, not the main repo path. Hook scripts that assume a fixed working directory can behave unexpectedly. + +### Not a substitute for branches in CI + +Worktrees are a local developer convenience. Don't model CI pipelines around them — use proper branch checkouts in ephemeral CI environments instead. + +### Submodules require extra care + +Submodules are not automatically initialized in a new worktree. You need to run `git submodule update --init` inside each linked worktree where you need them. + +### Avoid for long-lived parallel development + +If you find yourself maintaining two worktrees of the same repo for weeks at a time, that's a signal you might want two separate clones or a proper branch strategy — not worktrees. Worktrees shine for short-lived parallel work (hotfixes, reviews, quick tests), not as a permanent parallel development setup. + +--- + +## Quick Reference + +| Task | Command | +|---|---| +| Add a worktree for an existing branch | `git worktree add ` | +| Add a worktree and create a new branch | `git worktree add -b ` | +| List all worktrees | `git worktree list` | +| Remove a worktree | `git worktree remove ` | +| Clean up stale worktree records | `git worktree prune` | +| Move a worktree | `git worktree move ` |