# 一個 repo 只有一個資料夾:分身住 `.worktrees/`,收工就被收(inkstone/ISEP#147) > leo 2026-09-07(兩則,一字不改): > 「我看到的是一個 repo,你會產生大量的同一個頭不同尾巴的 repo,全部拆開就更亂了, > 為什麼要產出新的 repo?這個 repo 的目的就是收納所有相關的內容,這樣散開造成凌亂, > ISEP, Inkstoneco, Course Gen 這些都產出好多個資料夾,這要整理回去」 > 「另外要在 ISEP 裡寫明,禁止這樣產出一大堆資料夾」 ## 規約(三句) 1. 🔴 **禁止在專案目錄旁邊產出分身資料夾。** `tech_projects/` 底下一個 repo 只能有一個資料夾; `ISEP-wt-117`、`InkStoneCo-wt-112`、`course_gen-ticket-3-notes` 這種同頭不同尾的東西不准再長出來。 2. **一條線要隔離工作目錄,分身住 repo 裡面**:`/.worktrees/<票的 repo 名>-<票號>`。 Finder 看不到(點開頭)、`git status` 看不到(寫進 `.git/info/exclude`)、`git worktree list` 找得到。 3. **分身是借的,收工要還**:分支推上遠端且工作樹乾淨 ⇒ 收掉;沒推 ⇒ 點名分支與路徑,等人決定。 **絕不 force、絕不刪沒推的 commit。** ## 為什麼會長成那樣(根因,不是誰疏忽) `hooks/line-needs-own-worktree.sh`(inkstone/ISEP#109,08-29 立)擋下線在共用目錄切分支,教它 「開一份在 repo 旁邊、不要在 /tmp、收工時 `worktree remove`」。 那時比較的只有「旁邊 vs /tmp」——/tmp 會被系統清掉、登記簿說謊;旁邊的一份都沒掉。 **一份都沒掉,也一份都沒收**:`remove` 那一步只寫在閘訊息裡,沒有任何機制驗。 每個工人留一份,`tech_projects/` 就長成那排。**規則在文字裡,不在機器上** (同日 ISEP#109 comment 6629 是同一種病:出路寫在訊息裡,機器讀不到)。 ## 機器上的兩端 | 端 | 在哪 | 做什麼 | |---|---|---| | 開 | `hooks/line-needs-own-worktree.sh`(PreToolUse Bash) | 擋下共用目錄裡的 checkout,印出 `scripts/worktree open …`(絕對路徑,貼了就能跑) | | 收 | **同一支閘**多掛 PostToolUse `Agent\|Task` | 從派工單 `【工單】owner/repo#N` 認出分身名字,跑 `scripts/worktree close`:推了收、沒推點名(exit 2) | | 工具 | `scripts/worktree` | `open`/`close`/`list`/`sweep` 四個動詞;「推了沒」只有這一份判準(三態:有/沒有/問不到,問不到不當成沒推) | 為什麼收的那一半不另開一支閘:教你開的和替你收的是同一件事的兩半,拆成兩支就又是「規則在兩個地方」 (`countdown-guard.sh` 同一種形狀:注入與查核是一支閘掛兩個事件)。 為什麼掛 PostToolUse 不掛 SubagentStop:票號在派工單(Agent 的 `tool_input.prompt`)裡,SubagentStop 拿不到 (`baton-handback-guard.sh` 檔頭那段實撞)。 ## 工人怎麼用 ``` python3 /scripts/worktree open inkstone/ISEP#147 --repo -b feat/147-xxx # 開 cd /.worktrees/ISEP-147 # 在裡面做事 python3 /scripts/worktree close inkstone/ISEP#147 --repo # 收(推了才收得掉) ``` 忘了 `close` 也沒關係——線收工那一刻閘會替你跑;但**沒推的它不會替你收**,只會點名。 不要用 `git worktree add /../-wt-…` 這條老路;閘訊息已經不印它了。 ## leo 在 Mac 上整理現場(一次) ``` python3 ~/.claude/plugins/cache/inkstone/isep/<版本>/scripts/worktree sweep ~/tech_projects # 只列,不動 python3 ~/.claude/plugins/cache/inkstone/isep/<版本>/scripts/worktree sweep ~/tech_projects --apply --skip course_gen ``` - 預設**只列不動**;`--apply` 才收,而且只收「推了且乾淨」的。 - 沒推的、有未 commit 的、問不到遠端的、沒有任何 repo 登記它的:**全部列出來、一個都不動**,等他決定。 - `--skip ` 是操作者點名不碰的 repo(09-07:`course_gen` 地端正在處理,列可以、不收不動)。 它是操作者的明示指令,不是判準——判準永遠是「這個目錄是不是某個 repo 的 worktree、分支推了沒、乾不乾淨」。 ## 測試 - `hooks/tests/line-needs-own-worktree.test.sh` G 群(開在裡面、旁邊不多任何東西、閘印的那行原樣跑得動) 與 H 群(PostToolUse:推了收掉、沒推點名、沒工單/沒分身安靜)。 - `scripts/test-worktree.sh`:七個分身的 fixture(照 leo 09-07 看到的那排)跑 `sweep`—— dry-run 不動任何東西;`--apply` 只收已推的、`--skip` 的一根寒毛不動、沒推的印分支與路徑。