Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
8.1 KiB
分支規則 — SDLC 各階段動工前的分支確認
分析要讀對分支的程式碼,實作要寫進對的分支。兩件事都不能從「目前 checkout 的分支」推定使用者的意圖。
總則:一律以遠端為準,不吃本地分支
SDLC 各階段引用的參考分支與來源分支,一律指遠端的 origin/{分支}。本地分支不可作為基準。
理由:本地分支可能落後遠端、可能有沒推上去的 commit、也可能是別的工作留下的狀態。以本地為基準,分析會對著過時的程式碼做,實作會從錯誤的起點長出來,而且錯了不會有任何徵兆。
| 項目 | 規則 |
|---|---|
| 動作之前 | 先 git fetch --prune origin。沒 fetch 就用 origin/{分支} 等於用快取,遠端追蹤參照可能已經過時,連分支被刪掉都看不出來 |
| 列分支 | git branch -r,不看 git branch |
| 基準與比對 | 一律寫 origin/{分支},例如 git rev-list --count origin/master..origin/develop |
| 建立 worktree | 從 origin/{來源分支} 建,不從本地同名分支建 |
| 判定預設分支 | refs/remotes/origin/HEAD(見〔判定遠端預設分支〕) |
本地與遠端不一致時一律停下回報,不自行 pull、不自行 reset、不自行切換。要不要同步是使用者的決定。
origin 以外的遠端名稱(例如 upstream):先問使用者以哪個遠端為準,不臆測。
先確認,再動工
| 階段 | 要確認的分支 | 確認時機 |
|---|---|---|
analyze |
來源分支——哪條分支的程式碼算現況 | 讀任何程式碼之前 |
implement |
來源分支——worktree 的基準,也是每個工作包的 PR 目標 | 寫任何檔案之前 |
確認方式:
- 先
git fetch --prune origin,再把事實攤開:目前分支、工作區是否乾淨、遠端有哪些分支(git branch -r,不看本地)、下節判定出的遠端預設分支。 - 依
jsc-ask:ask的決策樹詢問,每個選項都要標明影響範圍。分析錯分支會產出對不上程式碼的工作包;來源分支錯了則 worktree 從錯的起點長出來,PR 也會開到錯的地方。 - 把確認結果寫進產出(分析頁的來源分支欄),後續步驟一律沿用同一個答案,不再自行改判。
- 使用者沒回答就不預設
develop/master;預設值只在使用者明確同意後才成立。
判定遠端預設分支
- 先用
git symbolic-ref --quiet refs/remotes/origin/HEAD,結果形如refs/remotes/origin/<預設分支>。 - 取不到時退而用
git remote show origin,找輸出中的HEAD branch:那行。 - 兩者都取不到 → 回報並停止,不臆測
master/main。
需要基準或後備分支時(例如 PR 目標):origin/develop 存在就用 develop;否則 origin/master 存在就用 master;兩者皆無則回報並停止。
只讀階段不動工作區
analyze 是 logic-only 階段:
- 工作目錄的 HEAD 必須與
origin/{來源分支}指向同一個 commit。落後、超前或分歧都代表讀到的不是遠端現況——停下來回報差距(git rev-list --left-right --count origin/{來源分支}...HEAD),請使用者自己處理。 - 需要換分支才能讀到正確現況時,停下來請使用者自己切換。
- 不代為
switch、不stash、不動工作區、不建分支。
實作階段的分支選擇
實作在 worktree 內進行,工作分支從 origin/{來源分支} 長出來,做完再 PR 回同一條來源分支。
- 一個工作包一個 PR,目標一律是
origin/{來源分支}。不把兩個完成的工作包併成一個 PR,也不把完成的工作包留到下一包一起送——拆工作包的意義就是各自能獨立審查。 - 呼叫
jsc-git:pr時必須明確帶入來源分支當 base。該 skill 在沒收到 base 時會自行退回develop,那會讓單一工作包越過它所屬的功能分支直接進 develop。 - 來源分支整條後續要進
develop時,那是另一個獨立的 PR,不在本階段範圍。 - 新分支名稱要可讀且不覆蓋既有分支;本地或遠端已存在同名分支時,換一個時間戳或短 hash。
- 切換或建立分支屬不可忽略的狀態變更,要在輸出中講清楚原因與結果分支名稱。
實作一律在 worktree 內進行
implement 動任何程式碼之前,先 git fetch --prune origin,再從分析頁記錄的來源分支的遠端版本(origin/{來源分支})建立 git worktree。所有修改都在 worktree 內,主工作目錄的分支與工作區完全不動。
路徑
{工作目錄}/.worktree/{分析頁 HASH}/{repo}
{分析頁 HASH}:ANALYZE_{HASH}的 HASH 部分,不含ANALYZE_前綴。{repo}:存取庫名稱,不含 owner(HP/WebService.Buy→WebService.Buy)。不同 owner 的同名存取庫同時出現時,才改用{owner}-{repo}避免蓋掉,並在輸出中說明。- 一份分析涉及多個存取庫時,每個存取庫各一個 worktree,並列在同一個 HASH 目錄下。
建立前先問分支怎麼處理
依 jsc-ask:ask 的決策樹詢問,每個選項標明影響範圍。固定兩個選項:
| 選項 | 指令 | 影響 |
|---|---|---|
| 以來源分支為基準開新工作分支 | git worktree add -b {工作分支} {路徑} "origin/{來源分支}" |
commit 落在新分支,來源分支不動 |
| 直接簽出來源分支 | git worktree add --track -b {來源分支} {路徑} "origin/{來源分支}" |
建立追蹤遠端的本地分支再簽出;本地已存在同名分支時指令會失敗,此時先確認它與遠端一致才可改用 git worktree add {路徑} {來源分支},不一致就停下回報 |
不得自行預設,也不得跳過詢問。
建立時的鐵則
- 分支名與路徑一律加引號:來源分支可能含中文、空白或多層斜線(例如
feat/一址通/查地址/完整版/P2),不加引號會被切斷。 - 找不到該存取庫的本地 clone → 停下來問使用者路徑,不自行 clone、不臆測位置。
- 目標路徑已存在 → 不覆蓋。先確認它是不是同一份工作的 worktree(
git worktree list),是就沿用,不是就回報並停止。 - 把
.worktree/加進該存取庫的.git/info/exclude(不動使用者的.gitignore,那是專案共用檔)。 - 建立後在輸出中明確列出:worktree 路徑、簽出的分支、來源分支,以及
origin/{來源分支}當下的 commit sha——那是這次實作的起點,要能事後追。
移除時機
PR 合併之後才移除:git worktree remove {路徑},接著 git worktree prune。
不是 PR 建立後就移除——審查留言可能要求修改,而修改要回到同一個 worktree、推到同一條工作分支(PR 會自己更新,不開第二個 PR)。先移除就得為了改一行重建整個 worktree。
- PR 尚未合併 → 保留。PR 建立失敗 → 保留,讓使用者接手處理。
- worktree 內還有未提交變更時不移除,回報並停止——那些變更沒有進 PR,移除等於丟掉。
- 同一份分析的多個 worktree 全部移除後,若
.worktree/{HASH}/已空就一併刪掉那層目錄。
PR 未合併就不開下一個工作包
一個工作包的 PR 還沒合併,就不得開始下一包。每次要領工作包之前先確認:
gitea.sh pr-status {owner}/{repo} {index}看{state} {merged} {mergeable}。- 未合併 → 同時用
gitea.sh pr-comments {owner}/{repo} {index}讀留言(issue 留言、審查評語、行內留言,含沒有文字的APPROVED/REQUEST_CHANGES),原文轉述給使用者。 - 依
jsc-ask:ask詢問:依留言修正(回原 worktree 改、推同一條工作分支)或先等待。不自行決定,也不為同一包開第二個 PR。 - 已關閉但未合併 → 回報並詢問,不得當成完成。
不破壞既有工作
- 工作區有未提交變更時,先提醒使用者 commit 或備份,絕不強制丟棄。
- 未提交變更導致切換分支或 pull 失敗 → 停止並回報,請使用者處理。
- 絕不
reset --hard/checkout -f/clean。