Skip to main content

git-workflow

Use when naming or scoping a branch, writing or fixing a commit message, picking the gitmoji for a commit, untangling history (rebase versus merge versus squash), or cutting a versioned release — the portable git-convention layer for any repo. Covers gitmoji + Conventional Commits, SemVer tags, branch hygiene, force-push safety and gh pr/release mechanics. NOT the land-it decision and pre-ship checklist (that is `ship`), NOT an isolated checkout before coding (that is `worktrees`), NOT CI/CD release automation (that is `deployment`).

インストールへ移動

ソース情報

リポジトリ
ericrisco/rsc-harness
ソースの最終更新活動
2026年8月20日 17:10
検出された SKILL.md の言語
英語
スター
110
フォーク
9

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

ファイルエクスプローラー
5 ファイル

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
git-workflow
description
Use when naming or scoping a branch, writing or fixing a commit message, picking the gitmoji for a commit, untangling history (rebase versus merge versus squash), or cutting a versioned release — the portable git-convention layer for any repo. Covers gitmoji + Conventional Commits, SemVer tags, branch hygiene, force-push safety and gh pr/release mechanics. NOT the land-it decision and pre-ship checklist (that is `ship`), NOT an isolated checkout before coding (that is `worktrees`), NOT CI/CD release automation (that is `deployment`).
tags
["git","version-control","conventional-commits","gitmoji","semver","pull-request"]
recommends
["ship","worktrees","deployment","github-actions"]
origin
risco
# git-workflow — the grammar and hygiene of version control Git history is a message to the next human who reads `git log`, runs `git blame` on a broken line, or bisects a regression at 2am. That human is usually future-you. **Every rule in this skill exists to make the next reader's job faster**, not to make this moment cheaper. A repo with legible branch names, conventional commits, and a clean linear narrative is a repo you can reason about; a repo with `wip`, `fix stuff`, and force-pushed shared history is one you fight. This is the **portable convention layer**. It is independent of any SDD phase or CI platform — it is the grammar that `../ship/SKILL.md`, `../worktrees/SKILL.md`, and `../deployment/SKILL.md` all lean on. It does not decide *whether to land* the work (that is ship) and it does not automate releases in a pipeline (that is deployment). It tells you how to name, commit, untangle, and tag — correctly. ## Branch naming Name a branch from its *intent*, prefixed by its kind, as a kebab-case slug. Keep it short-lived: hours to days, not weeks. Long branches drift from `main` and turn into merge pain. | Prefix | Use for | Why | |--------------|----------------------------------------------|--------------------------------------------------| | `feat/` | a new capability | matches the `feat` commit type; signals a MINOR | | `fix/` | a bug fix | matches `fix`; signals a PATCH | | `hotfix/` | an urgent fix landing straight to production | flags "skip the slow path" to reviewers | | `chore/` | tooling, deps, config — no product behavior | keeps non-feature noise out of the feature log | | `docs/` | documentation only | reviewers can fast-track, no test gate needed | | `refactor/` | restructure without behavior change | sets the expectation: tests stay green, no new behavior | Slug rules: derive it from the issue title or the one-sentence intent, lowercase, dash-separated, no spaces or `/` inside the slug. Optionally suffix the issue number. ```text Bad my-stuff (kind unknown, intent unknown) Bad eric-branch-2 (names the author and a counter, not the work) Good feat/oauth-pkce-flow Good fix/expired-refresh-token-401 Good chore/bump-node-22 ``` ## Commit grammar — gitmoji + Conventional Commits Write every commit to **Conventional Commits 1.0.0**, opened by a **gitmoji**. The structure: ```text <gitmoji> type(scope)!: subject body — what changed and why, wrapped, optional BREAKING CHANGE: description of the incompatible change Fixes #123 ``` - The **gitmoji is mandatory** and comes first — the intention of the change, readable in one glyph when you scan `git log --oneline`. `type` is what tooling reads; the emoji is what humans read. - `type` is mandatory. `scope` in parentheses is optional. `!` before the colon marks a breaking change. - Subject: imperative mood ("add", not "added"/"adds"), ≤72 chars, no trailing period. - Body explains *why*, not *what the diff already shows*. Separate from subject by a blank line. - Footers go last. `Fixes #123` / `Closes #123` in the body auto-closes that issue when the PR merges. Type → SemVer effect: | Type | SemVer bump | Notes | |-----------------------------------|-------------|----------------------------------------------------| | `feat` | MINOR | a new capability | | `fix` | PATCH | a bug fix | | `docs`, `chore`, `refactor`, `test`, `build`, `ci`, `perf`, `style`, `revert` | none | allowed, but no implicit version bump | | any type with `!` or a `BREAKING CHANGE:` footer | **MAJOR** | overrides the above regardless of type | `BREAKING CHANGE` **must be uppercase** in the footer; the type/scope units are case-insensitive but write them lowercase by convention. Type → gitmoji, the everyday set (the full 75-emoji table, and *why* the emoji never replaces the type, are in **`references/gitmoji.md`**): | Type | gitmoji | Type | gitmoji | Type | gitmoji | |------------|---------|------------|---------|-----------|---------| | `feat` | ✨ | `refactor` | ♻️ | `build` | 📦️ | | `fix` | 🐛 | `test` | ✅ | `style` | 🎨 | | `docs` | 📝 | `perf` | ⚡️ | `revert` | ⏪️ | | `chore` | 🔧 | `ci` | 👷 | breaking | 💥 | Pick by **intention**, not by which file changed, and prefer the specific one: 🚑️ for a production hotfix, 🩹 for a trivial non-critical fix, 🔥 for a deletion, 🚚 for a rename, ⬆️ for a dep bump, 🔖 for a release commit. ```text Bad fix stuff Bad updates Bad Fixed the login bug. (past tense, capitalized, trailing period) Bad fix(auth): reject expired refresh tokens (no gitmoji) Bad ✨ added a search endpoint (gitmoji but no type → no derivable bump) Good 🐛 fix(auth): reject expired refresh tokens Good ✨ feat(api): add /v2/search endpoint with cursor paging Good ♻️ refactor(parser): extract token scanner, no behavior change ``` A breaking change, both forms equivalent: ```text 💥 feat(api)!: drop the legacy /v1 search endpoint BREAKING CHANGE: /v1/search is removed; callers must migrate to /v2/search. ``` If the repo runs a **strict** conventional parser (commitlint, semantic-release) it anchors the type at position 0 and rejects the emoji prefix. Either widen its `headerPattern` — the config is in `references/gitmoji.md` — or move the emoji behind the header (`feat(api): ✨ add cursor paging`), which every parser accepts. Both forms satisfy this convention; dropping the gitmoji does not. **Authorship is always Eric.** Never add a `Co-Authored-By: Claude` trailer, never a "Generated with" footer, never any line crediting an AI tool — in a commit *or* a PR body. The work is Eric's; the agent is a tool, like the compiler. ## History hygiene — rebase, merge, or squash? Decide by who else has the commits. The lease rule below is non-negotiable. | Situation | Do this | Why | |------------------------------------------------------|------------------------------------------------------|------------------------------------------------------------| | Private branch, only you have it, want linear history | `git rebase main`, then `git push --force-with-lease`| rebase rewrites hashes; safe because nobody built on them | | Branch others have pulled / built on | `git merge main` — **never** rebase it | rebase changes every hash; collaborators' work diverges | | Noisy PR (many `wip` commits) | squash-merge into one gitmoji + conventional commit | `main` gets one meaningful entry, not 9 scratch commits | | Already pushed, shared, *and* you rewrote it | **STOP** — coordinate, or `git revert` instead | force-pushing shared history breaks everyone downstream | After a rebase, push with `--force-with-lease`, never bare `--force`: ```bash git push --force-with-lease # refuses if the remote moved since you fetched — catches a teammate's push git push --force # blindly overwrites — can erase a teammate's commits ``` The interactive cleanup loop (`rebase -i`, `fixup`/`squash`/`reword`/`drop`, `--autosquash`, the conflict→continue cycle, and recovery via `git reflog`) is a long branchy procedure — see **`references/interactive-rebase.md`** rather than reaching for it on every commit. ## Releases Derive the version bump from the commit log, never by guessing. Scan the commits since the last tag: - any `BREAKING CHANGE:` / `!` → **MAJOR** (`v1.4.2` → `v2.0.0`) - otherwise any `feat:` → **MINOR** (`v1.4.2` → `v1.5.0`) - otherwise only `fix:`/others → **PATCH** (`v1.4.2` → `v1.4.3`) Tag with the `vMAJOR.MINOR.PATCH` form, annotated, then create the release with auto-generated notes: ```bash git tag -a v2.0.0 -m "v2.0.0" git push origin v2.0.0 gh release create v2.0.0 --generate-notes # notes via the GitHub Release Notes API gh release create v2.0.0 --generate-notes --draft # stage notes, publish later gh release create v2.0.0-rc.1 --generate-notes --prerelease ``` GitHub auto-assigns the "latest" label by semver order unless you set it. With release immutability enabled, **a published release's tag cannot be edited or deleted** — get the version right before you publish. ```text Bad added a feature + a breaking config change, tagged v1.5.0 (breaking change → must be MAJOR) Good same changes → v2.0.0, bump derived from the BREAKING CHANGE footer in the log ``` Automating any of this on tag push (a `release.yml` workflow, OIDC to a registry) is **deployment** — see `../deployment/SKILL.md`. This skill covers the manual/local release act. ## PR mechanics — then hand off to ship Open the PR with autofilled title/body from the commits, against the right base: ```bash gh pr create --fill --base main # title/body from commits; --base falls back to repo default ``` Put `Fixes #123` in the body to link and auto-close the issue on merge. A PR body should let the reviewer understand the change without reading every line of the diff. The **decision to land** — direct-merge vs PR vs park, the pre-ship safety checklist, the actual merge — belongs to `../ship/SKILL.md`. This skill only makes the branch, commits, and PR body clean enough to hand over. Setting up the isolated checkout *before* you start coding is `../worktrees/SKILL.md`. ## Anti-patterns | Anti-pattern | Why it hurts | Instead | |-------------------------------------------------------|-----------------------------------------------------------|------------------------------------------------------| | `git push --force` on a shared branch | silently erases teammates' commits | `--force-with-lease`, or don't rewrite shared history | | `git commit -m "wip"` / `"fix"` / `"updates"` | the log carries zero signal for the next reader | `<gitmoji> type(scope): imperative subject` | | Commit message with no gitmoji | `git log --oneline` reads as a wall of undifferentiated text | pick the intention's emoji (`references/gitmoji.md`) | | Mixing unrelated changes in one commit | can't revert or review one concern in isolation | one logical change per commit | | Long-lived branch (weeks) | diverges from `main`, merge becomes a battle | short-lived; rebase or merge `main` in often | | Hand-computing the semver bump | breaking change shipped as a MINOR → broken downstream | derive the bump from the commit log | | Rebasing a public/shared branch | rewrites hashes others built on | merge shared branches; rebase only private ones | | Committing generated/secret files | leaks credentials, bloats history irreversibly | `.gitignore`; rotate any secret that slipped in | | `BREAKING CHANGE` lowercase | tooling won't detect it → wrong (too-low) bump | uppercase `BREAKING CHANGE:` in the footer | | PR with no description | reviewer reverse-engineers intent from the diff | `--fill` plus a why, link the issue | | Tagging a release with no notes | users can't tell what changed | `gh release create --generate-notes` | | `Co-Authored-By: Claude` / "Generated with" footer | forges authorship onto a tool | author is always Eric; no AI attribution | ## Checklist — before a PR or a release - [ ] Working tree clean (`git status`), no stray or generated files staged. - [ ] Branch rebased on / merged with current `main`; no avoidable conflicts. - [ ] Every commit carries its gitmoji **and** a conventional header; `wip`/scratch commits squashed away. - [ ] No secrets, no AI-attribution trailers. - [ ] PR body explains the why and links the issue (`Fixes #`). - [ ] (Release) version bump **derived from the commit log**, tag is `vX.Y.Z`, annotated. - [ ] (Release) `gh release create vX.Y.Z --generate-notes`; version confirmed before publishing (immutable once published).
GitHubで見る