カスタムGit Diff Driverの設定:バイナリデータの代わりにPDF・Word・SQLite・画像ファイルの内容を表示する

Git tutorial - IT technology blog
Git tutorial - IT technology blog

先週、プロジェクト内のWordドキュメントの変更履歴を確認する必要があった。git log -p contract.docx を実行してみると、ターミナルに意味不明なバイナリ文字の羅列が表示された。どのバージョンでどの条項が追加されたのか、誰がどの箇所を修正したのか——まったく追跡できなかった。

Gitはテキストファイルにはとてもパワフルだが、バイナリファイル(PDF、Word、SQLite、画像など)に対しては、デフォルトでは Binary files differ と表示するだけで止まってしまう。この問題を解決できる、あまり知られていない機能がある:Git Diff Driverだ。

Git Diff Driverとは?

Git Diff Driverは、Gitのデフォルトエンジンの代わりに外部コマンドを指定してdiff処理を行う仕組みだ。diff driverが設定されたファイルをGitが検出すると、そのコマンド——通常はバイナリファイルをテキストに変換するツール——を呼び出し、テキスト出力を通常のdiffと同様に処理する。

動作の流れは以下の通りだ:

  1. Gitが report.pdf の変更を検出する
  2. Gitが設定を読み込む:*.pdf ファイルは pdf という名前のdiff driverを使用
  3. Gitが pdf driverを呼び出し、pdftotext コマンドでファイルをプレーンテキストに変換する
  4. Gitが2つのバージョンのテキスト出力を通常ファイルと同様にdiffする

結果として、Binary files differ の代わりに、追加・削除・修正されたテキストの内容が正確に表示される

設定はたった2ステップだ:

  1. ~/.gitconfig(またはリポジトリの .git/config)にdriverを定義する
  2. .gitattributes でそのdriverをファイルの種類に割り当てる

実践:ファイルの種類ごとの設定

1. PDFファイル — pdftotext を使用

poppler-utils パッケージから pdftotext をインストールする:

# Ubuntu/Debian
sudo apt install poppler-utils

# macOS
brew install poppler

~/.gitconfig に追加する:

[diff "pdf"]
    textconv = pdftotext -layout -enc UTF-8 - -

リポジトリの .gitattributes に定義する:

*.pdf diff=pdf

テストしてみる:

git diff HEAD~1 HEAD -- report.pdf

Binary files differ の代わりに、PDFで追加または削除されたテキストがターミナルに正確に表示される。契約書や技術仕様書のレビュー時にこれを最もよく使う——Acrobatを開いてバージョンを比較する必要なく、ターミナル上で直接確認できる。

2. Word/DOCXファイル — pandoc を使用

2つの選択肢がある。フォーマット処理が優れているため、pandoc の方が好みだ:

# Ubuntu/Debian
sudo apt install pandoc

# macOS
brew install pandoc

~/.gitconfig にdriverを定義する:

[diff "docx"]
    textconv = pandoc --to=plain

よりシンプルにテキストを抽出したい場合は、docx2txt を使う:

pip install docx2txt
[diff "docx"]
    textconv = python3 -c "import docx2txt,sys; print(docx2txt.process(sys.argv[1]))"

.gitattributes に追加する:

*.docx diff=docx
*.doc  diff=docx

3. SQLiteファイル — SQLにdumpしてdiffする

SQLiteデータベースはバイナリだが、SQLにdumpすれば内容は完全に読み取れる。小さなシェルスクリプトを書き、/usr/local/bin/git-sqlite-diff に保存する:

#!/bin/bash
sqlite3 -readonly "$1" .dump
chmod +x /usr/local/bin/git-sqlite-diff

~/.gitconfig に追加する:

[diff "sqlite3"]
    textconv = git-sqlite-diff

.gitattributes でデータベースファイルに割り当てる:

*.db      diff=sqlite3
*.sqlite  diff=sqlite3
*.sqlite3 diff=sqlite3

diffすると、GitはSQL INSERT/CREATE TABLEの変更を表示する——データベースクライアントを開かずに直接レビューできる。実用的な注意点:数十MBのデータベースを .dump すると、数百万行のINSERTになることがある。その場合、スキーマだけをdumpすれば構造の変更箇所を把握するのに十分だ:

#!/bin/bash
sqlite3 -readonly "$1" .schema

4. 画像ファイル — exiftool でメタデータをdiffする

画像のピクセルをdiffすることはできないが、メタデータはdiffできる:サイズ、作成日、カメラ設定、GPSなど。exiftool をインストールする:

# Ubuntu/Debian
sudo apt install libimage-exiftool-perl

# macOS
brew install exiftool

~/.gitconfig に追加する:

[diff "image"]
    textconv = exiftool

.gitattributes に定義する:

*.png  diff=image
*.jpg  diff=image
*.jpeg diff=image
*.gif  diff=image
*.webp diff=image

ピクセルサイズやカラープロファイルの詳細情報を確認したい場合は、ImageMagickの identify を使う:

sudo apt install imagemagick

# ~/.gitconfig の中:
[diff "image"]
    textconv = identify -verbose

グローバル設定 vs リポジトリ単位の設定

driverの設定を行う場所は2つある:

  • ~/.gitconfig:マシン上のすべてのリポジトリに適用——PDF、DOCX、画像には最適。どのプロジェクトでも共通して使えるツールのため
  • .git/config:現在のリポジトリにのみ適用——そのプロジェクト固有のdriverに適切

.gitattributes ファイルはチーム全体が恩恵を受けられるようリポジトリにcommitすべきだ。driver定義については、各自が必要なツールをインストールし、自分のマシンで設定する

典型的なプロジェクトの完全な .gitattributes ファイル:

# バイナリファイルのdiff driver
*.pdf     diff=pdf
*.docx    diff=docx
*.doc     diff=docx
*.db      diff=sqlite3
*.sqlite  diff=sqlite3
*.sqlite3 diff=sqlite3
*.png     diff=image
*.jpg     diff=image
*.jpeg    diff=image
*.gif     diff=image
*.webp    diff=image

git log と git show でも使用可能

diff driverは git diff だけでなく、他のコマンドでも動作する:

# 履歴の変更を確認する
git log -p -- report.pdf

# 2つのブランチを比較する
git diff main..feature-branch -- database.db

# 特定のコミットのファイル内容を確認する
git show abc1234:report.pdf | pdftotext - -

重要な点:driverはdiffを表示するときにのみ実行され、Gitのファイル保存方法には影響しない。ファイルはオブジェクトストアにバイナリ形式のまま保存される——完全に安全だ。

以前、間違ったブランチにforce pushして重要なコードを失ったことがある——それ以来、共有ブランチで何か操作する前に必ず履歴を細かく確認するようにしている。だからこそ、バイナリファイルのdiffが読めることは単なる便利さにとどまらない——コミットメッセージを見て推測するのではなく、何をpushするか正確に把握できる。

よくあるエラーの対処法

  • driverが動作しないgitconfig のdriver名が .gitattributes の名前と一致しているか確認する(大文字・小文字を区別)。例:diff=pdf[diff "pdf"] と一致している必要がある
  • ツールが見つからない:GitはツールがPATHに存在する必要がある。ターミナルで直接コマンドを実行して確認してみること
  • 大きなSQLiteで出力が多すぎる.dump.schema に変更してテーブル構造のみを表示する
  • PDFのエンコードエラー:pdftotextコマンドに -enc UTF-8 を追加すれば解決

まとめ

Gitはデフォルトでバイナリファイルをブラックボックスとして扱う——変更があったことはわかるが、何が変わったかはわからない。Diff Driverはその制限を打ち破る:PDF、Word、SQLite、画像——すべてが通常のコードファイルと同様にレビューできる。

一度設定すれば、ずっと使える。チームで作業している場合は、すぐに .gitattributes ファイルをリポジトリにcommitしよう——各自が必要なツールを自分のマシンにインストールするだけで、チーム全体が恩恵を受けられる。

Share: