客製 /commit Skill:commit 前自動比對 module/export/print 的 SQL 一致性


Legacy 系統最容易出的包:改了編輯頁的 SQL,忘了同步改匯出和列印版

同一筆資料,編輯頁讀一個 SQL、列印頁讀另一個、匯出又一個——三份各自獨立。改了編輯頁的查詢條件,匯出還是舊的,使用者匯出的資料就跟畫面對不上。這種 bug 不會在當下爆,會在一週後客戶對帳時才發現。

我把這個檢查做進 /commit slash command:每次 commit 前,Claude Code 自動找出對應的匯出/列印檔、比對 SQL、掃索引雷區、分析表級寫入影響。這篇拆解這個 101 行的 skill。


為什麼是 Slash Command,不是 Hook

我有攔截危險指令的 PreToolUse Hook,那適合「擋」。但 commit 前的一致性檢查不是「擋」——是一套有順序的流程:看 diff → 找對應檔 → 讀檔比對 → 報告 → 問 issue 編號 → 產 commit message。

Slash command 適合封裝「多步驟的流程」,hook 適合「單點攔截」。/commit 是流程,所以做成 skill。

frontmatter 限定工具範圍:

---
allowed-tools: Bash(git add:*), Bash(git status:*), Bash(git commit:*), Bash(git diff:*), Bash(git log:*), Glob, Grep
description: Commit - 安全的 git commit 流程
---

只給 git 唯讀指令 + Glob/Grep——不給 Edit/Write,因為 commit 流程不該改檔案,只該檢查和提交。


流程總覽

1. git status / git diff / git diff --cached  → 看改了什麼
2. 沒暫存改動?→ 問要 add 哪些
3. 資料一致性檢查(核心,自動執行)
   ├─ 5a 跳過條件(純前端/設定/SQL migration/文件 → 跳過)
   ├─ 5b 找對應檔(module → export / print / word / download)
   ├─ 5d SQL 雷區掃描(diff 含 SQL 時)
   ├─ 5e 表級影響(diff 含寫入時)
   └─ 5f 報告 → 有 ⚠️ 就問人,不自行決定
4. 問 issue 編號
5. 產 commit message(issue-{N} 開頭)
6. 確認後 git commit

核心是第 3 步。其他步驟是包裝。


5a:先判斷要不要檢查

不是每次 commit 都需要一致性檢查。先排除不相關的:

### 5a. 跳過條件(任一符合則整段跳過)

- 只動 CSS / JS / HTML 樣板(純前端 UI)
- 只動設定檔(docker-compose、php.ini、.gitignore、composer.json)
- 只動 SQL migration(sql/issue-*.sql)
- 只動文件(doc/、CLAUDE.md、README*)

先講「什麼時候不用做」比「什麼時候要做」省事——大部分 commit 是前端微調或設定,直接跳過,不浪費 token 跑檢查。


5b:從改動檔反推對應檔

這是整個 skill 的核心。Legacy 系統的命名有規律:編輯頁在 module/、列印在 print/、匯出在 export/。從改動的檔案路徑解析出 {mod}{func},就能推出對應檔在哪。

### 5b. 對應檔案搜尋(精確 → 模糊)

從改動檔案路徑解析 {mod} 和 {func}:
- module_a/module/{mod}/{func}.php
- module_a/{func}.php

| 角色 | 路徑模式 | 同步必要 |
|------|----------|----------|
| AJAX/Class handler | grep 改動檔內 action="class/*" 或 url:"class/*" 抽出 endpoint | 必須(若改 SQL/欄位) |
| 匯出 | module_a/export/export_{func}.php、export*{func}*.php | 必須(若改 SQL) |
| 列印 | module_a/print/{mod}/{func}.php、print/{func}.php | 必須(若改 SQL) |
| Word 模板 | module_a/wordtemplate/{mod}/{func}*.php | 視情況 |
| 下載 | module_a/filedownload/**/*{func}*.php | 視情況 |

關鍵防呆:同名不等於對應

**重要**:精確路徑找不到才模糊搜,且 form4_5 / form4_a 等同名前綴
不自動算對應,必須讀檔內容判斷是否處理同一資料/邏輯,
否則只標註「同名但不相關」。

這條防呆很重要。form4_5form4_a 名字像,但可能是完全不同的功能。Skill 要求 Claude Code 讀檔內容確認,不是看檔名猜。否則會產生一堆假對應、淹沒真正要注意的。


5d:SQL 索引雷區掃描

如果 diff 裡有新增 SQL(+ 行),自動掃描已知的效能地雷:

### 5d. SQL 雷區自動掃描(diff 含 SQL 時)

- WHERE\s+.*date_format\s*\( → 會停用索引
- ORDER BY\s+\w+\s*,\s*\w+ → 多欄 ORDER BY 可能讓 MySQL 選錯索引,提醒 FORCE INDEX
- JOIN 大表(sign、service_admin_01、demo-org-1.*)在 FROM/JOIN 早期位置 → 提醒移到最後 JOIN
- SELECT * 在大表查詢 → 提醒指定欄位

這四條都是這個專案踩過的真實效能坑(我寫過DATE_FORMAT 反模式掃蕩那篇)。把它們寫進 commit 流程,等於每次 commit 都做一次 mini 效能 review——新引入的 date_format in WHERE 在 commit 當下就被攔,不會等到上線變慢才發現。


5e:表級寫入影響分析

如果 diff 裡有 INSERT/UPDATE/DELETE 某張表,自動找出「還有誰也寫這張表」:

### 5e. 表級影響(diff 含寫入操作時)

若 diff 含 INSERT INTO / UPDATE / DELETE FROM 接某張表名 T:
- 用 Grep 找全 codebase 還有哪些檔案寫入 T
- 列出清單,提醒:「以下檔案也寫入 T,本次邏輯改動是否需要同步?」
- 特別關注:
  - service_admin* 系列(admin / admin01 / admin02 / admin03 一向連動)
  - patient、employer、sign 等核心表

這解決另一種隱形坑:多個地方寫同一張表,改了寫入邏輯卻只改一處。例如申報用的 service_admin01/02/03 是一組連動表,改了一個的寫入邏輯,另外幾個常常要跟著改。Skill 主動列出「還有這些檔案也寫這張表」,讓人決定要不要一起改。


5f:報告格式 + 不自行決定

### 5f. 報告格式

📋 資料一致性檢查結果:
✅/⚠️ AJAX handler:{path or「無」}
✅/⚠️ 對應匯出:{path or「無」}
✅/⚠️ 對應列印:{path or「無」}
✅/⚠️ SQL 雷區:{命中 pattern 描述 or「無」}
✅/⚠️ 表級影響:寫入 {table},另有 N 處檔案也寫入此表

- 全 ✅ → 直接繼續
- 有 ⚠️ → 列出具體路徑與差異,詢問用戶是否繼續,不要自行決定

最後一條是關鍵原則:有疑慮時問人,不自行決定。Skill 不會因為「找到對應匯出檔但沒同步」就自己去改或自己跳過——它列出來、問人。一致性檢查的價值在「提醒人類注意」,不是「AI 自己判斷該不該管」。


commit message 規範

6. 詢問用戶 issue 編號(例如:421)
7. 產生 commit message,格式:
   issue-{編號} {改動描述}

## 規則
- 不要加 Co-Authored-By
- 不要加 Generated with Claude Code
- 不要加任何 emoji 簽名
- 不要自動 push
- commit message 第一行必須是 issue-{編號} 開頭
- 如果用戶沒有提供編號,必須詢問

團隊規範:commit 開頭必須是 issue-{編號}(對應 issue 追蹤系統),且不加 AI 署名。把這些寫進 skill,每次 commit 都自動遵守——不用每次提醒 Claude Code「不要加 Co-Authored-By」。


這個 Skill 解決的真實問題

沒有 skill有 skill
改編輯頁 SQL,忘了改匯出 → 一週後對帳爆炸commit 前自動列出對應匯出檔,提醒同步
新引入 date_format in WHERE → 上線變慢commit 當下掃出索引雷區
改了 service_admin01 寫入,漏改連動的 02/03自動列出所有寫此表的檔案
commit message 忘了加 issue 編號強制詢問 + 格式化
不小心加了 AI 署名規則明確禁止

為什麼這值得做成 Skill

這個檢查人也能做——每次 commit 前手動 grep 對應的匯出/列印檔、看有沒有同步。但人會累、會忘、會偷懶。

寫進 skill 後:

  1. 一致性:每次 commit 都做同樣的檢查,不會今天認真明天偷懶
  2. 知識沉澱:「編輯頁對應匯出在 export/、列印在 print/」這個命名規律寫進 skill,新人不用學
  3. AI 友善:Claude Code 跑 /commit 時自動套用,報告格式固定、可讀

這是 Legacy 多檔架構的「補償機制」——架構上三份 SQL 各自獨立沒辦法短期改,但可以用 commit 流程確保它們不會默默走偏。


給其他人的借鑑

如果你的專案也有「同一邏輯散在多個檔案」的問題(編輯/列印/匯出、或 model/view/serializer),可以把一致性檢查做進 /commit

  1. 找出命名規律:你的對應檔在哪?(print/{func}.phpexport_{func}.php?)寫成路徑模式表
  2. 列出已知雷區:你的專案有哪些反覆出現的效能/正確性陷阱?寫成 5d 那種掃描清單
  3. 連動表清單:哪些表是「一起改」的?寫進 5e
  4. 防呆:同名 ≠ 對應,強制讀檔確認
  5. 有疑慮問人:skill 報告問題,不自行決定要不要管

結語

/commit 不只是「幫我 commit」——它是把「資深工程師 commit 前會檢查的東西」固化成流程。

對 Legacy 多檔架構來說,最痛的不是寫新功能,是改舊功能時漏掉連動的地方。這個 skill 把「改了 A 要記得同步 B、C、D」從「靠記性」變成「每次 commit 自動提醒」。

101 行 markdown,把一個容易遺漏的 review 步驟變成 commit 流程的固定環節。如果你也在維護「改一處要連動多處」的系統,這個 pattern 很值得抄。