
這 30 天,我一邊開發遊戲,一邊也在寫開發日誌、學習筆記和文章草稿。
一開始,我直接把這些東西放在遊戲專案裡。
這樣最方便,寫程式和寫筆記都在同一個地方。
但遊戲程式碼準備公開到 GitHub 後,問題就來了:
程式碼想公開,筆記卻不想公開。
未發表的文章、還沒整理好的筆記、寫壞的段落,如果跟著遊戲 repo 一起 push 到 GitHub,之後任何人都可能看到。
所以最後同一個專案裡我把它拆成兩個 repo:
ObsidianTrial
└── 遊戲程式碼 → 公開 repo
doc
└── 開發筆記、文章草稿 → 私有 repo
這樣做之後,我還是可以把筆記放在遊戲專案旁邊寫,只是 Git 的管理分成兩邊。
看起來很簡單,但中間其實碰到了幾個 Git 和 Godot 的問題。
當時的專案大概是這樣:
ObsidianTrial/
├── assets/
├── scenes/
├── scripts/
└── doc/
├── DEVLOG.md
└── notes/
這樣做很方便。
但我很快又遇到一個 Godot 的問題。
我的文章一定會有很多截圖。
如果把 .png 放進 doc/,Godot 會把它們當成遊戲素材處理,並在 .godot/imported/ 裡產生對應的匯入資料。
這些圖片是拿來寫文章的,不是遊戲素材。
所以我需要告訴 Godot:
doc/是我的筆記,不是遊戲素材。
AI 建議我在 doc/ 裡放一個空白的 .gdignore:
touch doc/.gdignore
這是一個完全空白的檔案。
Godot 看到它之後,就會跳過這個目錄。
用 godot -e 開啟編輯器確認後,可以看到前後差異:

左邊還看得到 doc/ 和 doc_ithome_iron/,加上 .gdignore 後,兩個資料夾都不再出現在 Godot 的 FileSystem 面板。
右圖是稍後補拍的,所以多了幾個當時新增的場景和腳本,跟 .gdignore 無關。
這時候我才知道,原來筆記雖然放在遊戲專案裡,還是可以讓 Godot 忽略它。
但接下來的問題是:
如果遊戲 repo 要公開,doc/ 還是會跟著 Git 一起公開。
.gdignore 解決的是 Godot 的問題,沒有解決 Git 的問題。
我當時想到三種方式:
| 做法 | 結果 |
|---|---|
| 繼續放主 repo | 最簡單,但筆記會跟著公開 |
| Git submodule | 可以分開,但設定比較複雜,而且主 repo 會留下私有 repo 的網址 |
| 獨立 repo | 程式碼和筆記完全分開,但要分別管理 |
我最後選了第三種。
因為我其實不需要主 repo 知道筆記的版本。
我只需要兩件事:
遊戲程式碼 → 公開
開發筆記 → 私有
所以讓它們變成兩個獨立 repo,反而比較符合我的需求。
這時候又有一個問題。
如果我直接進入 doc/:
git init
新的 repo 當然可以馬上開始使用。
但之前 doc/ 裡已經有 9 個 commit。
直接 git init 的話,這些歷史就不會跟過去的 Git 紀錄一起搬過去。
所以我問 AI:
「有辦法把
doc/過去的 commit 歷史一起搬走嗎?」
這個問題讓我找到 git subtree split。
先執行:
git rm -r --cached doc
這裡最重要的是:
--cached
它只會把 doc/ 從 Git 的索引移除,本機檔案還會保留。
如果沒有 --cached:
git rm -r doc
Git 就會真的把檔案刪掉。
所以這裡我特別停下來問了一句:
「
--cached加跟不加差在哪?」
因為那個目錄裡放的是我這幾天累積的筆記。
doc/接著在 .gitignore 加上:
# 開發日誌、學習筆記、文章草稿
# 這些已獨立成私有 repo
doc/
這一步很重要。
因為接下來 doc/ 裡會有自己的 .git。
如果主 repo 還繼續追蹤它,就會變成「Git 裡面又放了一個 Git」。
後面我真的就踩到了這個坑。
如果只是想把檔案搬到另一個 repo,這時候直接 git init 就可以。
但我想保留原本 9 個 commit。
所以執行:
git subtree split --prefix=doc -b doc-history
這會把 doc/ 這個子目錄的歷史抽出來,建立成一個新的 doc-history 分支。
原本:
doc/DEVLOG.md
抽出來之後會變成:
DEVLOG.md
也就是 doc/ 本身會被拿掉,檔案直接變成新 repo 的根目錄。
接著把這段歷史接到新的 repo:
git -C doc init -b main
git -C doc fetch .. doc-history
git -C doc reset --mixed FETCH_HEAD
最後刪掉暫時建立的分支:
git branch -D doc-history
這樣原本 doc/ 裡的 9 個 commit,就完整搬到新的 repo。
拆完之後,我又遇到三個實際問題。
如果沒有把 doc/ 放進 .gitignore,主 repo 會看到裡面還有另一個 Git repo。
執行 git add 時,Git 會出現:
warning: adding embedded git repository: inner
hint: You've added another git repository inside your current repository.
hint: Clones of the outer repository will not contain the contents of
the embedded repository and will not know how to obtain it.
後面 Git 甚至還會告訴你,如果真的要使用 submodule,應該怎麼做;如果是不小心加進去的,也會告訴你怎麼移除。
Git 其實已經把問題講得很清楚。
但我差點忽略它。
因為這是:
warning
不是:
error
所以指令還是會成功。
接著看 git status:
A file.txt
A inner
整個巢狀 repo 只剩下一行:
inner
裡面到底有哪些檔案,完全看不出來。
原因是外層 Git 記錄的不是裡面的檔案內容,而是一個 commit。
如果別人 clone 外層 repo,也不會自動拿到裡面 repo 的完整內容。
所以 .gitignore 在這裡就很重要:
主 repo
↓
看到 doc/
↓
.gitignore
↓
「這個目錄不要由我追蹤」
拆完之後,我又發現:
VS Code 的「原始檔控制」面板只看到主 repo。
我修改了筆記,卻沒有看到任何 Git 變更。
原因是 doc/ 已經被 .gitignore 排除,VS Code 預設掃描 repo 時,也把它跳過了。
所以我在 .vscode/settings.json 加上:
{
"git.scanRepositories": ["doc"]
}
重新載入視窗之後,兩個 repo 就都出現了:

這裡可以看到:
ObsidianTrial main
doc main*
* 代表 doc 有尚未 commit 的變更。
兩個 repo 的狀態完全獨立。
所以之後 commit 前,我還多了一個要注意的地方:
先確認現在選的是哪一個 repo。
最後一個沒有什麼技術難度,卻最容易忘記。
程式碼:
git push
筆記:
git -C doc push
git -C <目錄> 可以理解成:
在指定的目錄裡執行 Git 指令。
所以不用先 cd doc。
這個操作之後會變成雙 repo 日常工作的一部分。
我也把這件事情寫進 CLAUDE.md,讓新的 Claude Code 對話一開始就知道:
主 repo → 遊戲程式碼
doc repo → 開發筆記
兩個 repo 要分開 commit / push
不然 AI 如果只在主 repo 執行:
git status
看到主 repo 沒有變更,就可能直接回報:
工作區是乾淨的。
但其實我的筆記 repo 可能早就有修改了。
現在的結構可以簡單理解成:
ObsidianTrial
└── 公開的遊戲程式碼
doc
└── 私有的開發筆記、文章草稿
但在我的電腦裡,doc/ 依然放在遊戲專案裡:
ObsidianTrial/
├── assets/
├── scenes/
├── scripts/
├── README.md
├── CLAUDE.md
└── doc/
├── DEVLOG.md
└── notes/
只是 Git 的管理已經分開。
所以我現在可以:
寫遊戲
↓
公開到 GitHub
寫文章
↓
留在私有 repo
兩邊都可以繼續在同一個 VS Code 裡工作。
Day 01 說過這個系列的心法:
攔截 → 追問 → 親手重做
這次最直接的攔截點,就是:
git rm -r --cached doc
提問:「--cached 加跟不加差在哪?」
提問:「有辦法保住 doc/ 過去的 commit 歷史嗎?」
第一個問題,讓我知道檔案不會被刪掉。
第二個問題,讓我找到 git subtree split,把原本 9 個 commit 一起搬走。
拆完之後,我自己確認:
ls doc/
確認檔案還在。
git -C doc log --oneline
確認新的 repo 有原本的歷史。
再回到主 repo:
git status
確認主 repo 已經不再追蹤 doc/。
三個都確認過,我才繼續 push。
所以 Day 11 最後留下來的結構,其實很簡單:
遊戲 repo
→ 公開
筆記 repo
→ 私有
只是為了做到這件事,我中間才碰到了 .gdignore、git rm --cached、git subtree split,以及兩個 repo 在 Git 和 VS Code 裡的管理問題。
程式碼公開,筆記私有。
這就是這次拆 repo 最後得到的結果。
明天 Day 12 開始進入遊戲的核心機制。
我很好奇一件事:
AI 為什麼把玩家的血量、牌組這些資料,都放進一個叫 Global.gd 的檔案?
這次就要開始拆 Godot 裡的資料到底怎麼流動。