.gitignore 沒生效?已追蹤檔案要先從 Git 暫存區移除
把 local settings.txt 寫進 .gitignore,修改後卻仍出現在 git status,先確認檔案是否已被追蹤。.gitignore 控制未追蹤檔案的忽略規則,不會讓既有 tracked file 自動離開 Git。 規則可能完全正確,只是作用對象不符。
如果目標是讓後續版本不再包含這個檔案,同時保留自己的本機副本,應對確認過的確切路徑使用 git rm --cached,再審查暫存區。不要為了一個檔案重建整個 index。
.gitignore 規則與追蹤狀態分開查
以下在出問題的 repository 根目錄執行,將範例路徑換成自己的檔案;空白路徑要保留引號:
git status --short -- 'local settings.txt'git ls-files --error-unmatch -- 'local settings.txt'git check-ignore -v --no-index -- 'local settings.txt'ls-files --error-unmatch 找到路徑時會輸出它並成功結束;找不到時會回傳非零狀態。前者表示它已在 index,這時增加忽略規則不會讓修改消失。
依 check-ignore 文件,預設不顯示已追蹤檔案,因為那些檔案不受忽略規則控制。--no-index 讓你針對規則進行檢查,-v 顯示規則檔、行號與 pattern。這個選項只是診斷,不會修改 index。
若輸出 pattern 以 ! 開頭,代表否定規則;不能只因為有輸出,就說它會被忽略。沒有輸出時,檢查規則位置、大小寫與路徑,不要直接用強制參數掩蓋問題。gitignore 官方文件也說明,多個目錄層級的規則會參與判斷。
逐檔停止追蹤,先預覽再操作
確認這個檔案應該從後續版本移除,並已備妥自己的副本後,才執行:
git rm --cached --dry-run -- 'local settings.txt'git rm --cached -- 'local settings.txt'git diff --cached --name-status -- 'local settings.txt'git diff --cached -- 'local settings.txt'git rm 文件說明,--cached 僅從 index 移除路徑,保留工作目錄的檔案。暫存差異出現 D 是預期結果:下一次包含這項變更的 commit 將不再追蹤它,並不代表這次指令刪掉本機副本。
如果 Git 因暫存內容與其他版本不一致而拒絕,先保存工作檔與暫存版本,再分別閱讀差異。不要立刻加 -f,也不要對整個 repository 執行遞迴移除。index 與工作檔案可能各有尚未提交的內容,可先用 git diff 三種比較辨識哪一份需要保留。
審查時也要確認 .gitignore 的規則有被納入預定提交。真正提交前檢閱全部已暫存檔案,避免把原本就存在的其他 staged 修改一起帶入;本文不提供一條包辦所有檔案的提交命令。
在暫存 repository 重現「本機還在,Git 已不追蹤」
以下是完整 Bash 實驗,僅使用自行建立的 OS 暫存目錄與假資料,不操作目前專案。存成 ignore-check.sh 後執行 bash ignore-check.sh;需要 Git、rg 與 mktemp,完成後保留 fixture 供檢查。
#!/usr/bin/env bashset -eufixture=$(mktemp -d)git init -q "$fixture"cd "$fixture"git config user.name 'Fixture'git config user.email 'fixture@example.invalid'git config commit.gpgsign false
printf 'original\n' > 'local settings.txt'git add -- 'local settings.txt'git -c core.hooksPath=/dev/null commit -qm 'track fixture'printf '/local settings.txt\n' > .gitignoreprintf 'local edit\n' >> 'local settings.txt'
git ls-files --error-unmatch -- 'local settings.txt' > /dev/nullgit check-ignore -v --no-index -- 'local settings.txt'git rm --cached --dry-run -- 'local settings.txt'git rm --cached -- 'local settings.txt'
test -f 'local settings.txt'test "$(cat 'local settings.txt')" = "$(printf 'original\nlocal edit')"if git ls-files --error-unmatch -- 'local settings.txt' > /dev/null 2>&1; then printf 'FAIL: still tracked\n' >&2 exit 1figit diff --cached --name-status -- 'local settings.txt' | rg '^D[[:space:]]'git check-ignore -q -- 'local settings.txt'# 停止追蹤尚未提交;舊 commit 的檔案仍可讀取。test "$(git show 'HEAD:local settings.txt')" = originalprintf 'PASS: local file kept; index removal staged; history unchanged\n'printf 'Fixture: %s\n' "$fixture"腳本以 rg 確認暫存差異是刪除。內容維護流程於 2026-10-27 在 macOS、Git 2.54.0(Apple Git-157)執行刊登腳本,確認空白檔名、本機修改保留、忽略規則與歷史讀取。它沒有 push、改寫歷史或模擬團隊成員拉取。
停止追蹤的影響要分三層看
本機這次執行 --cached 會留下檔案;提交並分享這個刪除後,其他人的 checkout 或更新可能移除原先受追蹤的副本,不能保證每個人都會保留。團隊應先約定備份、範本及重新建立本機設定的方式。
已存在的 commit 不會因 .gitignore 或 git rm --cached 改寫,fixture 的 git show HEAD:... 就能驗證。如果檔案曾包含真實憑證,停止追蹤不能撤銷外洩;需另依憑證供應商流程撤銷或輪替,歷史清理則是另一個需要協調的操作。
只是想暫時不提交某個已追蹤的個人修改,也不應把整個團隊仍需要的檔案刪出版本。可先把產品設計改成「受追蹤範本+未追蹤本機覆寫檔」,確認程式確實載入後者,再決定要從 Git 移除哪一份。
參考資料: