密碼或 token 不小心進了 Git,刪掉設定檔、加上 .gitignore,再提交一次,就能當作處理完嗎?不能。新提交可以停止往後追蹤,舊提交仍可能留下原內容;若那是真實可用的憑證,還要到對應服務撤銷或輪換。
先把兩個目標分開:讓已暴露的憑證失效,以及避免檔案再次進入版本管理。歷史清理是另一項需要協調的工作,不能用「目前頁面看不到檔案」證明所有副本都不存在。
先處理憑證的使用權,不等刪檔
若發現的是仍可登入或呼叫服務的真實密碼、token、金鑰,先依該服務的流程撤銷或輪換。GitHub 的敏感資料移除文件也把這件事放在第一步。單純刪 Git 檔案,不會通知提供者讓那份憑證失效。
確認哪個服務發出它、權限範圍與使用環境,再由有權限的人處理。正式網站可能也在使用同一份值;替換時要安排新值的接入與必要驗證,避免只撤掉舊值卻沒讓應用恢復。完成狀態要以提供者的管理結果與實際存取核對,不能靠 Git 提交訊息宣稱「已撤銷」。
記錄檔名、涉及的服務、發現時間、是否已推送及可能的副本,不在群聊、issue 或文章貼出完整真值。本文只用 DEMO_ONLY 假字串,不示範讀取真憑證,也沒有替任何服務執行撤銷。
用假字串看一次:忽略不會停止追蹤
本機示例 repository 已提交 config.local.env,內容是明確的假值:
DEMO_API_TOKEN=DEMO_ONLY_NOT_A_REAL_CREDENTIAL
把 /config.local.env 加進 .gitignore 後,git ls-files 仍列出檔名。改動那個假值,status 也仍顯示檔案被修改。原因是它已經追蹤過,不是忽略規則少寫了一個星號。
git ls-files -- config.local.env
git status --short
這個判斷與本站已追蹤與未追蹤的差異相同;接下來要處理的是暴露後的止損範圍,不只讓變更列表變乾淨。正式案例應先保護憑證,再處理追蹤與副本。
精確移除索引,保留本機設定
先保存必要的本機設定,核對工作目錄與索引差異。確認範圍後,針對單一檔案操作:
git diff
git diff --cached
git rm --cached -- config.local.env
git add -- .gitignore
git diff --cached
--cached 只從索引移除。本例操作後,工作目錄的檔案仍存在,暫存差異顯示下一次提交要移除那個檔案。若 Git 因索引和工作檔內容不一致而拒絕,先查看差異與備份,不要直接補 -f 或移除整個 repository 的索引。
確認下一個提交只包含預期的移除和忽略規則,再完成提交。示例提交後,ls-files 不再列出該路徑,status --short --ignored 則顯示 !! config.local.env。這確認目前版本已不追蹤,而且規則能忽略留下的本機檔案。
不要把含真值的檔案複製成另一個未忽略的新名稱。若需要團隊共用範本,另建只含欄位名稱與假值的設定示例,告訴新環境在哪裡提供真正的值;範本仍應再讀一次,避免把本機檔案原樣改名提交。
新版本沒檔案,舊提交還有內容
示例在移除追蹤的新提交完成後,仍用 git show 指定最初那個提交,讀回相同假字串:
git show 333acfb13d55:config.local.env
# 示例輸出,沒有真憑證
DEMO_API_TOKEN=DEMO_ONLY_NOT_A_REAL_CREDENTIAL
上面的提交前綴屬於這份本機示例;在自己的 repository 要用對應的歷史位置。這個結果說明刪除提交沒有抹去舊內容,不是示例真的外洩了可用金鑰。本機案例沒有 remote,也沒有任何推送。
真正敏感內容只在受控環境核對,不要把 git show 的完整輸出貼進 CI 日誌或公開畫面。確認「舊提交有這個路徑」與確認憑證是否已失效,是不同工作;前者由 Git 紀錄回答,後者要向發出憑證的服務核對。
已推送、尚未推送,盤點範圍不同
若從未分享,也要確認是不是出現在備份、工作檔同步或其他本機副本。若已推到遠端,則需要盤點相關分支、標籤、pull request、fork、其他人的 clone,以及自動流程曾保存的輸出。不要只看預設分支最後一個版本。
不知道是否有人看過時,不應把「目前沒有看到下載紀錄」解讀成沒有人取得。對仍有效的憑證,先處理失效,再按需要調查存取與使用情況;要報告的是已確認、待確認及已完成的項目,不是猜測一切安全。
通知維護者時,用檔案路徑與涉及服務描述問題,完整真值留在受控渠道。這可以讓有權限的人判斷影響,不增加一份公開副本。本文沒有提供任何真實帳號的變更指令。
歷史清理要協調,不能只 force push
需要清理歷史時,先依平台文件與團隊流程安排。重寫歷史會改提交識別,影響其他人的分支和工作;舊 clone 若再次把舊提交推回,敏感內容也可能重新出現。不能由一個人清完預設分支,就宣稱所有副本已處理。
GitHub 文件說明,其他 clone、fork、快取視圖與引用舊提交的 pull request,可能仍保留可讀入口。你也不能直接刪除別人電腦上的 clone。需要哪些平台支援與合作步驟,按實際暴露範圍決定,不把本機重寫當成全網刪除證明。
若撤銷或輪換已足以消除憑證使用風險,歷史重寫是否必要仍要評估。這篇沒有在共用歷史執行 rewrite 或推送,讀者也不應把示例的 rm --cached 當成整套歷史清理指令。
用分開的結果交接
交付時分別記錄:提供者是否確認舊憑證失效、應用是否已接入新值、目前提交是否停止追蹤,以及哪些歷史或副本已處理。還沒驗證的副本留待追蹤,不因一個 commit 完成就全部打勾。
後續再檢查忽略規則與假值範本能否避免重犯,必要時按團隊政策安排提交前或平台端的敏感資料掃描。掃描提示可以協助發現,不能取代已暴露憑證的撤換與存取調查。

評論0