--- name: git-branches description: > Use when creating, switching, deleting, renaming, tracking, merging, or comparing local git branches under GitHub Flow or Gitflow. Not writing or rewriting commits -> `git-commits`. Not history inspection -> `git-history`. Not a Gitea remote's branches -> `gitea-branches`. metadata: category: git source_keys: - context7-git-htmldocs - nvie-gitflow-post - atlassian-gitflow-tutorial - gitflow-cheatsheet --- ## Gotchas - **Uncommitted changes abort a switch.** `git switch` refuses rather than clobbering conflicting local edits. Offer to stash and retry — forcing the checkout past it is how work disappears. - **A branch and a tag can carry the same name.** Prefer `git switch` over `git checkout`, and where a command accepts either ref, disambiguate with `refs/heads/` or `refs/tags/`. - **`main` and `master` are a refusal, not a gate.** Force-pushing, force-deleting, or renaming them is rejected even when the caller passes `confirm: true` — no flag makes the remote's history recoverable. Offer a new branch instead. ## Step 1 — Determine the branching pattern Read `branching_pattern` from the git plugin config (`.claude/plugins/git/config.json`; the plugin root's `config.example.json` shows the shape). Default: `github-flow`. With no config, infer Gitflow from the presence of a `develop` or `release/*` branch, and GitHub Flow otherwise. The two patterns are not mixable, and the wrong merge rule silently damages history. If the action touches a base branch, a name prefix, or a merge rule, read `references/branch-patterns.md`. ## Step 2 — Dispatch on the action | Action | Reference | |---|---| | create, switch, delete, rename, track, list, get-intent | `references/branch-operations.md` | | merge a branch, resolve merge conflicts | `references/merging.md` | | compare two branches, find their divergence | `references/comparing-branches.md` | Load only the file the action needs. A destructive action still passes Step 3 first. ## Step 3 — Gate destructive operations Before any delete or force-delete that loses history: - [ ] Does the branch track a remote? Warn if so. - [ ] Are there unpushed commits on it? Warn if so. - [ ] Did the caller pass `confirm: true`? Fail if not — for a human caller, prompt interactively instead of failing. 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. ## Step 5 — Return a structured result Return every operation in this shape rather than prose, including failures — a calling agent chains its next operation on the result and cannot parse a sentence. ```json { "success": true, "action": "create|switch|delete|rename|track|list|get-intent", "branch": "", "message": "descriptive message", "intent": "", "tracking": "origin/", "error": "", "suggestion": "" } ``` When the failure is uncommitted local changes, set `"suggestion": "stash changes and retry"` so the caller can offer recovery rather than surfacing a dead end. When a calling agent supplies a structured request rather than prose, read `references/orchestrator-contract.md` for the request schema.