iT邦幫忙

2026 iThome 鐵人賽

DAY 7
0
Vibe Coding

從 Vibe Coding 到系統架構:Gemini x Claude Code 雙 AI 協同開發 Godot 2D Roguelike 卡牌遊戲實戰系列 第 7

Day 07:【版控實務】一個小設定,避免 commit 洩漏私人信箱;舊紀錄怎麼辦?

  • 分享至 

  • xImage
  •  

昨天 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 裡有不想公開的資訊,要怎麼修改呢?


1. GitHub 怎麼知道這個 commit 是我的?

Git 的 commit 裡會記錄作者名稱和 email。

例如:

Author: Jason Hung <jason@example.com>

當 commit 被推到 GitHub 後,GitHub 可以根據這個 email,判斷它是否和某個 GitHub 帳號裡已驗證的 email 相符。

所以,如果我使用自己的私人信箱,這些 commit 就可能和我的 GitHub 帳號產生關聯。

反過來說,如果使用 GitHub 提供的 noreply email,只要設定正確,就可以讓 commit 不直接使用自己的私人信箱。

這也是我這次想修改 email 的原因。


2. GitHub 其實有提供保護機制

後來我去看 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 已經存在了。


3. 為什麼改設定,舊 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 的歷史。


4. 那我要怎麼修改已經存在的 commit?

這次我的專案只有我自己使用,而且 GitHub 上也還沒有其他人 clone 這個 repository。
所以我決定直接修改歷史。
不過在動手之前,我先做了一個備份:

git branch backup-before-email-rewrite

這樣如果後面改壞了,至少還有一個分支可以回去。
接著,這次我使用 Git 的 filter-branch,把歷史紀錄裡的舊 email 替換掉。
完整指令放在文末附錄,概念上就是:

舊 email
    ↓
全部替換成
    ↓
GitHub noreply email

這個動作不是修改目前的 Git 設定,而是重新產生一份修改過的 Git 歷史
所以這類操作要特別小心。
如果 repository 已經有其他人一起使用,修改歷史就可能影響其他人的本地 Git 紀錄。


5. 改完之後,我先確認程式碼有沒有被改掉

因為我這次只是想修改 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。

程式碼本身沒有跟著改變。


6. 歷史改完,GitHub 上的歷史也要跟著更新

這時候又遇到另一個問題。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


7. 什麼情況可以修改 Git 歷史?

這次我會修改,是因為:

  • repository 目前只有我自己使用
  • 沒有人 clone 這個專案
  • GitHub 上也沒有其他人的 commit
  • 我只是要修正 commit 裡的 email

如果是一個多人共同開發的專案,就不能這麼隨便處理。
因為修改歷史之後,其他人的本地 repository 可能還保留著舊的歷史。
這時候如果直接 force push,就可能造成大家的 Git 歷史對不起來。
所以我這次的做法,比較適合自己的個人專案。


8. 順便把 Git 的 email 設定好

最後,我把 Git 的 email 設定成 GitHub 提供的 noreply email。

如果只想設定目前這個專案:

git config user.email "我的 noreply email"

如果希望之後所有 Git 專案預設都使用這個 email,可以加上 --global

git config --global user.email "我的 noreply email"

這次我也把 global 和目前專案的設定確認了一次,避免之後又不小心使用私人信箱。


9. 今天留下的幾個筆記

  1. Git 的 user.nameuser.email 會寫進 commit。
  2. 修改 Git 設定,不會修改已經建立的 commit。
  3. 要修改舊 commit,就必須修改 Git 歷史。
  4. 修改歷史後,推回 GitHub 可能需要 force push。
  5. 多人共同開發的 repository,不要隨便重寫歷史。

在 Vibe Coding 把作品公開之前,先確認 commit 沒有洩漏私人信箱,避免信箱被公開蒐集,也是對自己的一點保護。


Day 08 預告

今天從一個私人信箱開始,最後一路碰到了 Git history 和 force push。把 Git 的歷史改完,總算把 email 的問題處理好了。

但下一個問題又來了:

如果我每次都要自己盯著 Claude Code 的指令,那它到底能不能幫我自動檢查?

Day 08,開始來看我怎麼讓 AI 幫自己做檢查。


附錄:這次實際使用的指令

A. 修改歷史中的 email

這次我使用 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 歷史,但它會重新處理歷史紀錄,所以使用前最好先備份。

B. 確認舊 email 是否還存在

git grep "old-email@example.com"

以及:

git log --format='%h %an <%ae>'

C. 推送修改後的歷史

git push --force-with-lease origin main

上一篇
Day 06:【CLI 攔截】攔截 Claude Code 的 Git 指令,才發現裡面藏了不少知識
下一篇
Day 08:【CLI 驗證】讓 Claude Code 自己跑 Godot,不再問我「跑起來了嗎?」
系列文
從 Vibe Coding 到系統架構:Gemini x Claude Code 雙 AI 協同開發 Godot 2D Roguelike 卡牌遊戲實戰9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言