
昨天 Day 06,我把遊戲專案放進 Git,並建立了第一個 Git repository。
接著一連建立了 8 個 commit,最後也推到 GitHub。
今天整理 Git 紀錄時,我突然發現一件事:
每一個 commit,都帶著我的私人信箱。
如果這個 repository 之後要公開,這些資訊也會跟著 commit 一起被看到。
我第一個想到的是:
「那我現在把 Git 的 email 改掉,不就好了?」
於是我改了:
git config user.email "我的 noreply email"
接著檢查之前的 commit。
結果發現:完全沒變。
原本那 8 個 commit 裡的 email,還是原本的私人信箱。
所以修改 Git 的設定,只會影響之後產生的 commit。
那如果已經產生的 commit 裡有不想公開的資訊,要怎麼修改呢?
Git 的 commit 裡會記錄作者名稱和 email。
例如:
Author: Jason Hung <jason@example.com>
當 commit 被推到 GitHub 後,GitHub 可以根據這個 email,判斷它是否和某個 GitHub 帳號裡已驗證的 email 相符。
所以,如果我使用自己的私人信箱,這些 commit 就可能和我的 GitHub 帳號產生關聯。
反過來說,如果使用 GitHub 提供的 noreply email,只要設定正確,就可以讓 commit 不直接使用自己的私人信箱。
這也是我這次想修改 email 的原因。
後來我去看 GitHub 的設定,發現它本身就有和 email 隱私相關的選項。
其中一個是:
Keep my email addresses private
開啟後,GitHub 會提供一組 noreply email,可以拿來當 Git 的 user.email。
另外還有一個:
Block command line pushes that expose my personal email address
如果從命令列 push 時,commit 使用了個人 email,GitHub 可以阻止這次 push。

這兩個設定解決的是:
之後不要再把私人信箱推上去。
但我現在遇到的是另一個問題:
前面 8 個 commit 已經存在了。
這件事情其實很直覺。
當我執行:
git config user.email "我的 noreply email"
我只是告訴 Git:
「以後建立 commit 的時候,請使用這個 email。」
它不會回頭修改以前已經建立好的 commit。
所以:
第 1 個 commit → 私人信箱
第 2 個 commit → 私人信箱
...
第 8 個 commit → 私人信箱
現在修改 user.email
第 9 個 commit → noreply email
前面的 8 個 commit 並不會自己改掉。
這看起來也很合理,歷史紀錄本來就是要保留當時發生的事情。
Git 的設定和 Git 的歷史紀錄,是兩件不同的事情。
如果真的要修改以前的 commit,就必須修改 Git 的歷史。
這次我的專案只有我自己使用,而且 GitHub 上也還沒有其他人 clone 這個 repository。
所以我決定直接修改歷史。
不過在動手之前,我先做了一個備份:
git branch backup-before-email-rewrite
這樣如果後面改壞了,至少還有一個分支可以回去。
接著,這次我使用 Git 的 filter-branch,把歷史紀錄裡的舊 email 替換掉。
完整指令放在文末附錄,概念上就是:
舊 email
↓
全部替換成
↓
GitHub noreply email
這個動作不是修改目前的 Git 設定,而是重新產生一份修改過的 Git 歷史。
所以這類操作要特別小心。
如果 repository 已經有其他人一起使用,修改歷史就可能影響其他人的本地 Git 紀錄。
因為我這次只是想修改 commit 裡的 email,並不希望連遊戲程式碼一起被改掉。所以我先確認檔案內容,也檢查原本的 email 是否還存在:
git grep "old-email@example.com"
結果沒有找到。
接著檢查目前 commit 裡的作者 email:
git log --format='%h %an <%ae>'
原本:
abc1234 Jason Hung <old-email@example.com>
def5678 Jason Hung <old-email@example.com>
...
修改後:
c857aab Jason Hung <我的 noreply email>
xxxxxxxx Jason Hung <我的 noreply email>
...
8 個 commit 都換成了新的 email。
程式碼本身沒有跟著改變。
這時候又遇到另一個問題。GitHub 上已經有原本那 8 個 commit。
我在本機修改歷史之後,本機的 Git 歷史和 GitHub 上的歷史已經不一樣了。
所以一般的 git push 會被拒絕。因為 Git 會認為:
「你遠端已經有一條歷史了,現在本機突然換了一條,我不能直接幫你蓋掉。」
這時候就需要 force push。這次我使用的是:
git push --force-with-lease origin main
--force 和 --force-with-lease 都可以強制更新遠端歷史。
但 --force-with-lease 會多做一層檢查:
如果遠端的狀態和我預期的不一樣,就不要直接覆蓋。
所以這次在確認 repository 只有我自己使用後,我選擇 --force-with-lease。
這次我會修改,是因為:
如果是一個多人共同開發的專案,就不能這麼隨便處理。
因為修改歷史之後,其他人的本地 repository 可能還保留著舊的歷史。
這時候如果直接 force push,就可能造成大家的 Git 歷史對不起來。
所以我這次的做法,比較適合自己的個人專案。
最後,我把 Git 的 email 設定成 GitHub 提供的 noreply email。
如果只想設定目前這個專案:
git config user.email "我的 noreply email"
如果希望之後所有 Git 專案預設都使用這個 email,可以加上 --global:
git config --global user.email "我的 noreply email"
這次我也把 global 和目前專案的設定確認了一次,避免之後又不小心使用私人信箱。
user.name 和 user.email 會寫進 commit。
在 Vibe Coding 把作品公開之前,先確認 commit 沒有洩漏私人信箱,避免信箱被公開蒐集,也是對自己的一點保護。
今天從一個私人信箱開始,最後一路碰到了 Git history 和 force push。把 Git 的歷史改完,總算把 email 的問題處理好了。
但下一個問題又來了:
如果我每次都要自己盯著 Claude Code 的指令,那它到底能不能幫我自動檢查?
Day 08,開始來看我怎麼讓 AI 幫自己做檢查。
這次我使用 git filter-branch:
git filter-branch --env-filter '
OLD_EMAIL="old-email@example.com"
CORRECT_NAME="Jason Hung"
CORRECT_EMAIL="我的 noreply email"
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_COMMITTER_NAME="$CORRECT_NAME"
export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_AUTHOR_NAME="$CORRECT_NAME"
export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags
這次的重點是把舊的 email 找出來,換成新的 email。
filter-branch 可以修改 Git 歷史,但它會重新處理歷史紀錄,所以使用前最好先備份。
git grep "old-email@example.com"
以及:
git log --format='%h %an <%ae>'
git push --force-with-lease origin main