git rm --cachedで追跡だけを外し、.gitignoreと一緒にコミットする
.gitignoreは、まだGitが追跡していないファイルを無視するための設定です。一度addしてコミットしたファイルは、後から.gitignoreに名前を書いても追跡が続き、編集するたびにgit statusへ出てきます。Git公式のgitignoreの説明も、追跡中のファイルには影響しないと明記し、追跡をやめるにはgit rm --cachedを使うよう案内しています。
git rm --cachedは、ファイルをGitの管理(インデックス)からだけ外し、PCのファイルはそのまま残します。--cachedを付けないgit rmはPCのファイルも削除するので、付け忘れないでください。-nを付けると何も消さずに対象だけを表示するので、先に-nで確かめます。
以下はapp.envを外す例です。.gitignoreにapp.envの行を書いてから実行し、.gitignoreの変更と、追跡をやめる変更を同じコミットに入れます。コマンドはBash(WSLやGit Bashなど)用です。
git rm -n --cached -- app.env
git rm --cached -- app.env
git add -- .gitignore
git status --short
git commit -m 'Stop tracking app.env'外した後に残るもの・消えるもの
PCのファイルは残りますが、このコミットを取り込んだ他のPCやclone先では、git pullでそのファイルが作業フォルダーから削除されます。Gitから見ると「ファイルを削除したコミット」だからです。チームで使うリポジトリでは、取り込む前にファイルを控えるよう伝えてください(手順は後の節)。
過去のコミットにはファイルの中身が残ります。パスワードやAPIキーをコミットしてpushしていた場合は、追跡を外しただけでは見られる状態のままです。そのキーやパスワードを発行元で無効にし、新しいものに替えてください。履歴から消すには履歴の書き換えが必要で、この記事では扱いません。
表は横にスクロールできます →
| 対象 | git rm --cachedとコミットの後 |
|---|---|
| 自分のPCのファイル | 残る。.gitignoreに書いてあれば、git statusに出なくなる |
| 他のPC・clone先のファイル | 編集していなければgit pullで作業フォルダーから削除される(編集していればpullが止まる) |
| 過去のコミットの中身 | 残る。git showなどで見られる |
| リモートに送ったコミット | 残る。追跡を外すコミットをpushしても消えない |
練習用フォルダーを作り、そこへ移動する
以下はGitが使えるBash(WSLやGit Bashなど)用です。PowerShellへそのまま貼る例ではありません。実務のリポジトリではなく、まだ存在しないgit-rm-cached-practiceというフォルダーで試します。次の2行は1行ずつ実行し、エラーが出たらそこで止めてください。既に同名フォルダーがある場合は、別の新しい名前を選びます。
mkdirとcdの両方が成功したことを確かめてから、次へ進みます。
mkdir git-rm-cached-practice
cd git-rm-cached-practice外したいファイルを、わざとコミットしておく
設定ファイルapp.envと、ログを入れるlogsフォルダー(a.logとb.log)、README.txtを最初のコミットに入れます。app.envの中身は練習用の文字列で、本物のキーではありません。名前とメールアドレスは、この練習リポジトリ内だけに設定する例示値です。リモートへの接続や送信は行いません。git init -bはGit 2.28以降で使えます。それより前の版では-b mainを外して実行してください。
最後のgit ls-filesは、追跡中のREADME.txt・app.env・logs/a.log・logs/b.logの4行を表示します。
git init -b main
git config user.name 'Practice'
git config user.email 'practice@example.invalid'
printf 'API_KEY=practice-only\n' > app.env
mkdir logs
printf 'log 1\n' > logs/a.log
printf 'log 2\n' > logs/b.log
printf 'hello\n' > README.txt
git add -- app.env logs README.txt
git commit -m 'Initial files'
git ls-files.gitignoreに書いても、追跡中のファイルは表示され続ける
.gitignoreにapp.envとlogs/の2行を書き、app.envとlogs/a.logを編集します。git status --shortは M app.env、 M logs/a.log(右列のM=未ステージの変更)、?? .gitignoreの3行で、.gitignoreに書いた2つは変更として表示されたままです。
git check-ignore -vは、ファイルがどの行で無視されているかを表示するコマンドです。ただし追跡中のファイルは調べないため、1つ目は何も表示せず、終了コードは1(どれも無視されていない)でした。--no-indexを付けると追跡中かどうかを見ずに調べ、.gitignore:1:app.envのように、.gitignoreの何行目に当たるかを表示します。ここで自分のファイル名が出ない場合は、.gitignoreの書き方が合っていません。追跡を外す前に直してください。
printf 'app.env\nlogs/\n' > .gitignore
printf 'API_KEY=changed\n' > app.env
printf 'log 3\n' >> logs/a.log
git status --short
git check-ignore -v app.env logs/a.log
git check-ignore -v --no-index app.env logs/a.log-nで対象を確かめてから、追跡を外す
フォルダーを外すには-rが必要です。-rを付けずにgit rm --cached logsとすると、fatal: not removing 'logs' recursively without -rと表示されて何も外れません。
-nを付けた1行目は、rm 'app.env'、rm 'logs/a.log'、rm 'logs/b.log'の3行を表示しますが、何も変えません。外したくないファイルが混ざっていないことを確かめてから、-nを外した2行目を実行します。
実行後のgit status --shortは、D app.env、D logs/a.log、D logs/b.log(左列のDはステージ済みの削除)と?? .gitignoreです。PCのファイルは消えていないので、lsで確かめます。編集したapp.envとlogs/a.logの中身もそのままです。
git rm -n --cached -r -- app.env logs
git rm --cached -r -- app.env logs
git status --short
ls app.env logs.gitignoreと一緒にコミットし、表示されなくなったことを確かめる
.gitignoreをaddしてコミットします。コミット後のgit ls-filesは.gitignoreとREADME.txtの2行になり、git status --shortは何も表示しません。
--ignoredを付けると、無視されているファイルも表示されます。!! app.envと!! logs/の2行が出れば、追跡から外れて.gitignoreで無視されています。
.gitignoreに書く前にgit rm --cachedだけを実行してコミットすると、app.envは?? app.env(未追跡)として表示され、次のgit add .で再び追跡されます。.gitignoreへの追加と同じコミットにしてください。
git add -- .gitignore
git commit -m 'Stop tracking local files'
git ls-files
git status --short
git status --short --ignored過去のコミットには中身が残る
git show HEAD~1:app.envは、1つ前のコミットにあるapp.envの中身を表示します。この練習ではAPI_KEY=practice-onlyと表示され、追跡を外した後も最初のコミットから読めることが分かります。git log --oneline --stat -1では、直前のコミットでapp.env・logs/a.log・logs/b.logが削除扱い(1 -)になっています。
pushしたリポジトリでは、リモートや他の人のcloneにも同じ履歴があります。キーやパスワードだった場合は、前の節のとおり発行元で無効にしてください。
git show HEAD~1:app.env
git log --oneline --stat -1他のPCでは、pullする前にファイルを控える
このコミットを別のPCやclone先でgit pullすると、そのPCのapp.envは削除されます。検証用に別のリポジトリとcloneを用意して試したところ、app.envを編集していないcloneではpullが成功してapp.envが消えました。編集していたcloneでは、Your local changes to the following files would be overwritten by merge:と表示されてpullが止まりました。
そのPCのファイルを残したい場合は、pullの前に作業フォルダーの外へコピーし、pullの後で戻します。先にls ../app.env.backupを実行し、ファイルがないというエラー(英語の環境ではNo such file or directory)が出ることを確かめてください。同じ名前の控えが既にあると、cpが確認なしで上書きします。下の1行目のgit restoreは、そのPCで編集していた内容を捨てて最後のコミットの状態に戻すコマンドで、編集していた場合にpullが止まらないようにします。&&でつないでいるので、コピーが失敗するとgit restore以降は実行されません。
git pullが失敗した場合(通信エラーや別のファイルの衝突など)も、最後のcpは実行されず、app.envは最後のコミットの中身のままです。編集していた内容は../app.env.backupに残っているので、cp ../app.env.backup app.envで戻してから、原因を直してやり直してください。
戻した後のgit status --shortは何も表示せず、--ignoredでは!! app.envと表示されます。pullで取り込んだ.gitignoreにより、戻したファイルは無視されます。先にそのPCでgit rm --cachedを実行してからpullする方法は、この検証ではThe following untracked working tree files would be removed by merge:と表示されて止まりました。
cp app.env ../app.env.backup && git restore -- app.env && git pull && cp ../app.env.backup app.env
git status --short
git status --short --ignoredフォルダーを控える場合は、中身だけをコピーする
logsのようなフォルダーは、下のように控えます。先にls ../logs.backupでファイルがないというエラーが出ることを確かめてから実行します。pullが失敗した場合は、コードの5〜6行目(mkdir -p logsから)を実行して戻してからやり直してください。行末に&&があると、Bashは次の行を続きとして扱い、途中で失敗するとその先を実行しません。戻せたことを確かめたら、rm -r ../logs.backupで控えを消してからやり直します。控えが残っていると、1行目のmkdirが失敗して止まります。
logs/.と../logs.backup/.の末尾の/.は、フォルダーの中身をコピーする指定です。cp -r logs ../logs.backupのように書くと、pullの後にlogsフォルダーが残っていた場合(追跡していない新しいログがあるときなど)、戻すときにlogsの中へlogs.backupというフォルダーが作られ、ファイルが元の場所に戻りません。検証では、logsが残る場合と消える場合の両方で、下の手順で編集後のlogs/a.logが元の場所に戻りました。
mkdir ../logs.backup &&
cp -r logs/. ../logs.backup/ &&
git restore -- logs &&
git pull &&
mkdir -p logs &&
cp -r ../logs.backup/. logs/
git status --short --ignored控えずにpullして消えたときは、ORIG_HEADから書き出す
控えずにpullしてファイルが消えた場合は、pullの直後(次のpullやmergeをする前)なら、下の1行でpull前のコミットにあった中身を書き出せます。ORIG_HEADはpullの前にいたコミットを指します。そのPCで編集していた内容のうち、コミットしていなかった分は戻りません。
書き出した後のgit status --short --ignoredは!! app.envで、戻したファイルは.gitignoreにより無視されます。
git show ORIG_HEAD:app.env > app.env
git status --short --ignored外せないときのエラーと、--cachedを付け忘れたとき
addした後でさらにファイルを編集していると、git rm --cachedはerror: the following file has staged content different from both the file and the HEADと表示して止まります。ステージの内容が、最後のコミットとも、PCのファイルとも違う状態です。git add -- ファイル名でステージをPCのファイルにそろえると、git rm --cachedを実行できます。PCのファイルは、この操作では変わりません。
--cachedを付けずにgit rm ファイル名を実行すると、PCのファイルも削除されます。ファイルを最後のコミットから編集していた場合は、error: the following file has local modificationsと表示されて削除されません。削除された場合は、中身が最後のコミットと同じだったので、コミットする前なら下の1行で戻せます。この練習でもnote.txtが最後のコミットの内容で戻り、git status --shortは何も表示しませんでした。そのあとで、--cachedを付けて実行し直します。
下のnote.txtは例の名前です。自分のファイル名に置き換えてください。
git restore --source=HEAD --staged --worktree -- note.txt
git status --short関連する操作と、確認した環境
まだコミットしていないファイルのaddを取り消すだけなら、関連記事「git addを取り消す:編集内容を残してステージから外す手順」のgit restore --stagedで足ります。直前のコミットに入れてしまっただけでpushしていない場合は、「直前のコミットを取り消す:git reset --softで変更をステージに残す手順」で取り消してから入れ直す方法もあります。
2026年10月22日、WSLのLinux・Git 2.53.0・非rootユーザーで掲載例を実行しました。.gitignoreの追加前後のgit status --short、git check-ignore -vの表示と終了コード(--no-indexの有無)、-rなしのエラー、-nの表示、外した後のgit ls-files・--ignoredの表示とPCのファイルが残ること、git show HEAD~1:app.envの表示、別のcloneでpullしたときにファイルが削除されることと控えて戻す手順(フォルダーとORIG_HEADからの書き出しを含む)、エラー表示と--cachedを付け忘れたときの戻し方を照合しています。Git公式の説明は2026年10月22日時点の版(git-rmは2.50.0、gitignoreは2.55.0、git-check-ignoreは2.52.0で更新)を参照しました。Git for Windows(Git Bash)・コマンドプロンプト・PowerShellでは実行していません。