diff --git a/plugins/git/.apm/agents/git-orchestrate.agent.md b/plugins/git/.apm/agents/git-orchestrate.agent.md index a847abb..f4b68d5 100644 --- a/plugins/git/.apm/agents/git-orchestrate.agent.md +++ b/plugins/git/.apm/agents/git-orchestrate.agent.md @@ -16,7 +16,7 @@ You are the orchestrator for the git plugin—a composable workflow dispatcher d You act on the caller's real branch and session context (you explicitly carry forward `current_branch`), not a disposable copy — you do not run in an isolated worktree. -**Scope:** this orchestrator routes git-object operations only (commits, branches, worktrees, remotes, submodules, history). `pc-author` and `pc-run` (pre-commit config authoring and hook execution) are intentionally not routed here — they operate on `.pre-commit-config.yaml` and hook installation, not git objects. `git-workflow` is also not routed here, but for a different reason than `pc-author`/`pc-run`: it is a human-facing conversational wrapper for all git operation types (commits, branches, history, submodules, worktrees, remotes), and it itself calls this orchestrator internally as its execution backend — its own workflow explicitly invokes the `git-orchestrate` agent as its final step. It is not a peer to invoke instead of this dispatcher, and it explicitly refuses agent callers ("Do not use when the caller is an agent"). Agent callers route git-object operations here directly; direct human users to `git-workflow` when they want guided, conversational git help — it will call back into this orchestrator itself. Invoke `pc-author`/`pc-run` directly rather than through this dispatcher; do not invoke `git-workflow` as an agent caller under any circumstance. +**Scope:** this orchestrator routes git-object operations only (commits, branches, worktrees, remotes, submodules, history). `pc-author` and `pc-run` (pre-commit config authoring and hook execution) are intentionally not routed here — they operate on `.pre-commit-config.yaml` and hook installation, not git objects. `git-workflow` is also not routed here, but for a different reason than `pc-author`/`pc-run`: it is a human-facing conversational wrapper for all git operation types (commits, branches, history, submodules, worktrees, remotes), and it itself calls this orchestrator internally as its execution backend — its own workflow explicitly invokes the `git-orchestrate` agent as its final step. It is not a peer to invoke instead of this dispatcher, and its own boundary clause sends agent callers here ("Not an agent caller -> `git-orchestrate`"). Agent callers route git-object operations here directly; direct human users to `git-workflow` when they want guided, conversational git help — it will call back into this orchestrator itself. Invoke `pc-author`/`pc-run` directly rather than through this dispatcher; do not invoke `git-workflow` as an agent caller under any circumstance. ## Hard rules diff --git a/plugins/git/.apm/skills/git-branches/README.md b/plugins/git/.apm/skills/git-branches/README.md index b3626dd..5c4f104 100644 --- a/plugins/git/.apm/skills/git-branches/README.md +++ b/plugins/git/.apm/skills/git-branches/README.md @@ -20,7 +20,7 @@ Describe your branch task: create a feature/hotfix/release branch, switch, delet |------|---------| | `SKILL.md` | Skill instructions for agents | | `references/branch-patterns.md` | Loaded when a branch's base, name prefix, or merge rule depends on GitHub Flow vs. Gitflow | -| `references/branch-operations.md` | Loaded when running a create/switch/delete/rename/track/list action, or resolving `get-intent` | +| `references/branch-operations.md` | Loaded when running a create/switch/delete/rename/track/list/stash action, or resolving `get-intent` | | `references/merging.md` | Loaded when merging one branch into another or resolving merge conflicts | | `references/comparing-branches.md` | Loaded when comparing two branches or finding where they diverged | | `references/orchestrator-contract.md` | Loaded when `git-orchestrate` or another calling agent supplies a structured request rather than prose | @@ -29,5 +29,6 @@ Describe your branch task: create a feature/hotfix/release branch, switch, delet ## Composition `git-orchestrate` calls this skill for the branch step of a multi-step workflow and parses its -structured result. Cherry-pick and revert are `git-history`'s; commit authoring and rebase are -`git-commits`'; branch operations against a Gitea-hosted remote are `gitea-branches`'. +structured result. Revert is `git-history`'s; commit authoring, rebase, reset and cherry-pick are +`git-commits`'; deleting a remote branch is `git-remotes`'; branch operations against a +Gitea-hosted remote are `gitea-branches`'. diff --git a/plugins/git/.apm/skills/git-branches/SKILL.md b/plugins/git/.apm/skills/git-branches/SKILL.md index ca98aaf..44d79c9 100644 --- a/plugins/git/.apm/skills/git-branches/SKILL.md +++ b/plugins/git/.apm/skills/git-branches/SKILL.md @@ -33,7 +33,7 @@ The two patterns are not mixable, and the wrong merge rule silently damages hist | Action | Reference | |---|---| -| create, switch, delete, rename, track, list, get-intent | `references/branch-operations.md` | +| create, switch, delete, rename, track, list, get-intent, stash | `references/branch-operations.md` | | merge a branch, resolve merge conflicts | `references/merging.md` | | compare two branches, find their divergence | `references/comparing-branches.md` | @@ -51,7 +51,7 @@ These gates are passable. The `main`/`master` refusal in Gotchas is not. ## Step 4 — Set tracking -When pushing a branch for the first time, always `git push -u origin `. Without an upstream, later pushes and pulls either fail or silently target the wrong remote branch, and the caller has no way to tell which happened. +A new branch's first push must be `git push -u origin `. The push itself is `git-remotes`' — every remote-side gate lives there, which is why Step 2's remote-delete row hands off the same way — but the upstream requirement originates here, so carry it in the handoff. Without an upstream, later pushes and pulls either fail or silently target the wrong remote branch, and the caller has no way to tell which happened. ## Step 5 — Return a structured result diff --git a/plugins/git/.apm/skills/git-branches/references/branch-operations.md b/plugins/git/.apm/skills/git-branches/references/branch-operations.md index 8c428cc..b9e29f4 100644 --- a/plugins/git/.apm/skills/git-branches/references/branch-operations.md +++ b/plugins/git/.apm/skills/git-branches/references/branch-operations.md @@ -15,7 +15,9 @@ hatch. - **delete (local)** — `git branch -d ` refuses when the branch holds unmerged commits, which is why it is the default. `git branch -D ` forces the deletion and discards that work — only after the destructive-operation gates pass and `confirm: true` is set. -- **delete (remote)** — `git push origin --delete `. +- **delete (remote)** — not this skill's. Deleting a remote branch is a push, and every remote-side + gate lives in `git-remotes`; hand it there rather than running the push from here. Its + `references/push.md` carries the command and the refspec form. - **rename** — `git branch -m `. - **list** — `git branch` (local), `-a` (local plus remote-tracking), `-r` (remote-tracking only), `--merged` / `--no-merged` (filter by merge status into the current branch). @@ -32,3 +34,23 @@ On `get-intent`, either parse the intent back out of the branch-name convention (`feature/`) or return `{ "intent": null }` when the caller never persisted the create-time value. Never fabricate an intent: a downstream commit message built on a guessed intent is worse than one built on none. + +## Stashing work in progress + +A switch aborts rather than clobbering conflicting local changes (see Gotchas). Stash is the way +past it: it shelves the working tree and index so the branch pointer can move. + +- **save** — `git stash push -m ""`. Add `-u` to include untracked files; verified on Git + 2.39.5, a plain `push` leaves them in place, and a plain `push` with *only* untracked changes + reports `No local changes to save` and stashes nothing. Bare `git stash` is `push` with no message. +- **restore** — `git stash pop` applies the newest entry and deletes it. `git stash apply stash@{n}` + applies without deleting, for replaying one shelf onto more than one branch. +- **list** — `git stash list`; `git stash show -p stash@{n}` prints that entry's diff. +- **drop** — `git stash drop stash@{n}` deletes one entry. `git stash clear` deletes all of them + and nothing recovers them — confirm before running it. +- **branch from a stash** — `git stash branch stash@{n}` creates a branch at the commit the + stash was taken from and pops it there. Use it when the stash no longer applies to the current tip. + +**A conflicting `pop` keeps the entry.** Verified on 2.39.5: it exits 1, writes conflict markers, +prints "The stash entry is kept in case you need it again", and `git stash list` still shows it. +Resolve, `git add`, then `git stash drop` the entry by hand — otherwise it silently accumulates. diff --git a/plugins/git/.apm/skills/git-branches/references/merging.md b/plugins/git/.apm/skills/git-branches/references/merging.md index d1721e3..0302138 100644 --- a/plugins/git/.apm/skills/git-branches/references/merging.md +++ b/plugins/git/.apm/skills/git-branches/references/merging.md @@ -6,8 +6,8 @@ source_keys: # Merging one branch into another -Scope is fast-forward and merge-commit mechanics plus conflict resolution. Rebase belongs to -`git-commits`; cherry-pick and revert to `git-history`. +Scope is fast-forward and merge-commit mechanics plus conflict resolution. Rebase and cherry-pick +belong to `git-commits`; revert to `git-history`. - **Fast-forward** — `git merge ` advances the pointer with no merge commit when the target has not diverged. diff --git a/plugins/git/.apm/skills/git-commits/SKILL.md b/plugins/git/.apm/skills/git-commits/SKILL.md index 3b9683c..59ca602 100644 --- a/plugins/git/.apm/skills/git-commits/SKILL.md +++ b/plugins/git/.apm/skills/git-commits/SKILL.md @@ -8,6 +8,7 @@ description: > Not branch lifecycle -> `git-branches`. metadata: + version: "0.1.3" category: git source_keys: - conventional-commits-spec @@ -22,6 +23,7 @@ allowed-tools: Bash - **Run git as `rtk git `, never bare `git`** — org convention, in `&&` chains too. - **Refuse to force-push `main`/`master`** — a rewrite leaves the branch diverged and the reflex is to force it back; safe only where nobody else has based work on it. +- **`reset --hard` is a confirmation gate, not a default.** It overwrites the working tree, and uncommitted edits it discards were never in git, so no reflog recovers them. Name what will be lost and offer a stash first. - **Never add `--no-verify`** — using it when a hook fails bypasses the QA gate the pipeline depends on. Only on the user's explicit demand, with a warning. ## Dispatch @@ -31,18 +33,19 @@ Read exactly one flow file. Each is self-contained. | Condition | Flow | Read | |---|---|---| | Composing a new commit from staged changes | create | `references/create-commit.md` | -| Amending, squashing, or folding a fixup into an earlier commit | rewrite | `references/rewrite-history.md` | +| Amending, squashing, folding a fixup, rebasing onto a new base, or resetting HEAD | rewrite | `references/rewrite-history.md` | | Replaying an existing commit onto the current branch | cherry-pick | `references/cherry-pick.md` | ## Gates on every flow 1. **Confirmation.** No history rewrite executes without explicit approval from the user or the calling agent. Cherry-pick needs the destination branch confirmed first. -2. **Secrets.** Before any commit or amend, scan the staged diff for anything resembling an API key, +2. **Atomicity.** The result must be one logical, independently reviewable and reversible change that leaves the repository buildable and testable. This binds an amend or a squashed result as much as a fresh commit — say so before writing it, not after. +3. **Secrets.** Before any commit or amend, scan the staged diff for anything resembling an API key, token, password, connection string, or environment-specific config. Stop and flag it rather than committing it. -3. **Validation.** Check the message against commitlint `config-conventional` before committing. If a type, footer, or breaking-change edge case is not obvious, read `references/conventional-commits-spec.md` — it carries the constraint table, the 11-type set, and the footer token rules. -4. **SemVer impact.** Report the bump the commit implies: `feat` → MINOR, `fix`/`perf`/`revert` → PATCH, any breaking change → MAJOR, everything else → none. Callers decide releases from this, so never omit it. -5. **Conflicts.** If a rebase or cherry-pick halts, offer resolution or an abort. Do not resolve automatically without confirmation. +4. **Validation.** Check the message against commitlint `config-conventional` before committing. If a type, footer, or breaking-change edge case is not obvious, read `references/conventional-commits-spec.md` — it carries the constraint table, the 11-type set, and the footer token rules. +5. **SemVer impact.** Report the bump the commit implies: `feat` → MINOR, `fix`/`perf`/`revert` → PATCH, any breaking change → MAJOR, everything else → none. Callers decide releases from this, so never omit it. +6. **Conflicts.** If a rebase or cherry-pick halts, offer resolution or an abort. Do not resolve automatically without confirmation. ## Output diff --git a/plugins/git/.apm/skills/git-commits/references/rewrite-history.md b/plugins/git/.apm/skills/git-commits/references/rewrite-history.md index 942f44f..88bc993 100644 --- a/plugins/git/.apm/skills/git-commits/references/rewrite-history.md +++ b/plugins/git/.apm/skills/git-commits/references/rewrite-history.md @@ -21,7 +21,9 @@ Prefer this whenever a commit is written to be folded, because git does the mark 1. `rtk git commit --fixup=` keeps the target's message; `rtk git commit --squash=` lets you edit the combined message later. Both prefix the message with `fixup!`/`squash!` and name the target commit. 2. Get explicit approval — the rebase still rewrites history. -3. Run `rtk git rebase --autosquash HEAD~N`, or `-i --autosquash` to review the plan first. Git reorders the tagged commits against their targets automatically. +3. Run `rtk git rebase -i --autosquash HEAD~N`. Git pre-fills the todo list with the tagged commits already reordered against their targets; save it unchanged to apply. + +**`-i` is not optional here.** On Git 2.39.5, `rtk git rebase --autosquash HEAD~N` without `-i` prints `Successfully rebased and updated refs/heads/.` and exits 0 while leaving the `fixup!` commit in place at its original SHA — `--autosquash` is honoured only by the interactive machinery, and the false success is the trap: the fold is reported as done, and the surviving `fixup!` subject then fails the Conventional Commits `commit-msg` hook. Later Git versions taught the non-interactive rebase to honour the flag, but `-i --autosquash` is correct on every version, so always write that. ## Squash by hand (interactive rebase) @@ -35,3 +37,40 @@ Use this when the commits were not tagged at commit time. **Interactive rebase h ## When a rebase halts on a conflict Offer conflict resolution or `rtk git rebase --abort`. Do not resolve conflicts automatically without confirmation. + +## Rebase the branch onto a new base + +Replays this branch's commits on top of another branch's tip — bringing a feature branch up to +date without a merge commit. + +1. Confirm nothing being replayed has been pushed anywhere someone else has based work on. A rebase + gives every replayed commit a new SHA, which breaks any clone that already has the old ones. +2. Get explicit approval — this rewrites history like every other flow on this page. +3. `rtk git fetch origin` first, so `` is the real tip rather than a stale local copy. +4. `rtk git rebase ` — for example `rtk git rebase main`. Use + `rtk git rebase --onto ` to replay only the commits after + ``, which is how a branch started from the wrong base gets moved. +5. The branch has now diverged from its remote. It needs + `--force-with-lease --force-if-includes` to push, never a bare `--force`, and never on + `main`/`master` — refuse that and explain. + +## Move the branch pointer back (`git reset`) + +`reset` moves the current branch to another commit. The mode decides what survives: + +| Mode | Branch pointer | Index | Working tree | +|---|---|---|---| +| `--soft` | moves | untouched — the changes stay staged | untouched | +| `--mixed` (default) | moves | reset — the changes become unstaged | untouched | +| `--hard` | moves | reset | **overwritten; uncommitted work is destroyed** | + +- "Undo my last commit but keep the changes" is `rtk git reset --soft HEAD~1`. That is the default + answer to the request; reach for anything else only when the caller asked for it. +- `rtk git reset --mixed HEAD~1` when the staging should be redone from scratch too. +- `rtk git reset --hard ` is gated like a force-push: state exactly which uncommitted changes + will be discarded, get approval for that specific reset, and offer `rtk git stash push -u` first. + The commits it drops stay reachable through `git reflog`; the uncommitted edits never entered git + at all and nothing recovers them. + +Reset does not rewrite the commits it leaves behind, so no force-push is needed unless the branch +was already pushed at the newer commit. diff --git a/plugins/git/.apm/skills/git-history/README.md b/plugins/git/.apm/skills/git-history/README.md index 72aaa3b..e208cfa 100644 --- a/plugins/git/.apm/skills/git-history/README.md +++ b/plugins/git/.apm/skills/git-history/README.md @@ -8,7 +8,7 @@ This skill handles history inspection within the git workflow suite. It queries ## Composition -`git-branches` delegates cherry-pick and revert here (see `git-branches`'s `references/merging.md`), which is why this skill carries those two operations rather than treating them as out of scope. They are general git knowledge, not drawn from the `history-inspection.md` research corpus. Server-side commit history on a Gitea-hosted repository belongs to `gitea-branches`; this skill reads the local working copy. +`git-branches` delegates revert here (see `git-branches`'s `references/merging.md`), which is why this skill carries that operation rather than treating it as out of scope; it is general git knowledge, not drawn from the `history-inspection.md` research corpus. Cherry-pick is **not** this skill's: `git-commits` owns it, and this skill's job ends at locating the SHA to hand over. Server-side commit history on a Gitea-hosted repository belongs to `gitea-branches`; this skill reads the local working copy. ## Usage diff --git a/plugins/git/.apm/skills/git-history/SKILL.md b/plugins/git/.apm/skills/git-history/SKILL.md index bfb1fa9..6057bee 100644 --- a/plugins/git/.apm/skills/git-history/SKILL.md +++ b/plugins/git/.apm/skills/git-history/SKILL.md @@ -48,7 +48,7 @@ If you need the placeholder catalogue, format presets, `--diff-filter` letters, Offer the operation and its consequence; run it only once the user has chosen. -- `git cherry-pick ` copies the commit's changes onto the current HEAD — for backporting a fix to another branch. +- Backporting the commit to another branch is a cherry-pick, and cherry-pick is `git-commits`' — it owns the destination-branch check, the `rtk git` wrapper and the `--abort` path. Hand it the SHA; do not run `git cherry-pick` from here. - `git revert ` adds a new commit undoing it — for un-applying merged work without rewriting history. - `git blame ` attributes each line to the commit that last touched it, when the question is which commit introduced one specific line. diff --git a/plugins/git/.apm/skills/git-remotes/references/fetch.md b/plugins/git/.apm/skills/git-remotes/references/fetch.md index e0c05ff..0826b17 100644 --- a/plugins/git/.apm/skills/git-remotes/references/fetch.md +++ b/plugins/git/.apm/skills/git-remotes/references/fetch.md @@ -7,7 +7,9 @@ source_keys: # Fetching -Fetch updates remote-tracking branches (`refs/remotes//*`) and never modifies a local branch, so it is always safe to run. +Fetch **with no refspec** updates remote-tracking branches (`refs/remotes//*`) and leaves every local branch alone. + +That safety comes from the default refspec, not from `fetch` itself. Give it an explicit one and it writes to local branches: verified on Git 2.39.5, `git fetch origin main:probe` fast-forwarded the local `probe` branch, and a `+` prefix force-updates the destination, discarding whatever commits it held. Treat any `fetch` carrying a `:` refspec as a branch update, not a read. - **One remote**: `git fetch ` — all branches - **One branch**: `git fetch ` — the result lands in `FETCH_HEAD`, not a tracking ref diff --git a/plugins/git/.apm/skills/git-remotes/references/pull.md b/plugins/git/.apm/skills/git-remotes/references/pull.md index 52be576..b769742 100644 --- a/plugins/git/.apm/skills/git-remotes/references/pull.md +++ b/plugins/git/.apm/skills/git-remotes/references/pull.md @@ -23,9 +23,11 @@ A pull that diverges with no strategy configured fails, and that failure is the ## Config precedence -The installed default varies by Git version — older versions merge on divergence, newer ones -default to `--ff-only` — so an unset `pull.ff` means the same pull behaves differently on different -machines. Set it explicitly. +`--ff-only` is not Git's default on an unset config, and never has been. Older versions silently +merged on divergence; current ones refuse outright — verified on Git 2.39.5, a divergent pull with +nothing configured prints the reconciliation hint and exits 128 with +`fatal: Need to specify how to reconcile divergent branches.` The behaviour therefore still varies +by installed version, and neither variant is the one you want. Set it explicitly. Highest wins: diff --git a/plugins/git/.apm/skills/git-submodules/SKILL.md b/plugins/git/.apm/skills/git-submodules/SKILL.md index 297f6a2..55d65f2 100644 --- a/plugins/git/.apm/skills/git-submodules/SKILL.md +++ b/plugins/git/.apm/skills/git-submodules/SKILL.md @@ -3,7 +3,8 @@ name: git-submodules description: > Use when managing Git submodules — the full lifecycle of a nested - repository inside a superproject. + repository inside a superproject — including phrasings that never say the + word, such as "add a dependency repo" or "vendor this repo inside ours". Not multiple checkouts of one repo -> `git-worktrees`. Not the superproject's own remotes -> `git-remotes`. diff --git a/plugins/git/.apm/skills/git-submodules/references/setup-and-update.md b/plugins/git/.apm/skills/git-submodules/references/setup-and-update.md index dfb9c75..23b0cb0 100644 --- a/plugins/git/.apm/skills/git-submodules/references/setup-and-update.md +++ b/plugins/git/.apm/skills/git-submodules/references/setup-and-update.md @@ -70,8 +70,8 @@ rtk git submodule update --remote --merge --recursive rtk git commit -am "chore: update submodules to latest" ``` -`--remote` requires `submodule..branch`; without it Git falls back to the remote's default -branch. Commit the superproject afterwards or the new pin is lost on the next `update`. +`--remote` uses `submodule..branch` when it is set; without it Git falls back to the remote's +default branch. Commit the superproject afterwards or the new pin is lost on the next `update`. ## Run one command across every submodule diff --git a/plugins/git/.apm/skills/git-submodules/references/sources.md b/plugins/git/.apm/skills/git-submodules/references/sources.md index 41c8660..fd3adbc 100644 --- a/plugins/git/.apm/skills/git-submodules/references/sources.md +++ b/plugins/git/.apm/skills/git-submodules/references/sources.md @@ -22,10 +22,10 @@ source_keys: Other source keys extracted during the git plugin research phase inform sibling skills in the git workflow suite, not this one: -- `context7-git-htmldocs` — git:branches, git:history, git:remotes -- `git-scm-docs` — git:configuration -- `git-scm-worktree-docs` — git:worktrees -- `nvie-gitflow-post`, `atlassian-gitflow-tutorial`, `gitflow-cheatsheet` — git:branches -- `conventional-commits-spec`, `commitlint-config-conventional` — git:commits -- `git-scm-push-docs`, `git-scm-fetch-docs`, `git-scm-pull-docs`, `git-scm-remote-docs` — git:remotes -- `git-scm-bisect-docs`, `git-scm-log-docs`, `git-scm-diff-docs` — git:history +- `context7-git-htmldocs` — git-branches, git-history, git-remotes +- `git-scm-docs` — no current skill; it backed a git-configuration skill that no longer exists and survives here as provenance only +- `git-scm-worktree-docs` — git-worktrees +- `nvie-gitflow-post`, `atlassian-gitflow-tutorial`, `gitflow-cheatsheet` — git-branches +- `conventional-commits-spec`, `commitlint-config-conventional` — git-commits +- `git-scm-push-docs`, `git-scm-fetch-docs`, `git-scm-pull-docs`, `git-scm-remote-docs` — git-remotes +- `git-scm-bisect-docs`, `git-scm-log-docs`, `git-scm-diff-docs` — git-history diff --git a/plugins/git/.apm/skills/git-workflow/SKILL.md b/plugins/git/.apm/skills/git-workflow/SKILL.md index 40422fb..8f2f871 100644 --- a/plugins/git/.apm/skills/git-workflow/SKILL.md +++ b/plugins/git/.apm/skills/git-workflow/SKILL.md @@ -28,13 +28,16 @@ metadata: ## Domains -Every request resolves to exactly one of these six. An unambiguous one should have gone straight -to the domain skill; this skill exists for the ones that did not. +Route to the domain that owns the operation, and in sequence when a request spans two — a rebase +that ends in a force-push is `git-commits`, then `git-remotes`. An unambiguous request should have +gone straight to the domain skill; this one exists for the ones that did not. | The request is about | Domain | |---|---| | Writing, amending, squashing, or cherry-picking a commit, and its message | `git-commits` | +| Rebasing onto a new base, or undoing a commit with `reset` | `git-commits` | | Creating, switching, deleting, renaming, tracking, or merging a local branch | `git-branches` | +| Stashing work in progress to move between branches | `git-branches` | | When a change landed, which commit broke something, what to revert or backport | `git-history` | | Anything touching a remote — remote config, fetch, push, pull — even unnamed | `git-remotes` | | A nested repository pinned inside this one by a recorded commit | `git-submodules` | diff --git a/plugins/git/.apm/skills/git-worktrees/references/worktrees.md b/plugins/git/.apm/skills/git-worktrees/references/worktrees.md index 64172f1..c4d9b22 100644 --- a/plugins/git/.apm/skills/git-worktrees/references/worktrees.md +++ b/plugins/git/.apm/skills/git-worktrees/references/worktrees.md @@ -53,7 +53,7 @@ final argument of the `--track -b` form. | `-b ` | Create and check out a new branch; fails if it exists | | `-B ` | Like `-b` but resets the branch if it already exists | | `-d` / `--detach` | Detach HEAD; useful for throwaway experiments | -| `--orphan` | Create empty unborn branch | +| `--orphan` | Create empty unborn branch — **Git 2.42+**; earlier versions exit 129 with `error: unknown option 'orphan'`. Fallback below | | `--no-checkout` | Suppress initial checkout (for sparse-checkout setup) | | `--guess-remote` | Look for a matching remote-tracking branch by path basename | | `--lock [--reason ]` | Lock immediately on creation (atomic; avoids race vs. add-then-lock) | @@ -67,7 +67,22 @@ Using `-` as `` is shorthand for `@{-1}` (the branch checked out bef ```bash git worktree add --orphan -b ``` -Creates an empty branch with no commits. +Creates an empty branch with no commits. **`--orphan` needs Git 2.42 or later** — it was added +upstream in 2.42, and on 2.39.5 this fails with `error: unknown option 'orphan'` and exit 129. +Check `git --version` before reaching for it. + +Fallback on older Git, verified on 2.39.5 — detach first, then orphan the linked worktree in place, +which leaves the main worktree on its own branch throughout: + +```bash +git worktree add -d # linked worktree, detached HEAD +cd +git switch --orphan # unborn branch: empty index, empty working tree +``` + +`git worktree list` then shows the new worktree at `0000000 []` until its first commit. +Do not substitute `git switch --orphan` in the *main* worktree: it clears that checkout, which is +the disruption worktrees exist to avoid. ## Sparse-checkout worktree diff --git a/plugins/git/agents/git-orchestrate.agent.md b/plugins/git/agents/git-orchestrate.agent.md index a847abb..f4b68d5 100644 --- a/plugins/git/agents/git-orchestrate.agent.md +++ b/plugins/git/agents/git-orchestrate.agent.md @@ -16,7 +16,7 @@ You are the orchestrator for the git plugin—a composable workflow dispatcher d You act on the caller's real branch and session context (you explicitly carry forward `current_branch`), not a disposable copy — you do not run in an isolated worktree. -**Scope:** this orchestrator routes git-object operations only (commits, branches, worktrees, remotes, submodules, history). `pc-author` and `pc-run` (pre-commit config authoring and hook execution) are intentionally not routed here — they operate on `.pre-commit-config.yaml` and hook installation, not git objects. `git-workflow` is also not routed here, but for a different reason than `pc-author`/`pc-run`: it is a human-facing conversational wrapper for all git operation types (commits, branches, history, submodules, worktrees, remotes), and it itself calls this orchestrator internally as its execution backend — its own workflow explicitly invokes the `git-orchestrate` agent as its final step. It is not a peer to invoke instead of this dispatcher, and it explicitly refuses agent callers ("Do not use when the caller is an agent"). Agent callers route git-object operations here directly; direct human users to `git-workflow` when they want guided, conversational git help — it will call back into this orchestrator itself. Invoke `pc-author`/`pc-run` directly rather than through this dispatcher; do not invoke `git-workflow` as an agent caller under any circumstance. +**Scope:** this orchestrator routes git-object operations only (commits, branches, worktrees, remotes, submodules, history). `pc-author` and `pc-run` (pre-commit config authoring and hook execution) are intentionally not routed here — they operate on `.pre-commit-config.yaml` and hook installation, not git objects. `git-workflow` is also not routed here, but for a different reason than `pc-author`/`pc-run`: it is a human-facing conversational wrapper for all git operation types (commits, branches, history, submodules, worktrees, remotes), and it itself calls this orchestrator internally as its execution backend — its own workflow explicitly invokes the `git-orchestrate` agent as its final step. It is not a peer to invoke instead of this dispatcher, and its own boundary clause sends agent callers here ("Not an agent caller -> `git-orchestrate`"). Agent callers route git-object operations here directly; direct human users to `git-workflow` when they want guided, conversational git help — it will call back into this orchestrator itself. Invoke `pc-author`/`pc-run` directly rather than through this dispatcher; do not invoke `git-workflow` as an agent caller under any circumstance. ## Hard rules diff --git a/plugins/git/skills/git-branches/README.md b/plugins/git/skills/git-branches/README.md index b3626dd..5c4f104 100644 --- a/plugins/git/skills/git-branches/README.md +++ b/plugins/git/skills/git-branches/README.md @@ -20,7 +20,7 @@ Describe your branch task: create a feature/hotfix/release branch, switch, delet |------|---------| | `SKILL.md` | Skill instructions for agents | | `references/branch-patterns.md` | Loaded when a branch's base, name prefix, or merge rule depends on GitHub Flow vs. Gitflow | -| `references/branch-operations.md` | Loaded when running a create/switch/delete/rename/track/list action, or resolving `get-intent` | +| `references/branch-operations.md` | Loaded when running a create/switch/delete/rename/track/list/stash action, or resolving `get-intent` | | `references/merging.md` | Loaded when merging one branch into another or resolving merge conflicts | | `references/comparing-branches.md` | Loaded when comparing two branches or finding where they diverged | | `references/orchestrator-contract.md` | Loaded when `git-orchestrate` or another calling agent supplies a structured request rather than prose | @@ -29,5 +29,6 @@ Describe your branch task: create a feature/hotfix/release branch, switch, delet ## Composition `git-orchestrate` calls this skill for the branch step of a multi-step workflow and parses its -structured result. Cherry-pick and revert are `git-history`'s; commit authoring and rebase are -`git-commits`'; branch operations against a Gitea-hosted remote are `gitea-branches`'. +structured result. Revert is `git-history`'s; commit authoring, rebase, reset and cherry-pick are +`git-commits`'; deleting a remote branch is `git-remotes`'; branch operations against a +Gitea-hosted remote are `gitea-branches`'. diff --git a/plugins/git/skills/git-branches/SKILL.md b/plugins/git/skills/git-branches/SKILL.md index ca98aaf..44d79c9 100644 --- a/plugins/git/skills/git-branches/SKILL.md +++ b/plugins/git/skills/git-branches/SKILL.md @@ -33,7 +33,7 @@ The two patterns are not mixable, and the wrong merge rule silently damages hist | Action | Reference | |---|---| -| create, switch, delete, rename, track, list, get-intent | `references/branch-operations.md` | +| create, switch, delete, rename, track, list, get-intent, stash | `references/branch-operations.md` | | merge a branch, resolve merge conflicts | `references/merging.md` | | compare two branches, find their divergence | `references/comparing-branches.md` | @@ -51,7 +51,7 @@ These gates are passable. The `main`/`master` refusal in Gotchas is not. ## Step 4 — Set tracking -When pushing a branch for the first time, always `git push -u origin `. Without an upstream, later pushes and pulls either fail or silently target the wrong remote branch, and the caller has no way to tell which happened. +A new branch's first push must be `git push -u origin `. The push itself is `git-remotes`' — every remote-side gate lives there, which is why Step 2's remote-delete row hands off the same way — but the upstream requirement originates here, so carry it in the handoff. Without an upstream, later pushes and pulls either fail or silently target the wrong remote branch, and the caller has no way to tell which happened. ## Step 5 — Return a structured result diff --git a/plugins/git/skills/git-branches/references/branch-operations.md b/plugins/git/skills/git-branches/references/branch-operations.md index 8c428cc..b9e29f4 100644 --- a/plugins/git/skills/git-branches/references/branch-operations.md +++ b/plugins/git/skills/git-branches/references/branch-operations.md @@ -15,7 +15,9 @@ hatch. - **delete (local)** — `git branch -d ` refuses when the branch holds unmerged commits, which is why it is the default. `git branch -D ` forces the deletion and discards that work — only after the destructive-operation gates pass and `confirm: true` is set. -- **delete (remote)** — `git push origin --delete `. +- **delete (remote)** — not this skill's. Deleting a remote branch is a push, and every remote-side + gate lives in `git-remotes`; hand it there rather than running the push from here. Its + `references/push.md` carries the command and the refspec form. - **rename** — `git branch -m `. - **list** — `git branch` (local), `-a` (local plus remote-tracking), `-r` (remote-tracking only), `--merged` / `--no-merged` (filter by merge status into the current branch). @@ -32,3 +34,23 @@ On `get-intent`, either parse the intent back out of the branch-name convention (`feature/`) or return `{ "intent": null }` when the caller never persisted the create-time value. Never fabricate an intent: a downstream commit message built on a guessed intent is worse than one built on none. + +## Stashing work in progress + +A switch aborts rather than clobbering conflicting local changes (see Gotchas). Stash is the way +past it: it shelves the working tree and index so the branch pointer can move. + +- **save** — `git stash push -m ""`. Add `-u` to include untracked files; verified on Git + 2.39.5, a plain `push` leaves them in place, and a plain `push` with *only* untracked changes + reports `No local changes to save` and stashes nothing. Bare `git stash` is `push` with no message. +- **restore** — `git stash pop` applies the newest entry and deletes it. `git stash apply stash@{n}` + applies without deleting, for replaying one shelf onto more than one branch. +- **list** — `git stash list`; `git stash show -p stash@{n}` prints that entry's diff. +- **drop** — `git stash drop stash@{n}` deletes one entry. `git stash clear` deletes all of them + and nothing recovers them — confirm before running it. +- **branch from a stash** — `git stash branch stash@{n}` creates a branch at the commit the + stash was taken from and pops it there. Use it when the stash no longer applies to the current tip. + +**A conflicting `pop` keeps the entry.** Verified on 2.39.5: it exits 1, writes conflict markers, +prints "The stash entry is kept in case you need it again", and `git stash list` still shows it. +Resolve, `git add`, then `git stash drop` the entry by hand — otherwise it silently accumulates. diff --git a/plugins/git/skills/git-branches/references/merging.md b/plugins/git/skills/git-branches/references/merging.md index d1721e3..0302138 100644 --- a/plugins/git/skills/git-branches/references/merging.md +++ b/plugins/git/skills/git-branches/references/merging.md @@ -6,8 +6,8 @@ source_keys: # Merging one branch into another -Scope is fast-forward and merge-commit mechanics plus conflict resolution. Rebase belongs to -`git-commits`; cherry-pick and revert to `git-history`. +Scope is fast-forward and merge-commit mechanics plus conflict resolution. Rebase and cherry-pick +belong to `git-commits`; revert to `git-history`. - **Fast-forward** — `git merge ` advances the pointer with no merge commit when the target has not diverged. diff --git a/plugins/git/skills/git-commits/SKILL.md b/plugins/git/skills/git-commits/SKILL.md index 3b9683c..59ca602 100644 --- a/plugins/git/skills/git-commits/SKILL.md +++ b/plugins/git/skills/git-commits/SKILL.md @@ -8,6 +8,7 @@ description: > Not branch lifecycle -> `git-branches`. metadata: + version: "0.1.3" category: git source_keys: - conventional-commits-spec @@ -22,6 +23,7 @@ allowed-tools: Bash - **Run git as `rtk git `, never bare `git`** — org convention, in `&&` chains too. - **Refuse to force-push `main`/`master`** — a rewrite leaves the branch diverged and the reflex is to force it back; safe only where nobody else has based work on it. +- **`reset --hard` is a confirmation gate, not a default.** It overwrites the working tree, and uncommitted edits it discards were never in git, so no reflog recovers them. Name what will be lost and offer a stash first. - **Never add `--no-verify`** — using it when a hook fails bypasses the QA gate the pipeline depends on. Only on the user's explicit demand, with a warning. ## Dispatch @@ -31,18 +33,19 @@ Read exactly one flow file. Each is self-contained. | Condition | Flow | Read | |---|---|---| | Composing a new commit from staged changes | create | `references/create-commit.md` | -| Amending, squashing, or folding a fixup into an earlier commit | rewrite | `references/rewrite-history.md` | +| Amending, squashing, folding a fixup, rebasing onto a new base, or resetting HEAD | rewrite | `references/rewrite-history.md` | | Replaying an existing commit onto the current branch | cherry-pick | `references/cherry-pick.md` | ## Gates on every flow 1. **Confirmation.** No history rewrite executes without explicit approval from the user or the calling agent. Cherry-pick needs the destination branch confirmed first. -2. **Secrets.** Before any commit or amend, scan the staged diff for anything resembling an API key, +2. **Atomicity.** The result must be one logical, independently reviewable and reversible change that leaves the repository buildable and testable. This binds an amend or a squashed result as much as a fresh commit — say so before writing it, not after. +3. **Secrets.** Before any commit or amend, scan the staged diff for anything resembling an API key, token, password, connection string, or environment-specific config. Stop and flag it rather than committing it. -3. **Validation.** Check the message against commitlint `config-conventional` before committing. If a type, footer, or breaking-change edge case is not obvious, read `references/conventional-commits-spec.md` — it carries the constraint table, the 11-type set, and the footer token rules. -4. **SemVer impact.** Report the bump the commit implies: `feat` → MINOR, `fix`/`perf`/`revert` → PATCH, any breaking change → MAJOR, everything else → none. Callers decide releases from this, so never omit it. -5. **Conflicts.** If a rebase or cherry-pick halts, offer resolution or an abort. Do not resolve automatically without confirmation. +4. **Validation.** Check the message against commitlint `config-conventional` before committing. If a type, footer, or breaking-change edge case is not obvious, read `references/conventional-commits-spec.md` — it carries the constraint table, the 11-type set, and the footer token rules. +5. **SemVer impact.** Report the bump the commit implies: `feat` → MINOR, `fix`/`perf`/`revert` → PATCH, any breaking change → MAJOR, everything else → none. Callers decide releases from this, so never omit it. +6. **Conflicts.** If a rebase or cherry-pick halts, offer resolution or an abort. Do not resolve automatically without confirmation. ## Output diff --git a/plugins/git/skills/git-commits/references/rewrite-history.md b/plugins/git/skills/git-commits/references/rewrite-history.md index 942f44f..88bc993 100644 --- a/plugins/git/skills/git-commits/references/rewrite-history.md +++ b/plugins/git/skills/git-commits/references/rewrite-history.md @@ -21,7 +21,9 @@ Prefer this whenever a commit is written to be folded, because git does the mark 1. `rtk git commit --fixup=` keeps the target's message; `rtk git commit --squash=` lets you edit the combined message later. Both prefix the message with `fixup!`/`squash!` and name the target commit. 2. Get explicit approval — the rebase still rewrites history. -3. Run `rtk git rebase --autosquash HEAD~N`, or `-i --autosquash` to review the plan first. Git reorders the tagged commits against their targets automatically. +3. Run `rtk git rebase -i --autosquash HEAD~N`. Git pre-fills the todo list with the tagged commits already reordered against their targets; save it unchanged to apply. + +**`-i` is not optional here.** On Git 2.39.5, `rtk git rebase --autosquash HEAD~N` without `-i` prints `Successfully rebased and updated refs/heads/.` and exits 0 while leaving the `fixup!` commit in place at its original SHA — `--autosquash` is honoured only by the interactive machinery, and the false success is the trap: the fold is reported as done, and the surviving `fixup!` subject then fails the Conventional Commits `commit-msg` hook. Later Git versions taught the non-interactive rebase to honour the flag, but `-i --autosquash` is correct on every version, so always write that. ## Squash by hand (interactive rebase) @@ -35,3 +37,40 @@ Use this when the commits were not tagged at commit time. **Interactive rebase h ## When a rebase halts on a conflict Offer conflict resolution or `rtk git rebase --abort`. Do not resolve conflicts automatically without confirmation. + +## Rebase the branch onto a new base + +Replays this branch's commits on top of another branch's tip — bringing a feature branch up to +date without a merge commit. + +1. Confirm nothing being replayed has been pushed anywhere someone else has based work on. A rebase + gives every replayed commit a new SHA, which breaks any clone that already has the old ones. +2. Get explicit approval — this rewrites history like every other flow on this page. +3. `rtk git fetch origin` first, so `` is the real tip rather than a stale local copy. +4. `rtk git rebase ` — for example `rtk git rebase main`. Use + `rtk git rebase --onto ` to replay only the commits after + ``, which is how a branch started from the wrong base gets moved. +5. The branch has now diverged from its remote. It needs + `--force-with-lease --force-if-includes` to push, never a bare `--force`, and never on + `main`/`master` — refuse that and explain. + +## Move the branch pointer back (`git reset`) + +`reset` moves the current branch to another commit. The mode decides what survives: + +| Mode | Branch pointer | Index | Working tree | +|---|---|---|---| +| `--soft` | moves | untouched — the changes stay staged | untouched | +| `--mixed` (default) | moves | reset — the changes become unstaged | untouched | +| `--hard` | moves | reset | **overwritten; uncommitted work is destroyed** | + +- "Undo my last commit but keep the changes" is `rtk git reset --soft HEAD~1`. That is the default + answer to the request; reach for anything else only when the caller asked for it. +- `rtk git reset --mixed HEAD~1` when the staging should be redone from scratch too. +- `rtk git reset --hard ` is gated like a force-push: state exactly which uncommitted changes + will be discarded, get approval for that specific reset, and offer `rtk git stash push -u` first. + The commits it drops stay reachable through `git reflog`; the uncommitted edits never entered git + at all and nothing recovers them. + +Reset does not rewrite the commits it leaves behind, so no force-push is needed unless the branch +was already pushed at the newer commit. diff --git a/plugins/git/skills/git-history/README.md b/plugins/git/skills/git-history/README.md index 72aaa3b..e208cfa 100644 --- a/plugins/git/skills/git-history/README.md +++ b/plugins/git/skills/git-history/README.md @@ -8,7 +8,7 @@ This skill handles history inspection within the git workflow suite. It queries ## Composition -`git-branches` delegates cherry-pick and revert here (see `git-branches`'s `references/merging.md`), which is why this skill carries those two operations rather than treating them as out of scope. They are general git knowledge, not drawn from the `history-inspection.md` research corpus. Server-side commit history on a Gitea-hosted repository belongs to `gitea-branches`; this skill reads the local working copy. +`git-branches` delegates revert here (see `git-branches`'s `references/merging.md`), which is why this skill carries that operation rather than treating it as out of scope; it is general git knowledge, not drawn from the `history-inspection.md` research corpus. Cherry-pick is **not** this skill's: `git-commits` owns it, and this skill's job ends at locating the SHA to hand over. Server-side commit history on a Gitea-hosted repository belongs to `gitea-branches`; this skill reads the local working copy. ## Usage diff --git a/plugins/git/skills/git-history/SKILL.md b/plugins/git/skills/git-history/SKILL.md index bfb1fa9..6057bee 100644 --- a/plugins/git/skills/git-history/SKILL.md +++ b/plugins/git/skills/git-history/SKILL.md @@ -48,7 +48,7 @@ If you need the placeholder catalogue, format presets, `--diff-filter` letters, Offer the operation and its consequence; run it only once the user has chosen. -- `git cherry-pick ` copies the commit's changes onto the current HEAD — for backporting a fix to another branch. +- Backporting the commit to another branch is a cherry-pick, and cherry-pick is `git-commits`' — it owns the destination-branch check, the `rtk git` wrapper and the `--abort` path. Hand it the SHA; do not run `git cherry-pick` from here. - `git revert ` adds a new commit undoing it — for un-applying merged work without rewriting history. - `git blame ` attributes each line to the commit that last touched it, when the question is which commit introduced one specific line. diff --git a/plugins/git/skills/git-remotes/references/fetch.md b/plugins/git/skills/git-remotes/references/fetch.md index e0c05ff..0826b17 100644 --- a/plugins/git/skills/git-remotes/references/fetch.md +++ b/plugins/git/skills/git-remotes/references/fetch.md @@ -7,7 +7,9 @@ source_keys: # Fetching -Fetch updates remote-tracking branches (`refs/remotes//*`) and never modifies a local branch, so it is always safe to run. +Fetch **with no refspec** updates remote-tracking branches (`refs/remotes//*`) and leaves every local branch alone. + +That safety comes from the default refspec, not from `fetch` itself. Give it an explicit one and it writes to local branches: verified on Git 2.39.5, `git fetch origin main:probe` fast-forwarded the local `probe` branch, and a `+` prefix force-updates the destination, discarding whatever commits it held. Treat any `fetch` carrying a `:` refspec as a branch update, not a read. - **One remote**: `git fetch ` — all branches - **One branch**: `git fetch ` — the result lands in `FETCH_HEAD`, not a tracking ref diff --git a/plugins/git/skills/git-remotes/references/pull.md b/plugins/git/skills/git-remotes/references/pull.md index 52be576..b769742 100644 --- a/plugins/git/skills/git-remotes/references/pull.md +++ b/plugins/git/skills/git-remotes/references/pull.md @@ -23,9 +23,11 @@ A pull that diverges with no strategy configured fails, and that failure is the ## Config precedence -The installed default varies by Git version — older versions merge on divergence, newer ones -default to `--ff-only` — so an unset `pull.ff` means the same pull behaves differently on different -machines. Set it explicitly. +`--ff-only` is not Git's default on an unset config, and never has been. Older versions silently +merged on divergence; current ones refuse outright — verified on Git 2.39.5, a divergent pull with +nothing configured prints the reconciliation hint and exits 128 with +`fatal: Need to specify how to reconcile divergent branches.` The behaviour therefore still varies +by installed version, and neither variant is the one you want. Set it explicitly. Highest wins: diff --git a/plugins/git/skills/git-submodules/SKILL.md b/plugins/git/skills/git-submodules/SKILL.md index 297f6a2..55d65f2 100644 --- a/plugins/git/skills/git-submodules/SKILL.md +++ b/plugins/git/skills/git-submodules/SKILL.md @@ -3,7 +3,8 @@ name: git-submodules description: > Use when managing Git submodules — the full lifecycle of a nested - repository inside a superproject. + repository inside a superproject — including phrasings that never say the + word, such as "add a dependency repo" or "vendor this repo inside ours". Not multiple checkouts of one repo -> `git-worktrees`. Not the superproject's own remotes -> `git-remotes`. diff --git a/plugins/git/skills/git-submodules/references/setup-and-update.md b/plugins/git/skills/git-submodules/references/setup-and-update.md index dfb9c75..23b0cb0 100644 --- a/plugins/git/skills/git-submodules/references/setup-and-update.md +++ b/plugins/git/skills/git-submodules/references/setup-and-update.md @@ -70,8 +70,8 @@ rtk git submodule update --remote --merge --recursive rtk git commit -am "chore: update submodules to latest" ``` -`--remote` requires `submodule..branch`; without it Git falls back to the remote's default -branch. Commit the superproject afterwards or the new pin is lost on the next `update`. +`--remote` uses `submodule..branch` when it is set; without it Git falls back to the remote's +default branch. Commit the superproject afterwards or the new pin is lost on the next `update`. ## Run one command across every submodule diff --git a/plugins/git/skills/git-submodules/references/sources.md b/plugins/git/skills/git-submodules/references/sources.md index 41c8660..fd3adbc 100644 --- a/plugins/git/skills/git-submodules/references/sources.md +++ b/plugins/git/skills/git-submodules/references/sources.md @@ -22,10 +22,10 @@ source_keys: Other source keys extracted during the git plugin research phase inform sibling skills in the git workflow suite, not this one: -- `context7-git-htmldocs` — git:branches, git:history, git:remotes -- `git-scm-docs` — git:configuration -- `git-scm-worktree-docs` — git:worktrees -- `nvie-gitflow-post`, `atlassian-gitflow-tutorial`, `gitflow-cheatsheet` — git:branches -- `conventional-commits-spec`, `commitlint-config-conventional` — git:commits -- `git-scm-push-docs`, `git-scm-fetch-docs`, `git-scm-pull-docs`, `git-scm-remote-docs` — git:remotes -- `git-scm-bisect-docs`, `git-scm-log-docs`, `git-scm-diff-docs` — git:history +- `context7-git-htmldocs` — git-branches, git-history, git-remotes +- `git-scm-docs` — no current skill; it backed a git-configuration skill that no longer exists and survives here as provenance only +- `git-scm-worktree-docs` — git-worktrees +- `nvie-gitflow-post`, `atlassian-gitflow-tutorial`, `gitflow-cheatsheet` — git-branches +- `conventional-commits-spec`, `commitlint-config-conventional` — git-commits +- `git-scm-push-docs`, `git-scm-fetch-docs`, `git-scm-pull-docs`, `git-scm-remote-docs` — git-remotes +- `git-scm-bisect-docs`, `git-scm-log-docs`, `git-scm-diff-docs` — git-history diff --git a/plugins/git/skills/git-workflow/SKILL.md b/plugins/git/skills/git-workflow/SKILL.md index 40422fb..8f2f871 100644 --- a/plugins/git/skills/git-workflow/SKILL.md +++ b/plugins/git/skills/git-workflow/SKILL.md @@ -28,13 +28,16 @@ metadata: ## Domains -Every request resolves to exactly one of these six. An unambiguous one should have gone straight -to the domain skill; this skill exists for the ones that did not. +Route to the domain that owns the operation, and in sequence when a request spans two — a rebase +that ends in a force-push is `git-commits`, then `git-remotes`. An unambiguous request should have +gone straight to the domain skill; this one exists for the ones that did not. | The request is about | Domain | |---|---| | Writing, amending, squashing, or cherry-picking a commit, and its message | `git-commits` | +| Rebasing onto a new base, or undoing a commit with `reset` | `git-commits` | | Creating, switching, deleting, renaming, tracking, or merging a local branch | `git-branches` | +| Stashing work in progress to move between branches | `git-branches` | | When a change landed, which commit broke something, what to revert or backport | `git-history` | | Anything touching a remote — remote config, fetch, push, pull — even unnamed | `git-remotes` | | A nested repository pinned inside this one by a recorded commit | `git-submodules` | diff --git a/plugins/git/skills/git-worktrees/references/worktrees.md b/plugins/git/skills/git-worktrees/references/worktrees.md index 64172f1..c4d9b22 100644 --- a/plugins/git/skills/git-worktrees/references/worktrees.md +++ b/plugins/git/skills/git-worktrees/references/worktrees.md @@ -53,7 +53,7 @@ final argument of the `--track -b` form. | `-b ` | Create and check out a new branch; fails if it exists | | `-B ` | Like `-b` but resets the branch if it already exists | | `-d` / `--detach` | Detach HEAD; useful for throwaway experiments | -| `--orphan` | Create empty unborn branch | +| `--orphan` | Create empty unborn branch — **Git 2.42+**; earlier versions exit 129 with `error: unknown option 'orphan'`. Fallback below | | `--no-checkout` | Suppress initial checkout (for sparse-checkout setup) | | `--guess-remote` | Look for a matching remote-tracking branch by path basename | | `--lock [--reason ]` | Lock immediately on creation (atomic; avoids race vs. add-then-lock) | @@ -67,7 +67,22 @@ Using `-` as `` is shorthand for `@{-1}` (the branch checked out bef ```bash git worktree add --orphan -b ``` -Creates an empty branch with no commits. +Creates an empty branch with no commits. **`--orphan` needs Git 2.42 or later** — it was added +upstream in 2.42, and on 2.39.5 this fails with `error: unknown option 'orphan'` and exit 129. +Check `git --version` before reaching for it. + +Fallback on older Git, verified on 2.39.5 — detach first, then orphan the linked worktree in place, +which leaves the main worktree on its own branch throughout: + +```bash +git worktree add -d # linked worktree, detached HEAD +cd +git switch --orphan # unborn branch: empty index, empty working tree +``` + +`git worktree list` then shows the new worktree at `0000000 []` until its first commit. +Do not substitute `git switch --orphan` in the *main* worktree: it clears that checkout, which is +the disruption worktrees exist to avoid. ## Sparse-checkout worktree