記事
コードスニペットをアップロードせずに比較する
オンラインdiffツールに2つのファイルを貼り付けるたびに、そのコードはあなたのマシンを離れます。設定ファイル、データベースクエリ、.envスニペットに埋もれたAPIキー:すべてが管理できないサーバーに送られます。この記事では、diffアルゴリズムがどのように機能するか、粒度オプションが実際に何を意味するか、そして比較をローカルに保つことがなぜ重要かを解説します。
diffが計算するもの
diffツールは2つのテキストを受け取り、一方を他方に変換するための最小限の変更セットを見つけます。核心的な考え方は最長共通部分列(LCS)です:隣接していなくても、同じ順序で両方のテキストに現れる行(またはトークン)の最長シーケンスです。その共通部分列にないものはすべて、新しいバージョンへの追加か、古いバージョンからの削除です。 この古典的なアルゴリズムはMyers(1986年)によるもので、O((N+M)D)時間で最短編集スクリプトを見つけます。ここでNとMは2つのテキストの長さ、Dは編集回数です。実際には、ほとんどのツールが先頭の共通行と末尾の共通行を無視する前処理ステップを追加し、変更された領域に問題を絞り込みます。 結果はパッチです:一連のハンクで構成され、それぞれが連続したコンテキスト行、削除、追加のブロックを記述します。これがUnix diff、Git、ほとんどのコードレビューツールで使われるフォーマットです。

行、単語、文字の粒度
diffの粒度は、何を比較の単位とするかを決定します。行ベースのdiffはほとんどのツールのデフォルトです:各行が単一のトークンとして扱われます。これは高速で、文脈の中で読みやすい出力を生成しますが、その行の1つの単語しか変わっていなくても、行全体が変更としてマークされます。 単語レベルのdiffは、LCSを実行する前に各行を単語に分割します。これで行内で変わったものをより詳細に把握でき、散文、設定値、JSONに便利です。文字レベルのdiffはさらに進み、長い識別子の中の1文字の変更をハイライトできます。 空白の処理はノイズを追加します。CRLFで終わる行とLFで終わる同じ行は、厳密なバイト比較では異なるものとして表示されます。ほとんどのツールはdiff前に改行を正規化するフラグを提供しています。同様に、末尾のスペース、タブ対スペースのインデント、空白行もすべて余分なdiff出力を生成する可能性があります。異なるエディターやオペレーティングシステムのコードを比較するときは、通常、空白の正規化を有効にするのが適切なデフォルトです。
オンラインdiffツールのプライバシーリスク
オンラインdiffサービスやパステービンサービスは便利です:URLを開き、2つのスニペットを貼り付け、色付きの出力を得ます。問題は、貼り付けたテキストがサードパーティのサーバーに送信されることです。サービスによっては、そのテキストがログに記録され、インデックスされ、無期限に保存され、または分析プロバイダーと共有される可能性があります。 これは、コードに機密情報が含まれているときに最も重要です。ハードコードされた資格情報、内部ホスト名、独自のビジネスロジック、または個人識別可能なデータはすべてペーストに含まれる可能性があります。明示的なシークレットがなくても、内部コードの構造が、プライベートにしておきたいアーキテクチャ上の決定を明かす可能性があります。 リスクは仮説的なものではありません。セキュリティ研究者は、公開ペーストで資格情報と内部トークンを繰り返し発見しています。一部のサービスは、ユーザーが削除した後もペーストを保持します。キャッシュやバックアップにコピーが存在するためです。リモートサービスが受信したテキストをどう扱うかを確認する方法はありません。 唯一の確実な緩和策は、テキストをネットワーク経由で送信しないツールでdiffをローカルに保つことです。

ローカルdiffの実用的な用途
diffはコードレビューだけのものではありません。ローカルdiffが役立ついくつかの一般的なケース: コミット前にドキュメントや設定ファイルへの編集を確認する。Dockerfile、Nginx設定、Kubernetesマニフェストの2つのバージョンを比較して、デプロイ間で正確に何が変わったかを把握する。 環境間の設定のドリフトを確認する。本番とステージングの設定がホスト名とシークレット以外は同一であるはずなら、diffが意図しない乖離をすぐに示します。 デバッグ中のAPIレスポンスを比較する。RESTまたはGraphQL APIからの2つのJSONペイロードを貼り付け、単語レベルのdiffを実行すると、数百行を手動で読むことなく、追加されたフィールド、変更された値、削除されたキーが特定できます。 LLMが生成したコードをベースラインと比較する。モデルが関数を書き直したとき、行レベルのdiffはどのロジックが変わり、どれが同じままかを、両バージョンを独立して読むより速く示します。 これらのケースすべてで、関係するテキストは機密性が高く、リモートサーバーから遠ざけておくことが合理的な選択です。
ブラウザでアップロードなしに実行する
このサイトのtext-diffツールは、JavaScriptを使ってブラウザ内でdiff計算全体を実行します。2つのテキストを2つのパネルに貼り付けると、diffが1行ずつ、片側最大3000行まで即座にレンダリングされます。サーバーには何も送信されません。テキストはデバイスを離れません。 実装は行を単位に操作する標準的なLCSベースのアルゴリズムを使用しています。各行が1つのトークンとなり、2つのバージョン間の最長共通部分列を求めることで、その行が変更なし・追加・削除のいずれかを判定します。変更なしの行はハイライトなし、追加行は緑、削除行は赤で表示され、追加・削除の件数もあわせてカウント表示されます。現時点では単語単位や文字単位のモードはなく、空白の正規化トグルもありません。そのため末尾の空白や改行コードの違いだけの行も変更として表示されます。 計算はクライアントサイドで実行されるため、オフラインでも動作します。アカウントなし、履歴なし、保持なし。ローカルの設定ファイルをテンプレートと比較したり、適用前にパッチを確認したり、2つのAPIレスポンスを確認したりできます。そのテキストのどれもサードパーティに届きません。
この記事で紹介するツール
よくある質問
コードには行ベースのdiffと単語ベースのdiff、どちらが良いですか?
ほとんどのコードレビュー作業では、コードは行で構造化されているため、行ベースのdiffが標準で最も読みやすいです。単語ベースのdiffは、1行のJSON値など行が長くて変更が小さい部分では役立つことがありますが、このツールは行単位でしか比較しません。そうした場合は、ハイライトされた行を手がかりに、その中の小さな違いを目視で確認してください。
HTTPSを使っていてもオンラインdiffツールはプライバシーリスクがあるのはなぜですか?
HTTPSは転送中のテキストを盗聴から保護しますが、サーバーに届いた後は保護しません。サービス事業者は貼り付けたコンテンツへのフルアクセスを持ち、それをログ記録、保存、共有できます。TLSはトランスポートセキュリティについてであり、受信者がデータをどう扱うかについてではありません。
text-diffツールは過去の比較履歴を保存しますか?
いいえ。このツールにはバックエンドがなく、ネットワークリクエストも行いません。タブを閉じるかリロードすると、テキストは消えます。アカウントなし、保存された履歴なし、サーバー側のログなし。