既にコミット済みのファイルの変更を無視したい場合は git update-index --skip-worktree を使う。.gitignore や .git/info/exclude は未追跡ファイルにしか効かない。
.git/info/exclude では追跡ファイルの変更を無視できないプロジェクトごとにローカル環境だけでファイルを無視したい時、.git/info/exclude を使えばいいと思うかもしれない。しかしこれには落とし穴がある。
.git/info/exclude も .gitignore も、未追跡のファイルをignoreするためのもの。既にコミット済み(追跡されている)ファイルには効果がない。
つまり、既にリポジトリに含まれている設定ファイルをローカルでカスタマイズして、その変更を無視したい場合には使えない。
--skip-worktree を使う既に追跡されているファイルのローカルでの変更を無視するには、git update-index --skip-worktree を使う:
# ローカルの変更を無視する
git update-index --skip-worktree path/to/file
# 元に戻す
git update-index --no-skip-worktree path/to/file
--skip-worktree とはこれは「このファイルはローカルで変更するけど、その変更は追跡しない」という設定。設定ファイルのローカルカスタマイズなど、意図的に変更を無視したい場合に使う。
config/local.py, .env.local など)のカスタマイズ# --skip-worktree が設定されているファイルの一覧
git ls-files -v | grep '^S'
# パス名だけ欲しい場合
git ls-files -v | grep '^S' | cut -c 3-
git ls-files -v の出力の意味S = skip-worktree が設定されているH = 通常の追跡ファイルh = assume-unchanged が設定されているgit config --global alias.skipped "ls-files -v | grep '^S'"
# 使う時
git skipped
--skip-worktree vs --assume-unchangedGit には似たようなオプションとして --assume-unchanged もあるが、用途が異なる:
| オプション | 用途 | 安定性 |
|---|---|---|
--skip-worktree |
意図的に変更を無視する | 安定(ユーザーが明示的に解除しない限り維持) |
--assume-unchanged |
パフォーマンス最適化 | 不安定(Git操作で勝手にリセットされることがある) |
推奨: ローカルの変更を意図的に無視したい場合は --skip-worktree を使う方が確実。
リモートで同じファイルが更新されて git pull しようとするとコンフリクトする可能性がある。その場合は:
# 一旦 skip-worktree を解除
git update-index --no-skip-worktree path/to/file
# ローカルの変更を退避
git stash
# リモートから取得
git pull
# 必要に応じて変更を戻す
git stash pop
# 再度 skip-worktree を設定
git update-index --skip-worktree path/to/file
--skip-worktree はローカル設定なので、チーム全体で無視したいファイルには .gitignore を使うべき。
.gitignore または .git/info/excludegit update-index --skip-worktreegit ls-files -v | grep '^S'ローカル環境固有の設定変更を気にせず開発できるようになる、地味だけど便利なテクニックだ。