プロジェクト全体のdiffは情報量が多すぎてレビューしづらく、知りたいのは「今自分がいじった特定ファイルの差分だけ」というケースは日常茶飯事です。git diffにファイルやパスを指定すれば、ノイズを除いた本当に見たい差分だけを表示できます。
この記事では、git diffでファイル指定する方法を体系的に解説します。単一ファイル・ディレクトリ・globパターン・除外指定といったパススペック(pathspec)の書き方、--区切りの意味、working/index/HEADなどどの状態と比較するかとの組み合わせ、そしてシェル展開の落とし穴まで、実務で迷わない形で網羅します。
この記事で学べること
- ファイル指定の基本書式と
--区切りの必要性 - 単一/複数/ディレクトリ/globパターンの書き分け
- 除外指定(
:(exclude))と大文字小文字無視(:(icase)) - リポジトリトップ相対指定(
:/)やリテラル指定(:(literal)) - working tree・index・HEAD・コミットなど比較対象との組み合わせ
- ステータス別の表示オプション(
--name-only・--stat・-w) - シェル展開・ブランチ名衝突などよくある落とし穴の回避
基本:git diff にファイル名を渡すだけ
もっとも単純な使い方は、git diffのあとにファイル名を渡すことです。引数を何も指定しない場合は「作業ツリー ↔ index」の比較、そこにファイル名を追加するとそのファイルの同じ比較に絞り込まれます。
# ひとつのファイル git diff index.html # 複数ファイル(スペース区切り) git diff index.html style.css # ディレクトリ配下すべて git diff src/ # カレントディレクトリ全体(= 引数なしと同じ) git diff . # リポジトリのルート相対で指定(どのサブディレクトリにいても同じ結果) git diff :/src/auth.py
ポイント:パス指定は現在いるディレクトリからの相対パスが基本です。サブディレクトリからでも:/path/from/repo/rootでリポジトリトップ相対の指定ができます。スクリプト化するなら$(git rev-parse --show-toplevel)で絶対パスを取るのも確実です。
「--」区切りの意味と必要性
Gitコマンドでは--(ハイフン2つ)でコマンド引数とパスを明確に分離できます。ブランチ名とファイル名が同名だとGitが迷ってエラーになるため、この区切りを入れるのが安全です。
# 通常:パスはそのまま書ける git diff src/auth.py # -- で明示的に「ここから先はパス」と宣言 git diff -- src/auth.py # ブランチ名と同名ファイルがある場合は -- で区別(必須) git diff main -- main # main ブランチ vs main というファイル # 複数コミット比較にパスを追加する書式 git diff v1.2.0 v1.3.0 -- src/auth.py # ブランチ比較+パス指定 git diff main feature -- src/
— を付けるべき場面
- パス名とブランチ名/タグ名が衝突している可能性がある
- パスが
-で始まる(オプションと誤解されるのを防ぐ) - スクリプトで動的にパスを組み立てる(意図を明示してバグを予防)
- commit指定+パス指定の順序を明確にしたい
globパターンで複数ファイルを一括指定
拡張子や名前パターンでまとめて指定できます。ただしシェル(bash等)が先にワイルドカードを展開してしまうため、必ずダブルクォートで囲むことでGitに解釈させます。
# 拡張子で絞る(必ず引用符で囲む) git diff -- "*.js" git diff -- "*.ts" "*.tsx" # 任意ディレクトリ配下(再帰) git diff -- "src/**/*.py" # **(再帰)はリポジトリのgitattributesやsparse-checkout設定と相性に注意 # ディレクトリ直下のファイルだけ git diff -- "src/*.py" # 名前パターン git diff -- "test_*.py" # 複数パターンの組み合わせ git diff -- "*.css" "*.scss" "*.less"
注意:クォートを付け忘れると、シェルが先にglob展開を行ってからGitに渡します。現在存在するファイルだけが対象になり、削除されたファイルや今はマッチしないパスが漏れることがあります。Gitに解釈させたいときは必ずダブルクォートで囲みましょう:git diff -- "*.log"。
除外指定:特定ファイルをdiffから外す
「src/配下のdiffを見たいがtests/は除きたい」「ロックファイルの巨大diffを除外したい」といった場面では、マジックパススペック:(exclude)が便利です。
# src/ 配下を見るが、テストは除外 git diff -- "src/" ":(exclude)src/tests/" # 短縮形 :! も使える git diff -- "src/" ":!src/tests/" # ロックファイルを除外(よくあるノイズ対策) git diff -- . ":(exclude)package-lock.json" ":(exclude)yarn.lock" # 複数拡張子の除外 git diff -- . ":!*.min.js" ":!*.map" # カレント全体から特定ディレクトリ除外 git diff -- . ":(exclude)node_modules/" ":(exclude)dist/"
ポイント:除外指定は包含指定と組み合わせる必要があります。「全体-除外」の形で書くのが基本。git diff -- ":!tests/"単独だと「tests以外」ではなく「何も指定していない+除外」扱いで期待通りに動きません。. ":!tests/"のように「含める範囲」を明示しましょう。
マジックパススペック一覧
Gitには:(name)の形で指定する便利なマジックパススペックが複数あります。知っておくと検索の幅が広がります。
# 大文字小文字無視(READMEかreadmeか曖昧なとき) git diff -- ":(icase)readme.md" # * や ? などのメタ文字を含むファイル名をそのまま探す git diff -- ":(literal)log-*.txt" # 「log-*.txt」という名前のファイル # リポジトリ全体から git diff -- ":/" git diff -- ":/docs/README.md" # 複数の条件を組み合わせる(カンマ区切り) git diff -- ":(icase,glob)**/*.MD"
比較対象との組み合わせパターン
ファイル指定はどの状態と比較するかと組み合わせて使います。同じパス指定でも、比較対象を変えると結果が変わります。
比較対象の詳細は用途別に以下を参照してください:addしたファイルの変更を確認(staged)、ブランチ間の差分を比較(2ドットと3ドット)、コミット間の差分を比較(SHA指定・git show)。
ファイル指定と組み合わせる表示オプション
# 変更ファイル一覧 git diff --name-only -- src/ # ファイル名+変更種別 git diff --name-status -- src/ # 行数統計 git diff --stat -- "*.py" # 空白無視 git diff -w -- src/auth.py # 前後行コンテキストを増やす git diff -U10 -- src/auth.py # ワード単位で比較 git diff --word-diff -- README.md # 色を強制 git diff --color -- src/
旧記事でよくある誤解の訂正
-Uは「コンテキスト行数」オプションで数値が必須(例:-U10)-wは空白無視(--ignore-all-space)であって「ビジュアル表示」ではない-cはマージコミット用のcombined diffであって「簡潔表示」ではない- 「簡潔な表示」が欲しいなら
--statや--shortstatを使う
実践シナリオ
シナリオ① 巨大PRから自分の担当ファイルだけ見たい
# 自分の担当ディレクトリだけの差分 git diff main...feature -- src/auth/ # 統計で規模を把握 git diff --stat main...feature -- src/auth/ # テストだけ除外してコード本体だけ見る git diff main...feature -- "src/" ":!**/tests/**"
シナリオ② ロックファイルを除外してコード差分を確認
# package-lock.json などの自動生成ファイルを除外 git diff -- . \ ":(exclude)package-lock.json" \ ":(exclude)yarn.lock" \ ":(exclude)pnpm-lock.yaml" \ ":(exclude)poetry.lock" # エイリアス登録して使い回し git config --global alias.diff-src \ '!git diff -- . ":(exclude)package-lock.json" ":(exclude)yarn.lock"' git diff-src
シナリオ③ 特定拡張子だけを一括チェック
# TypeScriptソースの変更だけ見る git diff -- "*.ts" "*.tsx" # ブランチ比較で git diff main...feature -- "*.ts" "*.tsx" # PRレビューで変更行数を言語別に把握 git diff --shortstat main...feature -- "*.ts" git diff --shortstat main...feature -- "*.py"
シナリオ④ リポジトリ全体から特定パターンを探す
# 設定ファイル系だけの変更 git diff main...feature -- ":/config/" ":/*.yml" ":/*.yaml" ":/*.json" # CSSとSCSS git diff main...feature -- "*.css" "*.scss" # 大文字小文字無視でREADMEを全部 git diff main...feature -- ":(icase,glob)**/readme*"
GUI・IDEでのファイル単位比較
主要ツール
- VS Code / Cursor:Source Controlパネルでファイルをクリックで個別diffビュー
- JetBrains:Gitツールウィンドウで変更ファイル選択 → Compare with… / Show Diff
- SourceTree:ファイル選択で下部にdiff、パスフィルタも指定可
- GitHub Web:PR差分ページの
Filter changed filesで絞り込み - git difftool:
git difftool -- src/auth.pyでGUIビューア起動
やってはいけない落とし穴
globを引用符なしで書いてシェル展開される
git diff -- *.logと引用符なしで書くと、シェルが先にファイル名リストに展開してからgitに渡します。現在存在するファイルだけが対象になり、削除されたファイルはマッチしません。「Gitに解釈させたい」ときは必ず引用符で囲む:git diff -- "*.log"。同様の問題はpathspec全般に起きます。
ブランチ名と同名ファイルで曖昧エラー
git diff mainのように書いたとき、mainというブランチとmainというファイル/ディレクトリが両方あるとambiguousエラーになります。曖昧になり得るときは--区切りで明示してください:git diff main --(ブランチ)/git diff -- main(ファイル)。
除外だけを書いて「含まれない」と勘違いする
git diff -- ":!tests/"と書くと、「tests以外を表示」ではなく「空(包含対象が無い)+除外」になり、期待と違う結果になります。除外は必ず包含対象と組み合わせる:git diff -- . ":!tests/"で「カレント全体からtests/を除く」になります。
-U を数値なしで使う
git diff -U file.pyと書くと「-Uの後の数値」がなく、予期しない挙動になります。必ず-U10のように数値を続けるか、-U0(文脈なし)、-U3(既定と同じ)のように明示しましょう。
サブディレクトリで相対パスがずれる
サブディレクトリでgit diff src/auth.pyと打つと、現在ディレクトリからの相対パスとして解釈されます。同じ指定でもディレクトリ位置で結果が変わるため、スクリプトや手順書ではリポジトリトップ相対の:/src/auth.pyや絶対パスを使うと事故が減ります。
よくある質問
-で始まる、スクリプトで動的に組み立てる、などのケースでは--を付けて明示するのが安全。迷うなら「常に--」で書くのが無難です。** は使える?git diff -- "src/**/*.py")。シェルによっては**を有効化しないと期待通りに動かないこともあり、Git側で確実に解釈させたい場合は:(glob)マジックを付けると確実です。:/を付けるか、:(top)pathマジックを使います。例:git diff -- :/src/auth.py。サブディレクトリからでもリポジトリトップ相対で指定できるので、手順書やスクリプトで便利です。:!patternを並べて書きます:git diff -- . ":!*.min.js" ":!dist/"。エイリアスでdiff-cleanのように登録しておくと毎回書かずに済みます。:(icase)マジックを使います:git diff -- ":(icase)readme.md"。Windowsからのリネーム整理などで役立ちます。globと組み合わせるなら":(icase,glob)**/readme*"のようにカンマ区切り。*や?が入っているファイルを指定したい:(literal)マジックで解釈を無効化できます:git diff -- ":(literal)log-*.txt"は「log-*.txtという名前のファイル」を指します。通常運用ではほぼ出会いませんが、知っておくと便利です。git diff --name-only -- src/でファイル名リスト、--name-statusで変更種別付き、--statで行数統計、と目的で使い分けます。パイプでxargsに渡して一括処理も可能です。関連記事
- 【Git】addしたファイルの変更を確認する方法 — staged変更+ファイル指定
- 【Git】ブランチ間の差分を比較する方法 — 2ドット/3ドットとファイル指定の組み合わせ
- Gitでコミット間の差分を比較する方法 — SHA指定と組み合わせたファイル絞り込み
- 【Git】addの取り消し方法 — 特定ファイルだけunstage
- 【Git】消したファイルを戻す方法 — 削除ファイルの差分確認
- 【Git】管理からファイルを外す方法 — pathspecを使った追跡解除
- 【Git】よく使うgitコマンドまとめ — 日常コマンドの早見表
まとめ
- ファイル指定は
git diff [対象] -- <path>の形が基本 - 単一/複数/ディレクトリ/globが可能——globは必ず引用符で囲む
- 除外は
:!pathまたは:(exclude)path、包含と組み合わせる - リポジトリトップ相対なら
:/pathまたは:(top)マジック - 大文字小文字無視:
:(icase)、リテラル::(literal) - 比較対象(working/index/HEAD/コミット/ブランチ)と自由に組み合わせ可能
- ブランチ名との衝突を防ぐため、迷ったら
--区切りを明示
ファイル指定を使いこなすと、巨大プロジェクトでも「自分が見たい差分だけ」を素早く取り出せます。パススペックの基本+マジック(:!・:/・:(icase))を押さえれば、レビュー・リリースノート作成・影響範囲調査がぐっと効率化します。ブランチ名衝突やシェル展開といった落とし穴さえ避ければ、日常のあらゆる場面で役立つ強力な武器になります。

