# Git Patch Workflow

> Generic workflow for implementing tasks on any git repo or provided file set and delivering verified git-format-patch files the user applies with git am. ONLY activate when user explicitly invokes with /git-patch-workflow or says "use git-patch-workflow". Do NOT auto-trigger on git URLs, repo mentions, patch requests, or coding tasks.

- Skill: `6543/git-patch-workflow` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add 6543/git-patch-workflow`
- Raw SKILL.md: https://api.skillmd.com/api/skills/6543/git-patch-workflow/raw
- Safety review: pending (external: skill-scanner PASS, skillspector CAUTION)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: 6543 (https://skillmd.com/u/6543)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/6543/git-patch-workflow

---


# Git Patch Workflow

Produce minimal, tested, `git am`-ready patches against the exact state the user applies onto.

## On activation — print this first

Print the apply snippet in the user's default shell. Default to **bash**; if a pref declares another shell, translate the loop and note which was used.

````
Apply patches — bash:
```bash
for f in *.patch; do git am "$f"; done
```
````

Keep only one revision per number in the apply dir (see Numbering), else the glob applies duplicates.

## Bootstrap

Two modes, by what the user gave.

**A — repo URL / git ref given.** That ref is the **anchor**. Clone if absent; if reusing a checkout, confirm its remote matches and preserve unrelated user changes (never stash/discard to get a clean tree). Resolve the anchor to a commit.

**Identity — do not clobber.** Use the existing repo/user `user.name`/`user.email`. If either is missing, ask; set it only in this checkout. Never overwrite with a Claude default.

**Sync before every task** — `git fetch`, then **rebase** local work onto the anchor: `git rebase <anchor>`. Never blind `git pull`, never `reset --hard` onto upstream (nukes unpushed stand-in commits).
- Upstream unchanged → no-op.
- Your patches landed (patch-id match) → they drop empty on rebase; verify an *altered* upstream impl before dropping the local stand-in.
- Upstream moved with foreign commits → replay, resolve only understood conflicts, regenerate affected patches.
- Ambiguous authorship/equivalence → ask.

The apply target may be a **PR head or a locally-prepared tree**, not `main`: fetch that ref (`git fetch origin pull/<N>/head:pr-<N>`) or replay the user's cleanups, commit as baseline, build on top.

**B — files only, no upstream.** `git init`, reproduce the given paths (none → repo root), commit unchanged as baseline, identity as above. No fetch/rebase; assume delivered patches are applied, build on local commits.

**Record the base** after sync, before editing — every patch is generated and verified against it:
```bash
APPLY_BASE=$(git rev-parse HEAD)
```
If the target changes, re-sync and reset `APPLY_BASE`. For a rework, `APPLY_BASE` is the rejected commit's parent.

If the mode is unclear, ask. On first activation, note in one line which shell and identity were used.

## Task intake

1. Read structure, repo instructions (`AGENTS.md`, `CONTRIBUTING.md`, CI config), relevant sources, tests.
2. Research unknown APIs/libs from authoritative sources. Don't guess.
3. Re-read files right before editing. Stale context breaks `str_replace`.
4. Plan in ≤3 bullets. Ask only if a missing choice changes the result or an op is destructive.

**Go:** read `go.mod` first; ensure the available Go satisfies the declared `go`/`toolchain` version, install/activate it if possible, else report what couldn't be verified.

## Implementation

- Smallest diff that solves it. No drive-by renames, restructuring, or re-scoping; preserve the author's deliberate patterns.
- TDD where practical: add/failing test → implement → green.
- One logical, bisectable change per commit.
- Update docs/README in the same commit as the behavior change.
- Preserve unrelated user changes; never discard them for a clean tree.
- More than one materially different fix, or ambiguous behavior → ask.

## Formatting

Pick format/validate commands once per series, preferring repo/CI/tool-config declarations. Else the language default — for Go, `gofumpt` **only if the project uses it**, else `gofmt`.

Probe baseline without dirtying the tree (check flag, or run then `git checkout -- .`). Not formatter-clean → don't format (no churn). Clean → format every patch before committing.

## Commit

Conventional Commits. Subject ≤72 chars. Body = *why*, not *what*. No AI attribution. Inspect the staged diff first — only the intended change.

```
fix(scope): concise imperative summary

Why it's needed and any tradeoff.
Refs #123
```

## Generate patches

Clear stale patches first — `/mnt/user-data/outputs/` persists across sessions and branches.

```bash
cd "$REPO_DIR"
git add <files>; git commit -m "..."
rm -f /mnt/user-data/outputs/*.patch     # or just the NNNN-* you're regenerating

# N = your session counter; generate against the recorded base
git format-patch --start-number N "$APPLY_BASE..HEAD" -o /mnt/user-data/outputs/
```

Confirm patch count == commits in `APPLY_BASE..HEAD`. Names `NNNN-subject.patch`; rework `NNNN-subject-vN.patch` (rename manually — never `git format-patch -vN`, its `v2-` prefix breaks sort order).

## Verify before delivery — mandatory

Never `present_files` unverified. Detached worktree at the recorded base, `git am` the batch, run the repo's real checks there (format, focused tests, build) — not just apply-ability:

```bash
V=$(mktemp -d)/wt
git worktree add --detach "$V" "$APPLY_BASE"
git -C "$V" am /mnt/user-data/outputs/*.patch && echo AM_OK    # then fmt/test/build in "$V"
git worktree remove --force "$V"
```

Any `am` or check failure → fix base/source, regenerate, re-verify. Deliver only all-clean, with the exact `git am` command and any old files to delete. **`git am`, never `git apply`** — apply silently drops mismatched hunks into `.rej` and a hollow commit.

## Numbering: new / follow-up / rework / abandon

Counter is **per session**. Default: a delivered patch **was applied**; don't re-derive it. Pick the case before naming.

- **New / follow-up** — next unused number, build on current HEAD. Never squash/replace a delivered patch; append.
- **Rework** (rejected/broken, still wanted) — rebuild from the rejected commit's parent (preserve old history on a backup branch, cherry-pick later dependents). **Reuse the same number** + `-v2`, `-v3`. Commit body notes what was wrong. Tell the user which old file to delete.
- **Abandon** (change dropped) — drop the commit, **burn the number** (leave a gap), next work takes the next fresh number. Tell the user to delete the file. No `-vN`.

Unclear whether a patch was applied → ask. An applied change needs a follow-up or revert, not a same-number rework.

## Pitfalls

- **Sync = fetch + rebase**, never `pull`/`reset --hard` — local carries stand-ins for delivered patches.
- **Verify with real checks** on a clean worktree before delivery; catches wrong-base rejects and stray-file pollution.
- **`git am`, never `git apply`.**
- **Don't clobber Git identity** — the user cares about authorship.
- **Outputs dir persists** across sessions/branches; clear stale patches, one revision per number.
- **Smallest diff**; no drive-by refactors.
- **No toolchain = no compile check.** Say so.
- **Number reuse only for rework** (`-vN`); abandon burns; new/follow-up take the next.

