Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
85 lines
6.1 KiB
Markdown
85 lines
6.1 KiB
Markdown
---
|
||
name: spec-git-safety
|
||
description: JSC plugins 共用「Git 安全操作規範」:不破壞既有工作(未提交變更先提醒、絕不 reset --hard/checkout -f/clean)、git mv 保留歷史、develop → master 後備分支選擇、pull --ff-only、分支一律先跟使用者確認(分析前確認來源分支、寫檔前確認目標分支,不從目前 checkout 推定,只讀階段不代為切換)、工作分支選擇(用 git remote show origin/origin/HEAD 判定遠端預設分支、develop 不存在時從遠端預設分支建立、只有來源與目標分支同名才開新分支)、保守解衝突、建立分支不覆蓋(時間戳或短 hash)。當其他 skill 內文引用 spec-git-safety 或 /jsc-shared:spec-git-safety、或執行任何會操作 git 工作區/分支的 JSC skill 時載入此 skill。單獨被使用者呼叫時,直接說明本規範內容。
|
||
---
|
||
|
||
# spec-git-safety — 共用 Git 安全操作規範
|
||
|
||
所有 JSC skills 操作 git 工作區、分支與遠端時,一律遵守以下規範。
|
||
|
||
## 不破壞既有工作
|
||
|
||
- 改寫/覆寫/搬移檔案前,若工作區有未提交變更,先提醒使用者建議先 commit/備份。
|
||
- **絕不** `reset --hard`/`checkout -f`/`clean`,也不刪除使用者既有原始碼、不強制丟棄未提交變更。
|
||
- 未提交變更導致切換分支/pull/建立分支失敗時,**停止並回報**,請使用者先處理;不可強制丟棄。
|
||
- 目錄已存在且非預期內容(如非 git repo)→ 回報並略過,**不刪除、不覆蓋**。
|
||
|
||
## 移動檔案優先 `git mv`
|
||
|
||
- 搬移/改名檔案優先用 `git mv` 保留歷史。
|
||
- 大小寫不敏感的檔案系統上需兩段式改名(先 `git mv A A.tmp` 再 `git mv A.tmp a`)。
|
||
- 改名後必須同步更新專案內所有引用(設定檔、CI、文件連結),確保行為不變。
|
||
|
||
## develop → master 後備分支
|
||
|
||
需要基準/後備分支時(當前分支不在遠端、clone 後選工作分支、PR 目標後備),依序:
|
||
|
||
1. `origin/develop` 存在 → 用 `develop`。
|
||
2. 否則 `origin/master` 存在 → 用 `master`。
|
||
3. 兩者皆無 → 回報「找不到 develop/master」並停止或略過該項,**不臆測其他分支**。
|
||
|
||
切換寫法:
|
||
|
||
```bash
|
||
git switch develop 2>/dev/null || git switch -c develop --track origin/develop
|
||
```
|
||
|
||
- 切換後備分支屬不可忽略的狀態變更,需明確告知使用者已從原分支切換到哪個分支。
|
||
- 批次更新既有 repo 時用 `git pull --ff-only`;無法快進(本地與遠端分歧)→ 回報需人工處理,**不**自動 merge/rebase/reset。
|
||
|
||
## 分支一律先跟使用者確認
|
||
|
||
動手之前先確認分支,不可從「目前 checkout 的分支」推定使用者的意圖:
|
||
|
||
| 情境 | 要確認的分支 | 確認時機 |
|
||
| --- | --- | --- |
|
||
| 分析既有程式碼(例:`/jsc-sdlc:analyze`) | **來源分支**——哪條分支的程式碼算現況 | 讀任何程式碼之前 |
|
||
| 實作、修改程式碼(例:`/jsc-sdlc:implement`) | **目標分支**——這批工作要合併進哪條分支 | 寫任何檔案之前 |
|
||
|
||
確認方式:
|
||
|
||
1. 先把事實攤開:目前分支、工作區是否乾淨、遠端有哪些分支(`git branch -r`)、依上一節判定出的遠端預設分支。
|
||
2. 依 `/jsc-shared:spec-ask-user` 的決策樹詢問,每個選項都要標明影響範圍。分析錯分支會產出對不上程式碼的工作包;目標分支錯了則 PR 會開到錯的地方。
|
||
3. 把確認結果寫進該 skill 的產出(分析頁的來源分支欄、PR 的目標分支),後續步驟一律沿用同一個答案,不再自行改判。
|
||
4. **只讀取的階段不切分支**:需要換分支才能讀到正確現況時,停下來請使用者自己切換,不代為 `switch`、不 `stash`、不動工作區。
|
||
5. 使用者沒回答就**不預設** `develop`/`master`;預設值只在使用者明確同意後才成立。
|
||
|
||
判定遠端預設分支,以及是否需要為當前操作另開一條工作分支:
|
||
|
||
- **判定遠端預設分支**:優先用 `git symbolic-ref --quiet refs/remotes/origin/HEAD`(結果形如 `refs/remotes/origin/<預設分支>`),取不到時退而用 `git remote show origin`(找輸出中的 `HEAD branch:` 那行)。兩者都取不到 → 回報並停止,**不臆測** `master`/`main`。
|
||
- **`develop` 在遠端不存在時**,改由上一步判定出的遠端預設分支(通常是 `master`,但仍須以實測結果為準,不可不判定就固定假設)建立:
|
||
|
||
```bash
|
||
git switch -c develop "origin/<上一步判定出的遠端預設分支>"
|
||
```
|
||
|
||
- **只有來源分支與目標分支同名時才開新的工作分支**:
|
||
- 同名 → 不可在該分支上直接操作/commit,也不可直接把它 push 成目標分支。改從已更新到最新的目標分支建立新的工作分支,後續操作(修復、commit、push)都以新分支為準。
|
||
- 不同名 → 直接在目前分支操作,不另開分支;即使目前分支已存在對應的遠端分支,也照常在目前分支處理。
|
||
- 新工作分支的命名(避免覆蓋既有分支、加時間戳或短 hash)依下方「建立分支不覆蓋」規範辦理。
|
||
- 切換或建立分支皆屬不可忽略的狀態變更,需在輸出中明確告知使用者原因(例如「來源分支與目標分支同名」或「遠端沒有 develop,已從 `<預設分支>` 建立」)與結果的分支名稱。
|
||
|
||
## 保守解衝突
|
||
|
||
pull/merge/cherry-pick 發生衝突時:
|
||
|
||
1. 用 `git status --porcelain` 與衝突標記定位衝突檔。
|
||
2. 讀取衝突檔脈絡,依專案現有行為與遠端變更做**最小合理整合**。
|
||
3. 可安全解決的衝突:編輯移除衝突標記,`git add -- <檔案...>` 標記已解決,完成 merge/rebase/cherry-pick 的必要步驟。
|
||
4. 無法安全判斷的衝突:**停止處理**,列出檔案、原因與需要使用者決策的點;不要硬選任一邊。
|
||
|
||
## 建立分支不覆蓋
|
||
|
||
- 新分支名稱需可讀且避免覆蓋既有分支;本地或遠端已存在同名分支時,換一個時間戳或短 hash,不可覆蓋。
|
||
- 建立新分支屬不可忽略的狀態變更,需明確告知使用者原因與新分支名稱。
|