背景
範例 001 跟 009 都只跑「一次性 build」:全量 graphify extract . 之後就放著。但真實開發是持續的:
- 你改了一個 function,圖譜過時了
- 同事 merge 一個 PR,你本地的
graph.json跟遠端衝突 - 團隊共用一份 commit 進 repo 的
graphify-out/,但每次 pull 都要重建
graphify 的增量重建三招解決這些日常摩擦:update(手動增量)、watch(自動監聽)、hook install + git merge driver(融入 git 流程)。這個範例帶你把三招接起來,讓圖譜在持續開發中一直保持新鮮,不必每次都全量重建。
⚠️ 與範例 003 差異:003 談的是「團隊共享 + PR review」,只順帶提到
hook install。本範例聚焦在單人/團隊日常的增量維護流程,涵蓋 watch 與 merge driver 的完整設定。
適用情境
- 中大型 codebase,全量 build 要 30 秒以上,不想每次改一行就重跑
- 團隊把
graphify-out/commit 進 repo,需要處理 merge 衝突 - 想讓圖譜在背景自動同步,不佔用開發節奏
- 升級到 v0.9.41,想用新的「縮小圖譜保護」與 POSIX 路徑
增量重建的三個層次
| 工具 | 觸發時機 | 適合場景 |
|---|---|---|
graphify update |
手動按需 | 改了幾個檔,想同步圖譜 |
graphify watch |
檔案變動自動觸發 | 開發中背景跑,持續同步 |
graphify hook install |
git commit/merge 觸發 | 團隊流程,確保 commit 進 repo 的圖譜永遠最新 |
三者不互斥,可以疊加:個人用 watch,團隊用 hook,臨時用 update。
完整流程
步驟 1:建立 baseline 圖譜
先跑一次全量 build 作為 baseline:
cd ~/my-project
uv tool install graphifyy
graphify install --project
graphify extract . --code-only
確認 graphify-out/graph.json 產生。
步驟 2:改幾個檔,手動增量更新
模擬日常開發:加一個新 function、改一個既有 function。
# 加新檔
cat > notifier.py << 'EOF'
def notify(user, message):
print(f"[notify] {user}: {message}")
EOF
# 改既有檔
echo " # v2: added logging" >> auth.py
現在跑增量更新,只重抽變動的檔:
graphify update
update 會:
- 比對檔案 mtime/hash,找出變動的檔
- 只對變動檔重跑 AST 解析
- 把新節點/邊 merge 進既有
graph.json,刪掉消失的節點
輸出會告訴你「重新萃取 N 個檔,新增 M 個節點」。比全量 extract 快很多。
💡 v0.9.41 重點:
graphify update不會以「extractor 失敗造成的縮小圖譜」覆寫既有資料。如果你看到 update 被拒絕,先檢查 extractor 是否報錯(例如某個檔 parse 失敗),修正後再重跑。
步驟 3:背景 watch,檔案變動自動重建
不想每次手動 update?開一個終端跑 watch:
graphify watch
watch 會監聽專案目錄,檔案一變動就觸發增量重建。開發時讓它背景跑,你只管寫 code,圖譜自動同步。
[watch] detected change: notifier.py
[watch] incremental update... done (1 file, 0.4s)
[watch] detected change: auth.py
[watch] incremental update... done (1 file, 0.3s)
watch 適合個人本地開發。要停就 Ctrl+C。
步驟 4:裝 git hook,把重建融入團隊流程
團隊若把 graphify-out/ commit 進 repo(範例 003 的做法),每個人在 commit/merge 前都要確保圖譜是新的。手動容易忘,裝 hook 自動化:
graphify hook install
graphify hook install 一次寫入三樣東西:
- post-commit hook — 每次
git commit後自動執行 AST-only 重建(零 API 成本) - post-checkout hook — 切 branch 時重建圖譜,確保助理看到的是當前 branch 的 code
graph.json的 git merge driver(merge=graphify) — 兩人平行 commitgraphify-out/時自動 union-merged,永不出現 conflict marker
驗證 hook 有裝上:
graphify hook status
輸出類似:
Git hooks (graphify v0.9.41):
post-commit installed → runs AST-only rebuild after commit
post-checkout installed → runs AST-only rebuild after branch switch
merge driver installed → graphify-out/graph.json union-merged via merge=graphify
步驟 5:git pull 不卡 graph.json 衝突
graph.json 是機器產生的 JSON,兩人同時 commit 各自重建的版本,merge 時本來必定衝突。手動解 JSON 衝突是惡夢。
但步驟 4 的 graphify hook install 已經順手把 merge driver 寫好了:graphify-out/graph.json 會套用 merge=graphify,當 git pull / git merge 遇到 graph.json 衝突時,git 不再寫 <<<<<<< 標記,而是交給 driver 把兩邊的圖譜智慧合併:
- 讀兩邊的節點 / 邊
- 取聯集(node id 相同就合併屬性)
- 寫回當前檔
換句話說:步驟 4 一條指令就把 hook 與 merge driver 都搞定,不需要另外手動編輯 .gitattributes 或 git config。
步驟 6:驗證整套流程
模擬一個完整循環:
# 1. 改檔
echo "def new_func(): pass" >> utils.py
# 2. commit(觸發 post-commit hook → AST-only 重建)
git add -A
git commit -m "feat: add new_func"
# 3. hook 輸出
# [graphify post-commit] rebuilding AST graph... 1 file changed, 1 node added
# 4. push
git push origin main
同事 pull 時,因為步驟 4 已裝好 merge driver,graph.json 自動 union-merged:
git pull origin main
# graphify-out/graph.json: merge=graphify driver applied, union-merged cleanly
圖譜永遠是新的,且不會卡在 merge 衝突。
真實輸出範例
$ graphify update
Scanning for changed files... 3 found
Re-extracting: notifier.py, auth.py, utils.py
Merging into existing graph...
+ 2 nodes added (notify, new_func)
+ 1 edge added (login --calls--> notify)
~ 0 nodes updated
- 0 nodes removed
Done in 1.2s
$ graphify watch
[watch] v0.9.41 watching . (recursive, ignore .git/, graphify-out/)
[watch] press Ctrl+C to stop
[watch] 14:23:01 changed: services/billing.py → rebuilt (1 file, 0.5s)
[watch] 14:23:45 changed: services/billing.py, services/auth.py → rebuilt (2 files, 0.7s)
對比傳統做法
| 情境 | 沒有增量重建 | graphify 增量重建 |
|---|---|---|
| 改一行 code 想同步 | 全量 extract .,30 秒起跳 |
update 只跑變動檔,< 1 秒 |
| 開發中圖譜同步 | 手動重跑,容易懶得做 | watch 背景跑,零摩擦 |
| 兩人 commit 圖譜衝突 | 手動解 JSON,易出錯 | merge=graphify driver 自動合併 |
| 忘了重建就 commit | commit 進 repo 的圖譜過時 | hook install 在每次 commit 後自動重建,下個 commit 一定帶新圖譜 |
失敗處理
| 情境 | 排查 |
|---|---|
update 報「graph shrunk, refusing to overwrite」 |
v0.9.41 的保護機制:本次萃取結果比既有圖譜小很多。先檢查 extractor 是否報錯(例如某檔 parse 失敗、.graphifyignore 範圍設錯),修正後重跑 |
watch 吃 CPU 過高 |
大型 repo 的檔案監聽成本高;可限定監聽子目錄(例如 graphify watch ./src 而非整個 repo),縮小監聽範圍 |
hook status 顯示未安裝 |
重跑 graphify hook install;若 .git/hooks/ 權限不對,chmod +x .git/hooks/post-commit |
| merge driver 沒生效 | 確認 graphify hook install 跑過(它會自動寫入 merge=graphify driver);若 hook status 顯示 driver 缺失,重跑一次 install 即可 |
| 升級 v0.9.41 後 cache 失效 | 此版本要求 semantic 節點含 rationale,舊 cache 會自動重新萃取,屬正常現象;先確認語意後端額度充足 |
內部連結
下一步
- PR 審查 + 團隊共享 graphify-out(團隊層級的共享與 CI)
- 大型 monorepo 重購(圖譜維持新鮮後,做重購分析)
關鍵學習點
update是手動增量、watch是自動監聽、hook install是融入 git 流程;三個不互斥,依場景疊加。- v0.9.41 的
update會拒絕以縮小圖譜覆寫,遇到拒絕先修 extractor,別強制覆蓋。 - 把
graphify-out/commit 進 repo 的團隊,一定要設merge=graphifydriver,否則 graph.json 衝突會反覆發生。 hook install是團隊紀律的自動化:把「commit 後順手更新圖譜」從口頭約定變成每次 commit / checkout 自動執行。