Gitインデックスの深淵:`assume-unchanged` と `skip-worktree` の境界線
「ローカルの環境変数ファイルやビルド設定を、Gitの追跡から外したい」。
現場でこの欲求に駆られた時、多くのエンジニアが安易に `git update-index –assume-unchanged` に手を伸ばす。しかし、それがチーム開発の地獄への入り口であることを知る者は少ない。
今日は、Gitのインデックスという「心臓部」を操作するこの2つのコマンドの決定的な違いと、DevOpsスペシャリストとして現場で絶対に守るべき「Git運用の流儀」を授ける。
—
1. 致命的な勘違い:そのコマンドは「何のために」あるのか
まず、この2つはどちらも「Gitにファイルの変更を無視させる」ためのものだが、設計思想が全く異なる。
`–assume-unchanged`(本来の用途:パフォーマンス改善)
- 思想: 「このファイルは(ユーザーが)変更するはずがない」とGitに嘘をつかせる。
- 用途: 巨大なリポジトリで、OSやファイルシステムが遅いために `git status` が重い場合、頻繁に変更されないファイルを「変更なし」と決め打ちしてI/Oを減らすためのもの。
- 悲劇: `git pull` でリモートからそのファイルの変更が降ってきたら、容赦なく上書きされるか、競合してインデックスが整合性を失う。
`–skip-worktree`(本来の用途:ローカル設定の保護)
- 思想: 「このファイルはローカル環境ごとに異なる。リモートの変更を無視して、私の手元で自由に書き換えさせてくれ」という意思表示。
- 用途: `.env` やローカル用のデバッグ設定など、「リモートの変更を追跡したくないが、自分の変更は保持したい」ものに使う。
- 安全: `git pull` でリモートが更新されても、Gitは「このファイルは無視対象だ」と認識しているため、ローカルの変更が守られる。
結論: ローカル設定をいじりたいなら、必ず `–skip-worktree` を選べ。
—
2. 現場を救う「Git運用」の鉄則
コマンドを知るだけでは二流だ。チーム全体を速くするための「仕掛け」を導入せよ。
神プラグイン:`git-extras` と `fzf`
CLIの操作速度が開発体験(DX)を左右する。
- [git-extras](https://github.com/tj/git-extras): `git ignore` や `git pull-request` など、実戦的なコマンドを即座に使えるようにする。
- [fzf](https://github.com/junegunn/fzf): `git checkout` のブランチ選択や、コミットログの検索に組み込め。検索速度が思考の速度に追いつく。
隠れたキーボードショートカット(`.gitconfig` ハック)
`.gitconfig` にエイリアスを詰め込み、指を最適化せよ。
[alias]
# ステージ済みの変更をインタラクティブに確認
st = status -sb
# skip-worktreeされている全ファイルをリストアップ
ls-skip = !git ls-files -v | grep ^S
# 全てのskip-worktreeを解除(事故防止用)
unskip-all = !git ls-files -v | grep ^S | cut -c3- | xargs git update-index –no-skip-worktree
—
3. 設定ファイル(YAML/JSON)のベストプラクティス
ローカル設定を管理するために `–skip-worktree` を使うのは「緊急避難」だ。プロは最初から設定を分離する構造を設計する。
YAML/JSON 設計の黄金律
1. `config.default.yaml`: チーム全員共通のデフォルト値。Git管理下。
2. `config.local.yaml`: ローカル固有値。`.gitignore` に含める。
3. 読み込みロジック: アプリ起動時に「Defaultをロードし、Localがあれば上書きする」実装にする。
実装例 (Python/Node風)
import yaml
import os
def load_config():
# デフォルトを読み込み
with open(“config.default.yaml”) as f:
config = yaml.safe_load(f)
# ローカル設定があればマージ(こっちを git ignore する)
if os.path.exists(“config.local.yaml”):
with open(“config.local.yaml”) as f:
local_config = yaml.safe_load(f)
config.update(local_config)
return config
—
4. 最後に:伝説のエンジニアからの忠告
「Gitのインデックスを汚す」という行為は、最後の手札であるべきだ。
もしチームメンバーが `–assume-unchanged` を使って「なぜか変更が反映されない!」と叫んでいたら、即座に `git ls-files -v | grep ^h` で犯人を特定し、修正を促してやってほしい。
技術とは、知識量ではなく「いかに不要なトラブルを未然に防ぐか」という設計思想に宿る。
明日のデプロイがよりスムーズになることを祈る。健闘を祈る。