【Git】管理からファイルを外す方法|rm –cached・.gitignore・skip-worktreeの使い分け完全ガイド

【Git】管理からファイルを外す方法 Git

node_modulesをうっかりcommitしてしまった、.envファイルがリポジトリに入ってしまった、IDEの個人設定(.idea/.vscode/)まで共有してしまった——「Gitに追跡されているファイルを管理から外したい」という場面は日常的に発生します。ファイルはローカルに残したままGitの追跡対象から外すのが正解で、単に.gitignoreに追記するだけでは解決しません。

この記事では、Gitでファイルを管理から外す方法を状況別に整理します。git rm --cachedによる「ファイルを残したまま追跡解除」、.gitignoreの正しい併用、一時的に変更を追跡させないskip-worktree/assume-unchanged、そして履歴から完全に削除したい場合の使い分けまで、実務で迷わない形で解説します。

この記事で学べること

  • Git管理下の「tracked」と「untracked」の違いとステータス確認方法
  • git rm --cachedで「ファイルは残して追跡だけ外す」手順
  • 単一ファイル・ディレクトリ・glob・ignored済み全件の一括外し方
  • .gitignoregit rm --cachedの正しい併用順序
  • 一時的に変更を見せないskip-worktreeassume-unchangedの使い分け
  • 他メンバーへの影響と、pull後に消えないための運用上の注意
  • 履歴から完全削除が必要なケースの判断基準
スポンサーリンク

まず押さえる:「Git管理」の3つの状態

「管理から外す」を正しく理解するには、Gitがファイルをどう扱っているかを整理すると迷いません。

状態 意味 git statusでの見え方
tracked(追跡中) 過去にgit addcommitされ、Gitが変更を監視中 変更時に「modified:」表示
untracked(未追跡) Gitが知らない新規ファイル 「Untracked files」に表示
ignored(無視) .gitignoreで除外指定、通常は表示されない 通常は非表示(-uで見える)

ポイント:「管理から外す」とはtrackedからuntrackedに戻すことです。.gitignoreは「まだtrackedになっていないファイル」にしか効きません。一度git addされたファイルは、まずgit rm --cachedでtrackedから外してから.gitignoreで今後の追跡も防ぐ、という2段階が必要です。

中心コマンド:git rm –cached でファイルを残して追跡を外す

Gitの追跡対象から外すメインコマンドはgit rm --cachedです。--cachedを付けると作業ツリーのファイルは削除されず、Gitのindex(ステージング領域)からだけ外れます。次のcommitで「ファイルが削除された」という変更が記録され、以降リポジトリの追跡対象外になります。

基本の使い方
# 単一ファイルを追跡から外す(ローカルには残る)
git rm --cached config/secrets.env

# ディレクトリを再帰的に外す
git rm --cached -r node_modules/

# globパターンで一括(シェル展開を避けるため引用符で囲む)
git rm --cached "*.log"
git rm --cached -r "build/"

# 追跡から外したことをcommit
git commit -m "chore: secrets.env を追跡対象から除外"

# プッシュしてチーム全体に反映
git push origin <branch>

git rm と git rm –cached の違い

コマンド Git index 作業ツリー(ローカル) 主な用途
git rm <file> 削除 削除 ファイル自体を消したい
git rm --cached <file> 削除 保持 追跡だけ外したい(管理解除)

削除しないのに「deleted:」表示になる

git rm --cached実行後のgit statusでは「deleted:」と表示されますが、これは「リポジトリから見て削除」という意味で、ローカルファイルは実在します。commit後に他メンバーがgit pullすると、その人のローカルからは削除されます(これは後述の落とし穴)。

.gitignore との正しい併用手順

git rm --cachedだけでは次にgit addしたら再び追跡対象に戻ります。再追跡を防ぐには.gitignoreに追記してから外すのが鉄則です。正しい手順は次のとおり。

正しい手順:gitignore → rm –cached → commit
# STEP 1: .gitignore に追加
echo "config/secrets.env" >> .gitignore
echo ".env.local" >> .gitignore
echo "*.log" >> .gitignore

# STEP 2: 既に追跡されているファイルを index から外す
git rm --cached config/secrets.env
git rm --cached .env.local
git rm --cached "*.log"

# STEP 3: .gitignore と 削除 をまとめてcommit
git add .gitignore
git commit -m "chore: 機密・ログファイルを追跡対象から除外"

# STEP 4: push
git push origin <branch>

一気に「.gitignoreに合致する追跡ファイル全部」を外す

.gitignoreを後から整備した場合、既に追跡済みのファイルが無視ルールに合致していても追跡され続けることがあります。全件一括で外す場合は次のテクニックが便利です。

ignored済みの追跡ファイルを一括untrack
# .gitignoreに合致する既追跡ファイルをリストアップ
git ls-files -i -c --exclude-standard

# そのまま一括で追跡解除(macOS/Linux/Git Bash)
git ls-files -z -i -c --exclude-standard | xargs -0 git rm --cached

# commit
git commit -m "chore: .gitignore に合致する追跡ファイルを一括除外"

# リポジトリ丸ごと index を作り直す強力な手段(全ファイル再stage)
git rm -r --cached .
git add .
git commit -m "chore: .gitignore を適用してindexを再構築"

注意:最後のgit rm -r --cached .git add .全ファイルのindexを作り直すため、改行コード・ファイルモード変更があると大量のdiffが出ることがあります。影響が不安な場合はまず対象ファイルだけ個別に処理してください。

「.gitignoreに追記したのに無視されない」問題の詳細は.gitignoreに追加しても既存ファイルが無視されないときの解決方法に原因と別解も含めて解説があります。

よくあるユースケース別の管理外し方

.env・config系の機密ファイル

機密ファイルを追跡から外す
# .gitignore に登録
echo ".env" >> .gitignore
echo "config/secrets.yml" >> .gitignore

# index から外す
git rm --cached .env config/secrets.yml

# commit
git add .gitignore
git commit -m "chore: 機密ファイルを追跡対象から除外"

警告:機密情報がパブリックリポジトリにpushされた場合、git rm --cached過去の履歴には残ります。漏洩した認証情報は即rotate(無効化・再発行)してください。履歴からの完全削除は履歴に含まれる機密情報を完全に削除する方法を参照。

ビルド成果物(dist/・build/・node_modules/)

ビルド成果物の一括解除
# .gitignore に追加
cat >> .gitignore << EOF
node_modules/
dist/
build/
*.log
.next/
EOF

# index から一括除外
git rm -r --cached node_modules/ dist/ build/ .next/
git rm --cached "*.log"

git add .gitignore
git commit -m "chore: ビルド成果物を追跡対象から除外"

IDE・OS固有ファイル(.idea/・.vscode/・.DS_Store)

個人の開発環境ごとに異なるIDE設定やOS生成ファイルはグローバルgitignoreで管理すると、各リポジトリの.gitignoreを汚さずに済みます。

グローバルgitignoreで個人環境を除外
# グローバルgitignoreを設定
git config --global core.excludesfile ~/.gitignore_global

# ファイルに記述
cat >> ~/.gitignore_global << EOF
.DS_Store
Thumbs.db
.idea/
.vscode/
*.swp
.vs/
EOF

# 既に追跡されているファイルは個別リポジトリで --cached 除外
git rm --cached -r .vscode/
git commit -m "chore: IDE設定ファイルを追跡対象から除外"

ポイント:IDE設定を.idea/フォルダごと外すかは判断が分かれます。共有すべき設定(run configuration、コード規約)は追跡、個人用(workspace.xml、タスク履歴)は除外というハイブリッド運用が現実的です。JetBrains公式の推奨.gitignoreを参照するとバランスが取れます。

大きなバイナリ・メディアファイル

リポジトリが肥大化してきた大きなファイルは、単に追跡解除するだけでなくGit LFSへの移行も検討します。LFS移行については本記事の範囲外ですが、「動画・画像・デザインデータ・ビルド済みバイナリ」はLFS対象の代表例です。

一時的に変更を追跡させない:skip-worktree と assume-unchanged

「ファイルはリポジトリに残したいが、自分のローカルだけ設定を変えて追跡させたくない」という特殊ケースにはgit update-indexの2オプションが使えます。追跡解除ではなく「追跡中だけど差分を見せない」という特殊な運用です。

skip-worktree の使い方
# ローカルの変更を追跡させない(意図的に別設定を使いたい場合)
git update-index --skip-worktree config/local-override.yml

# skip-worktree を解除(再度追跡を戻す)
git update-index --no-skip-worktree config/local-override.yml

# skip-worktree指定ファイルを確認(先頭がSまたはsの行)
git ls-files -v | grep "^[Ss]"
assume-unchanged の使い方
# パフォーマンス目的:「このファイルは変わらない」とGitに伝える
git update-index --assume-unchanged config/large-static.json

# 解除
git update-index --no-assume-unchanged config/large-static.json

# assume-unchanged指定ファイルを確認(先頭が小文字hの行)
git ls-files -v | grep "^h "

skip-worktree と assume-unchanged の違い

  • skip-worktree:「意図的に差分を追跡しない」宣言。pull/checkout時も設定が優先される
  • assume-unchanged:「変わらない前提」のパフォーマンス最適化。Gitが書き換える場合がある
  • 個人設定の上書きにはskip-worktreeが推奨、大量ファイルの高速化用途がassume-unchanged
  • どちらもローカル限定で、他メンバーには影響しない(.gitのinfo/excludeと同じ扱い)

注意:これらは本来の「管理から外す」とは違い、リポジトリには残したままローカルの挙動だけ変える特殊機能です。本当はconfig.example.ymlconfig.ymlを分離し、前者だけ追跡する設計にするのが最も健全です。

他メンバーへの影響と安全な運用

git rm --cachedはリポジトリ上で「ファイル削除」として記録されるため、pull した他メンバーのローカルからはそのファイルが消えます。これが最大の落とし穴です。

他メンバーが影響を受けるケース
# あなたがpushした時点から、プルする人に影響
# 他メンバー側で以下が起きる:
#   - .env が手元から消える(ローカルで復元が必要)
#   - node_modules/ が消える(npm ci で再インストール必要)
#   - IDE設定が消える(.vscode/ 等を再設定)

# 他メンバーがpull後に実行すべきコマンドの例
# (機密・環境ファイルの復元)
cp .env.example .env     # あるいは vault から再取得
# (依存再インストール)
npm install              # or npm ci

安全な運用フロー

  • 他メンバーに事前通知(Slack・PR descriptionで必ず周知)
  • .env.exampleconfig.example.ymlのようにテンプレートを追加
  • READMEやCONTRIBUTINGに「初回セットアップ手順」を明記
  • PRで変更内容を確認してもらう(自分一人でmainに直接pushしない)
  • CIを運用している場合は「追跡外になったファイル」がビルドに必要でないか確認

履歴からも完全に削除したい場合

git rm --cached今後の追跡を止めるだけで、過去のコミットに含まれる内容は履歴に残り続けます。git log -pや古いクローンから参照可能です。

目的 推奨手段
今後の追跡を止める(履歴には残してよい) git rm --cached.gitignore
履歴からも痕跡を消す(機密情報・大容量バイナリ) git filter-repo(またはBFG
機密が漏洩した rotate最優先→filter-repo→force push

重要:履歴書き換えは全メンバーの再cloneが必要な破壊的操作です。実行前に必ずチームに周知し、進行中の作業を退避してもらってください。詳しい手順は履歴に含まれる機密情報を完全に削除する方法を参照。

誤って管理から外したときの復旧

git rm --cachedの commit前・push前なら簡単に戻せます。

状況別の復旧コマンド
# commit前:index を元に戻す
git restore --staged <file>
# あるいは旧構文
git reset HEAD <file>

# commit済みだが未push:1つ前に戻す
git reset --soft HEAD~1

# push済み:revertで打ち消し
git revert <untrack-commit-SHA>
git push origin <branch>

# 特定ファイルだけ復元したい(過去コミットから取り出す)
git checkout HEAD~1 -- path/to/file
git commit -m "restore: path/to/file の追跡を復元"

ファイル復元の詳細は消したファイルを戻す方法、commit取り消しはコミットの取り消し方を参照。

やってはいけない落とし穴

.gitignoreに追記するだけで解決すると思う

.gitignoreすでに追跡されているファイルには効きません。既にtrackedになったファイルはgit rm --cachedで一度indexから外してからignoreすることで初めて無視されます。これを知らずに.gitignoreだけ更新して「変更が反映されない」と悩むのはGit初心者の王道ミスです。

–cached を付け忘れる

git rm <file>--cachedなし)はファイルごとローカルから削除します。大事な設定ファイルが消えてから「あれ?」となる事故が多発します。Git管理から外すだけなら必ず--cachedを付ける習慣を付けましょう。削除された場合でも未pushならgit restore <file>で戻せます。

他メンバーのローカルが消えることを忘れる

git rm --cachedをcommit/pushすると、他メンバーがgit pullした瞬間にそのファイルがローカルから消えます。.envやIDE設定など個人ファイルを消されて作業が止まる事故が起きます。PR descriptionや通知で事前アナウンス.env.exampleのようなテンプレートファイル用意がセットです。

機密情報をrm –cachedで消したつもりで安心する

既に説明したとおり、履歴には残ります。APIキーやパスワードがpushされてしまった場合は必ずrotate→filter-repoの順で対応します。履歴から消えても、GitHub等は一度公開された内容をキャッシュしている可能性があるため、「漏洩したものは取り戻せない」前提で動きましょう。

globパターンを引用符なしで指定してシェル展開される

git rm --cached *.logとクォートなしで書くと、シェルが先に*.logを現存ファイル名に展開してからgit rmに渡るため、将来追加される*.logには適用されません。Gitに解釈させたいパターンは必ずダブルクォートで囲みましょう:git rm --cached "*.log"

よくある質問

Qgit rm –cached と .gitignore、どちらを使うのが正解?
A両方です。既に追跡中のファイルを外すにはgit rm --cached、今後も追跡しないよう.gitignoreに追記、この組み合わせが正解。新規ファイルで一度もaddしていないなら.gitignoreだけで十分です。
Qgit rm –cached の後に「deleted」と出るけどファイルは消えてない
A正常な動作です。「リポジトリから削除(追跡解除)」という意味で、ローカルのファイルは残ります。他メンバーがpullすると、彼らのローカルからは消えます(自分のローカルは保持されます)。
Q誤ってgit rm(–cached忘れ)でファイルを消した
Acommit前ならgit restore <file>で復元できます。commit済みならgit checkout HEAD~1 -- <file>で前のコミットから取り出せます。詳しくは消したファイルを戻す方法を参照。
Qディレクトリ全体を追跡から外したい
Agit rm --cached -r path/to/dir/で再帰的に外せます。ディレクトリは追跡対象ではなく「その中のファイル群」が追跡されているため、-r(再帰)が必須です。
Q.envファイルを追跡から外したが、履歴のAPIキーが心配
A即座にAPIキーをrotate(無効化・再発行)してください。履歴からの完全削除はgit filter-repoで可能ですが、全メンバー再clone必須です。パブリックリポジトリの場合、既に自動収集されている前提で動くのが安全です。
Qskip-worktree と –cached の違いは?
A--cachedは追跡自体を止めて他メンバーにも影響します。skip-worktreeは追跡は続けつつ自分のローカルだけ差分を見せない特殊設定です。「リポジトリに残すが個人設定で上書きしたい」ときはskip-worktree、「そもそも管理から外したい」なら--cachedです。
Q.gitignore に追記したのに既存ファイルが無視されない
Aすでに追跡されているファイルには.gitignoreは効きません。git rm --cached <file>で一度indexから外してからcommitすれば無視されます。詳しくは.gitignoreに追加しても既存ファイルが無視されないときの解決方法を参照。

関連記事

まとめ

  • 「管理から外す」とはtrackedからuntrackedに戻すこと——git rm --cachedが中心コマンド
  • .gitignoreは「まだaddされていないファイル」にしか効かない
  • 正しい手順:.gitignore追記 → git rm –cached → commit → push
  • --cachedを忘れるとファイル自体が消える。必ず付ける
  • ディレクトリは-r、globは引用符で囲む
  • 個人環境だけ差分を見せたくないならskip-worktree(特殊用途)
  • 他メンバーはpullでファイルが消える——事前通知+テンプレート用意が必須
  • 履歴からの完全削除はfilter-repo(機密情報・大容量バイナリのみ)

「Git管理から外す」は.gitignoregit rm --cachedを併用するだけ、と覚えれば迷いません。ファイルは残したいが追跡だけ外したいという意図を正確にコマンドへ翻訳できれば、.env漏洩事故やnode_modules誤commitといった典型的な事故を未然に防げます。チーム全員のローカルに影響する操作であることを意識し、事前通知+テンプレートファイルの用意+READMEへの手順記載までセットで運用しましょう。