.maigo/ 跨機器同步
集中儲存 讓同一台機器上的所有 worktree 共用一份 .maigo/。這一頁說明怎麼讓另一台機器
也拿到其中一部分:集中 root 本身是一個 git work tree,remote 叫 origin,指向你自己的私有 repo。
同步是兩個手動動作,沒有 daemon、沒有自動解衝突,也不呼叫 gh。
預設拒絕
集中 root 底下的東西預設全都不同步。只有寫在 <root>/allowlist 的 owner/repo 才會被追蹤:
allowlist是一個明文檔,每行一個owner/repo(#開頭為註解)。maigo 沒有內建任何項目,一開始是空的。- 排除規則由 allowlist 產生,寫在
<root>/.git/info/exclude(不追蹤、不要手改;init、allow、status、pull、push都會重新產生,所以 clone 下來的第二台機器第一次跑status就有):沒在 allowlist 的<owner>/<repo>/、_local/、_migration-backup/, 以及每個 allowlisted repo 底下的_internal/(機器日誌、tidy 備份、board snapshot)都不會被追蹤;*.zip一律排除。 唯一從_internal/放行的是_internal/board/dropped.jsonl(只增不改的排除紀錄),.gitattributes讓它用merge=union合併,兩台機器各加一行不會衝突。 allowlist與.gitattributes兩個中繼檔本身會被追蹤,所以另一台機器 clone 下來就有同一份規則。allowlist也用merge=union:兩台機器各自allow不同的 repo,pull之後是兩邊的聯集,不會衝突。push在排除規則之外再檢查一次:git add -f可以繞過 ignore,所以 index 與尚未推送的 commit 裡 每個路徑都必須落在 allowlist 內(或是兩個中繼檔),否則拒絕、exit 1,什麼都不推。
identity 解成同一個 owner/repo 不代表可以同步。公司或私人內容不要加進 allowlist;
board 與 review 報告是你尚未發佈的意見,放上私有 repo 也要自己先決定。
指令
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/maigo_state_sync.py" init [--url URL]
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/maigo_state_sync.py" allow OWNER/REPO
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/maigo_state_sync.py" status [--fetch]
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/maigo_state_sync.py" pull
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/maigo_state_sync.py" push
集中 root 由 $MAIGO_STATE_HOME 決定(預設 ~/.local/share/maigo/state),同步指令用同一個位置。
init [--url URL]:把集中 root 變成 git repo(分支main),有給--url就加 remoteorigin, 建立allowlist(空的)、.gitattributes,並寫入排除規則。可重跑;已有不同的origin時拒絕。不 commit、不連網。allow OWNER/REPO:把一行加進allowlist並重新產生排除規則。_或.開頭的 owner(_local等)一律拒絕。status [--fetch]:印出branch、ahead、behind、uncommitted,以及 allowlist 內但還沒被追蹤的目錄 (untracked-allowlist: owner/repo)。加--fetch才會先連origin,否則用上次 fetch 的結果;fetch 失敗或超過 10 秒只警告。本機還沒有任何 commit、remote 卻已有歷史時,behind是 remote 的 commit 數,並多印一行note:提示改用 clone。 集中 root 不是 git repo 時印一行說明、exit 0。pull:先把本機變更 commit 成一個快照,再 fetch 並 mergeorigin/<目前分支>。push:檢查通過後 commit 並推到origin。merge 還沒收尾(有衝突標記或MERGE_HEAD)時拒絕,exit 1。pull發現origin沒有目前分支時,會警告 remote 上有哪些其他分支,exit 0。
push 的警告(印到 stderr,只列出,不擋):含 /Users/ 或 /home/ 絕對路徑的檔案、單檔 ≥ 1 MB 的檔案。
既有筆記裡的絕對路徑不會被改寫;它們在另一台機器上只是失效的文字。
第一次設定
gh repo create 與第一次 git push 由你親手執行,maigo 不會代跑。
gh repo create maigo-state --private
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/maigo_state_sync.py" init --url git@github.com:<you>/maigo-state.git
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/maigo_state_sync.py" allow <owner>/<repo>
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/maigo_state_sync.py" push
push 會先 commit 再推;先看一眼 git -C <root> status 與 git -C <root> ls-files 是否只有預期的檔案。
日常
- 開工前
pull,收工後push。/maigo:board開頭會跑status --fetch,落後origin時只提示一句,不會自動 pull。 pull會先把本機未 commit 的變更 commit 成快照,這樣兩邊同時改同一個檔才會走 git 的三方合併, 而不是被擋在「本機有未 commit 的變更」。快照 commit 只在本機,push才會送出。
第二台機器
第二台機器要 git clone,不要在已有內容的集中 root 上 init(兩邊歷史不相干,pull 會停下)。
若那台機器的集中 root 已經有內容,先搬開再 clone,再把不同步的目錄搬回來:
mv ~/.local/share/maigo/state ~/.local/share/maigo/state.old
git clone git@github.com:<you>/maigo-state.git ~/.local/share/maigo/state
不同步的目錄(例如 _local/、沒進 allowlist 的 repo)從舊目錄搬回來,不要覆蓋 clone 下來的檔案:
cp -Rn ~/.local/share/maigo/state.old/_local ~/.local/share/maigo/state/
cp -Rn ~/.local/share/maigo/state.old/<owner> ~/.local/share/maigo/state/
_migration-backup/ 也是這樣搬。確認都搬回來之後再刪 state.old。
clone 下來就帶著 allowlist 與 .gitattributes;排除規則在第一次 status/pull/push 時產生。
clone 後先跑 status(它會產出 .git/info/exclude);在那之前不要在 root 直接 git add -A,否則會 stage 到 allowlist 外的目錄
(push 會擋,但不必走到那步)。worktree 的 .maigo symlink 指向集中 root 的路徑,
所以位置要和原本一致。
衝突
兩台機器都改了同一個檔(通常是 board.md),pull 會停下,exit 1,並印出:
- 衝突檔清單
git status --short
它不會 --abort,也不會選邊;工作區保留 git 的衝突標記。用 nvim 打開衝突檔,解完之後:
git -C <root> add <檔案>
git -C <root> commit
之後再 push。想放棄這次合併就 git -C <root> merge --abort。merge 還沒收尾時再跑 pull 會直接拒絕。
pull 會先把本機變更 commit 成快照再合併,所以 merge --abort 只會退回合併前,快照 commit 仍在本機。
要連本機那次修改一起放棄,得自己 reset 掉那個快照 commit,否則下次 pull 會再衝突一次:
git -C <root> merge --abort
git -C <root> reset --hard HEAD~1
reset --hard 會丟掉那次本機修改,執行前先用 git -C <root> log -1 確認 HEAD 是 maigo-state: local snapshot before pull 開頭的那個 commit。
另請參閱
.maigo/集中儲存:位置、identity、遷移、信任邊界