refactor(skills): retrofit the corpus to the ADR-0020 context contract #129

Merged
Defame1297 merged 89 commits from refactor/adr0020-skill-retrofit into main 2026-09-01 13:47:47 +00:00
4 changed files with 106 additions and 26 deletions
Showing only changes of commit ddf85518c7 - Show all commits

View File

@@ -24,18 +24,19 @@ metadata:
| Operation | Run | | Operation | Run |
|---|---| |---|---|
| Create on an existing branch | `git worktree add <path> <branch>` | | Create on a branch that already exists locally | `git worktree add <path> <branch>` |
| Create on a new branch | `git worktree add -b <branch> <path>` | | Create on a new branch | `git worktree add -b <branch> <path>` |
| Create on the branch named after the path basename | `git worktree add <path>` — checks that branch out if it exists, else creates it from HEAD | | Create on the branch named after the path basename | `git worktree add <path>` — checks that branch out if it exists, else creates it from HEAD |
| Create and reset an existing branch to HEAD — discards its commits | `git worktree add -B <branch> <path>` | | Create and reset an existing branch to HEAD — discards its commits | `git worktree add -B <branch> <path>` |
| Create tracking a remote branch | `git worktree add <path> <remote>/<branch>` | | Create a local branch tracking a remote one | `git worktree add --track -b <branch> <path> <remote>/<branch>` — always correct. `git worktree add <path> <branch>` expands to exactly this, but **only** when `<branch>` has no local copy (gate below) |
| Throwaway experiment, no branch | `git worktree add -d <path>` | | Throwaway experiment, no branch | `git worktree add -d <path>` — detached HEAD |
| **Never** `git worktree add <path> <remote>/<branch>` | That ref resolves, so the shortcut never fires and you get **a detached HEAD, no branch, no upstream**. Commits there go unreachable once HEAD moves, and `git push` needs an explicit refspec. Use the tracking row above |
| List | `git worktree list -v`, or `--porcelain -z` to parse | | List | `git worktree list -v`, or `--porcelain -z` to parse |
| Lock or unlock | `git worktree lock [--reason <str>] <path>` / `git worktree unlock <path>` | | Lock or unlock | `git worktree lock [--reason <str>] <path>` / `git worktree unlock <path>` |
| Move | `git worktree move <from> <to>` | | Move | `git worktree move <from> <to>` |
| Remove | `git worktree remove <path>` | | Remove | `git worktree remove <path>` |
| Prune stale metadata | `git worktree prune --dry-run`, then without the flag | | Prune stale metadata | `git worktree prune --dry-run`, then without the flag |
| Repair after a manual move | `git worktree repair [<path>]` — from the main worktree to fix all links, or from the moved worktree itself | | Repair after a manual move | `git worktree repair` — in the main worktree if *it* moved, or inside a linked worktree that moved. `git worktree repair <path>...` — from any worktree, naming each moved linked worktree's new path |
If the operation needs anything the table does not carry — the full `add` flag If the operation needs anything the table does not carry — the full `add` flag
table, orphan branches, sparse-checkout, locking for removable media, remote table, orphan branches, sparse-checkout, locking for removable media, remote
@@ -47,6 +48,7 @@ Gates:
- **`move`, `remove` — the main worktree cannot be moved or removed.** Only linked worktrees, the ones `git worktree add` created, are candidates. - **`move`, `remove` — the main worktree cannot be moved or removed.** Only linked worktrees, the ones `git worktree add` created, are candidates.
- **`add`, `move`, `remove` — escalate force flags one step at a time.** `-f` overrides a safeguard such as an unclean tree; `move` and `remove` need `-ff` on top of that when the worktree is locked. Confirm with the user before either — both discard state. - **`add`, `move`, `remove` — escalate force flags one step at a time.** `-f` overrides a safeguard such as an unclean tree; `move` and `remove` need `-ff` on top of that when the worktree is locked. Confirm with the user before either — both discard state.
- **`lock`, `move`, `remove`, `repair` — identify a worktree by full path, unique basename, or unique partial path.** An ambiguous name errors rather than picking; `git worktree list` shows the usable identifiers. - **`lock`, `move`, `remove`, `repair` — identify a worktree by full path, unique basename, or unique partial path.** An ambiguous name errors rather than picking; `git worktree list` shows the usable identifiers.
- **`add` — the bare-name tracking shortcut needs exactly one remote.** `git worktree add <path> <branch>` sets up tracking only when `<branch>` is absent locally, no `-b`/`-B`/`-d` is given, and exactly one remote carries the name. With several, it fires only if `checkout.defaultRemote` names one. When the remote is ambiguous or unknown, use `--track -b`.
- **`add` — lock at creation, not after.** `git worktree add --lock` is atomic, where add-then-`lock` leaves a window in which the worktree is unprotected. - **`add` — lock at creation, not after.** `git worktree add --lock` is atomic, where add-then-`lock` leaves a window in which the worktree is unprotected.
## Step 2 — Report ## Step 2 — Report

View File

@@ -15,16 +15,29 @@ or moved. Every other worktree is a **linked worktree** created by `git worktree
## `add` forms ## `add` forms
```bash ```bash
git worktree add <path> <branch> # check out an existing branch — non-destructive git worktree add <path> <branch> # <branch> exists locally: check it out — non-destructive
git worktree add -b <branch> <path> # create a new branch; fails if it exists git worktree add -b <branch> <path> # create a new branch; fails if it exists
git worktree add <path> # branch named after $(basename <path>): checked out git worktree add <path> # branch named after $(basename <path>): checked out
# if it exists, else created from HEAD # if it exists, else created from HEAD
git worktree add -B <branch> <path> # create the branch, or reset an existing one to HEAD, git worktree add -B <branch> <path> # create the branch, or reset an existing one to HEAD,
# discarding the commits it carried # discarding the commits it carried
git worktree add <path> <remote>/<branch> # track a remote branch git worktree add --track -b <branch> <path> <remote>/<branch>
# new local branch tracking the remote — always works
git worktree add <path> <branch> # <branch> absent locally and in exactly one remote:
# Git expands this to the --track -b form above
git worktree add -d <path> # detached HEAD, no branch git worktree add -d <path> # detached HEAD, no branch
``` ```
The same `git worktree add <path> <branch>` spelling appears twice above and does two
different things: it checks out a local branch when one exists, and only otherwise falls
through to the remote-tracking shortcut. Read the local branch list before relying on either.
**Do not write `git worktree add <path> <remote>/<branch>`.** A remote-tracking ref resolves as a
commit-ish, so the tracking shortcut never fires and the worktree lands on a **detached HEAD with
no local branch and no upstream** — commits there go unreachable once HEAD moves or the worktree is
removed, and `git push` fails without an explicit refspec. That spelling is correct only as the
final argument of the `--track -b` form.
## Full `add` flag table ## Full `add` flag table
| Flag | Meaning | | Flag | Meaning |
@@ -69,19 +82,40 @@ git worktree unlock <path> # when reconnected
## Remote-branch disambiguation ## Remote-branch disambiguation
```bash ```bash
git worktree add <path> <remote>/<branch> git worktree add --track -b <branch> <path> <remote>/<branch> # explicit: no guessing at all
git worktree add <path> <branch> # shortcut: needs one clear remote
``` ```
For ambiguous names across remotes, `checkout.defaultRemote` config disambiguates explicitly, or `--guess-remote` auto-matches by path basename (default controlled by `worktree.guessRemote` config). If a branch name matches multiple remotes during `worktree add` and neither is set, Git refuses rather than guessing. The shortcut fires only when `<branch>` is not found locally, none of `-b`/`-B`/`--detach` were
given, and a tracking branch of that name exists in exactly one remote. When several remotes carry
the name, `checkout.defaultRemote` picks one for disambiguation purposes; with no such setting the
shortcut has no single remote to resolve against and does not apply.
`--guess-remote` covers the *other* spelling — `git worktree add <path>` with no `<commit-ish>` at
all. It bases the new branch on the remote-tracking branch matching `$(basename <path>)` when
exactly one remote has it, and marks that branch as upstream. Its default comes from the
`worktree.guessRemote` config.
## Repair after a manual move ## Repair after a manual move
```bash ```bash
git worktree repair # run from the main worktree: fixes the links to every linked worktree git worktree repair # the MAIN worktree moved: run it there to reconnect every linked
git worktree repair <path> # run from a moved linked worktree: fixes its own pointer back to main # worktree back to the main worktree
git worktree repair # a LINKED worktree moved: run it inside that recently-moved worktree
git worktree repair <path>... # reconnect a specific linked worktree — runnable from any worktree,
# naming each moved tree's new path
``` ```
`repair` reestablishes the bidirectional pointers a manual move breaks, but only for the side it is Which form applies depends on what moved:
run from. Run it from the wrong directory and it reports nothing and fixes nothing.
| What moved | Remedy |
|---|---|
| The main worktree (or bare repo) | `git worktree repair` in the main worktree |
| One linked worktree | `git worktree repair` inside that worktree |
| Several linked worktrees | `git worktree repair <path>...` from any worktree, listing each new path |
| Both main and linked worktrees | `git worktree repair <path>...` in the main worktree, naming each linked worktree's new path — this restores the connections in both directions |
Only the no-argument form is tied to the current directory. The `<path>...` form is not — it
reestablishes the connection to every path you name, run from any worktree.
## Configuration ## Configuration
@@ -111,6 +145,10 @@ git worktree remove ../temp
context switch: context switch:
```bash ```bash
git worktree add ../review-pr-123 origin/feature-xyz git worktree add ../review-pr-123 origin/feature-xyz # detached HEAD — read-only review
git worktree add --track -b feature-xyz ../review-pr-123 origin/feature-xyz # if you will commit
# open ../review-pr-123 in a second editor window or terminal # open ../review-pr-123 in a second editor window or terminal
``` ```
Pick the second form the moment you intend to push anything back: the first leaves no branch to
push and no upstream to push to.

View File

@@ -24,18 +24,19 @@ metadata:
| Operation | Run | | Operation | Run |
|---|---| |---|---|
| Create on an existing branch | `git worktree add <path> <branch>` | | Create on a branch that already exists locally | `git worktree add <path> <branch>` |
| Create on a new branch | `git worktree add -b <branch> <path>` | | Create on a new branch | `git worktree add -b <branch> <path>` |
| Create on the branch named after the path basename | `git worktree add <path>` — checks that branch out if it exists, else creates it from HEAD | | Create on the branch named after the path basename | `git worktree add <path>` — checks that branch out if it exists, else creates it from HEAD |
| Create and reset an existing branch to HEAD — discards its commits | `git worktree add -B <branch> <path>` | | Create and reset an existing branch to HEAD — discards its commits | `git worktree add -B <branch> <path>` |
| Create tracking a remote branch | `git worktree add <path> <remote>/<branch>` | | Create a local branch tracking a remote one | `git worktree add --track -b <branch> <path> <remote>/<branch>` — always correct. `git worktree add <path> <branch>` expands to exactly this, but **only** when `<branch>` has no local copy (gate below) |
| Throwaway experiment, no branch | `git worktree add -d <path>` | | Throwaway experiment, no branch | `git worktree add -d <path>` — detached HEAD |
| **Never** `git worktree add <path> <remote>/<branch>` | That ref resolves, so the shortcut never fires and you get **a detached HEAD, no branch, no upstream**. Commits there go unreachable once HEAD moves, and `git push` needs an explicit refspec. Use the tracking row above |
| List | `git worktree list -v`, or `--porcelain -z` to parse | | List | `git worktree list -v`, or `--porcelain -z` to parse |
| Lock or unlock | `git worktree lock [--reason <str>] <path>` / `git worktree unlock <path>` | | Lock or unlock | `git worktree lock [--reason <str>] <path>` / `git worktree unlock <path>` |
| Move | `git worktree move <from> <to>` | | Move | `git worktree move <from> <to>` |
| Remove | `git worktree remove <path>` | | Remove | `git worktree remove <path>` |
| Prune stale metadata | `git worktree prune --dry-run`, then without the flag | | Prune stale metadata | `git worktree prune --dry-run`, then without the flag |
| Repair after a manual move | `git worktree repair [<path>]` — from the main worktree to fix all links, or from the moved worktree itself | | Repair after a manual move | `git worktree repair` — in the main worktree if *it* moved, or inside a linked worktree that moved. `git worktree repair <path>...` — from any worktree, naming each moved linked worktree's new path |
If the operation needs anything the table does not carry — the full `add` flag If the operation needs anything the table does not carry — the full `add` flag
table, orphan branches, sparse-checkout, locking for removable media, remote table, orphan branches, sparse-checkout, locking for removable media, remote
@@ -47,6 +48,7 @@ Gates:
- **`move`, `remove` — the main worktree cannot be moved or removed.** Only linked worktrees, the ones `git worktree add` created, are candidates. - **`move`, `remove` — the main worktree cannot be moved or removed.** Only linked worktrees, the ones `git worktree add` created, are candidates.
- **`add`, `move`, `remove` — escalate force flags one step at a time.** `-f` overrides a safeguard such as an unclean tree; `move` and `remove` need `-ff` on top of that when the worktree is locked. Confirm with the user before either — both discard state. - **`add`, `move`, `remove` — escalate force flags one step at a time.** `-f` overrides a safeguard such as an unclean tree; `move` and `remove` need `-ff` on top of that when the worktree is locked. Confirm with the user before either — both discard state.
- **`lock`, `move`, `remove`, `repair` — identify a worktree by full path, unique basename, or unique partial path.** An ambiguous name errors rather than picking; `git worktree list` shows the usable identifiers. - **`lock`, `move`, `remove`, `repair` — identify a worktree by full path, unique basename, or unique partial path.** An ambiguous name errors rather than picking; `git worktree list` shows the usable identifiers.
- **`add` — the bare-name tracking shortcut needs exactly one remote.** `git worktree add <path> <branch>` sets up tracking only when `<branch>` is absent locally, no `-b`/`-B`/`-d` is given, and exactly one remote carries the name. With several, it fires only if `checkout.defaultRemote` names one. When the remote is ambiguous or unknown, use `--track -b`.
- **`add` — lock at creation, not after.** `git worktree add --lock` is atomic, where add-then-`lock` leaves a window in which the worktree is unprotected. - **`add` — lock at creation, not after.** `git worktree add --lock` is atomic, where add-then-`lock` leaves a window in which the worktree is unprotected.
## Step 2 — Report ## Step 2 — Report

View File

@@ -15,16 +15,29 @@ or moved. Every other worktree is a **linked worktree** created by `git worktree
## `add` forms ## `add` forms
```bash ```bash
git worktree add <path> <branch> # check out an existing branch — non-destructive git worktree add <path> <branch> # <branch> exists locally: check it out — non-destructive
git worktree add -b <branch> <path> # create a new branch; fails if it exists git worktree add -b <branch> <path> # create a new branch; fails if it exists
git worktree add <path> # branch named after $(basename <path>): checked out git worktree add <path> # branch named after $(basename <path>): checked out
# if it exists, else created from HEAD # if it exists, else created from HEAD
git worktree add -B <branch> <path> # create the branch, or reset an existing one to HEAD, git worktree add -B <branch> <path> # create the branch, or reset an existing one to HEAD,
# discarding the commits it carried # discarding the commits it carried
git worktree add <path> <remote>/<branch> # track a remote branch git worktree add --track -b <branch> <path> <remote>/<branch>
# new local branch tracking the remote — always works
git worktree add <path> <branch> # <branch> absent locally and in exactly one remote:
# Git expands this to the --track -b form above
git worktree add -d <path> # detached HEAD, no branch git worktree add -d <path> # detached HEAD, no branch
``` ```
The same `git worktree add <path> <branch>` spelling appears twice above and does two
different things: it checks out a local branch when one exists, and only otherwise falls
through to the remote-tracking shortcut. Read the local branch list before relying on either.
**Do not write `git worktree add <path> <remote>/<branch>`.** A remote-tracking ref resolves as a
commit-ish, so the tracking shortcut never fires and the worktree lands on a **detached HEAD with
no local branch and no upstream** — commits there go unreachable once HEAD moves or the worktree is
removed, and `git push` fails without an explicit refspec. That spelling is correct only as the
final argument of the `--track -b` form.
## Full `add` flag table ## Full `add` flag table
| Flag | Meaning | | Flag | Meaning |
@@ -69,19 +82,40 @@ git worktree unlock <path> # when reconnected
## Remote-branch disambiguation ## Remote-branch disambiguation
```bash ```bash
git worktree add <path> <remote>/<branch> git worktree add --track -b <branch> <path> <remote>/<branch> # explicit: no guessing at all
git worktree add <path> <branch> # shortcut: needs one clear remote
``` ```
For ambiguous names across remotes, `checkout.defaultRemote` config disambiguates explicitly, or `--guess-remote` auto-matches by path basename (default controlled by `worktree.guessRemote` config). If a branch name matches multiple remotes during `worktree add` and neither is set, Git refuses rather than guessing. The shortcut fires only when `<branch>` is not found locally, none of `-b`/`-B`/`--detach` were
given, and a tracking branch of that name exists in exactly one remote. When several remotes carry
the name, `checkout.defaultRemote` picks one for disambiguation purposes; with no such setting the
shortcut has no single remote to resolve against and does not apply.
`--guess-remote` covers the *other* spelling — `git worktree add <path>` with no `<commit-ish>` at
all. It bases the new branch on the remote-tracking branch matching `$(basename <path>)` when
exactly one remote has it, and marks that branch as upstream. Its default comes from the
`worktree.guessRemote` config.
## Repair after a manual move ## Repair after a manual move
```bash ```bash
git worktree repair # run from the main worktree: fixes the links to every linked worktree git worktree repair # the MAIN worktree moved: run it there to reconnect every linked
git worktree repair <path> # run from a moved linked worktree: fixes its own pointer back to main # worktree back to the main worktree
git worktree repair # a LINKED worktree moved: run it inside that recently-moved worktree
git worktree repair <path>... # reconnect a specific linked worktree — runnable from any worktree,
# naming each moved tree's new path
``` ```
`repair` reestablishes the bidirectional pointers a manual move breaks, but only for the side it is Which form applies depends on what moved:
run from. Run it from the wrong directory and it reports nothing and fixes nothing.
| What moved | Remedy |
|---|---|
| The main worktree (or bare repo) | `git worktree repair` in the main worktree |
| One linked worktree | `git worktree repair` inside that worktree |
| Several linked worktrees | `git worktree repair <path>...` from any worktree, listing each new path |
| Both main and linked worktrees | `git worktree repair <path>...` in the main worktree, naming each linked worktree's new path — this restores the connections in both directions |
Only the no-argument form is tied to the current directory. The `<path>...` form is not — it
reestablishes the connection to every path you name, run from any worktree.
## Configuration ## Configuration
@@ -111,6 +145,10 @@ git worktree remove ../temp
context switch: context switch:
```bash ```bash
git worktree add ../review-pr-123 origin/feature-xyz git worktree add ../review-pr-123 origin/feature-xyz # detached HEAD — read-only review
git worktree add --track -b feature-xyz ../review-pr-123 origin/feature-xyz # if you will commit
# open ../review-pr-123 in a second editor window or terminal # open ../review-pr-123 in a second editor window or terminal
``` ```
Pick the second form the moment you intend to push anything back: the first leaves no branch to
push and no upstream to push to.