ToolDeck

テキスト差分ツール

2つのテキストを並べて比較し、行ごとの差分をハイライト表示

サンプルを試す

テキスト A

テキスト B

ローカルで実行 · シークレットの貼り付けも安全
ローカルで実行 · シークレットの貼り付けも安全

テキスト差分とは?

テキスト差分(diff)とは、2つのテキストブロックを比較し、追加・削除・変更なしの行を特定した結果です。この概念は、1974年にVersion 5 Unixの一部として初めてリリースされたUnixの diff ユーティリティに由来しています。現在、テキスト差分はGitなどのバージョン管理システムの基盤となっており、各コミットはファイルの完全なコピーではなくdiffを保存しています。

diff アルゴリズムは、2つの行シーケンス間の最長共通部分列(LCS)を見つけます。LCSに含まれる行は「変更なし」としてマークされます。元のテキストにあってLCSにない行は「削除」としてマークされます。変更後のテキストにあってLCSにない行は「追加」としてマークされます。結果は、一方のテキストをもう一方に変換するために必要な最小限の変更セットです。

diff の出力にはいくつかの形式があります。unified diff(git diff のデフォルト)は削除行にマイナス記号、追加行にプラス記号を付けます。サイドバイサイド diff は両テキストを並列カラムに配置します。このツールは行ごとの比較とカラーコード出力を使用します:追加は緑、削除は赤、変更なしはニュートラルです。変更なしの行はデフォルトでプレフィックスなしで表示されますが、変更箇所のみに集中するために非表示にできます。

オンラインテキスト差分ツールを使う理由

ターミナルでテキストを比較するには diff ユーティリティのインストールとコマンドラインフラグの操作が必要です。ブラウザベースの diff ツールはその手間を完全に排除します。

即座に比較
2つのテキストブロックを貼り付けるだけで、差分が即座にハイライト表示されます。ファイル作成不要、コマンド暗記不要、出力の解析不要。
🔒
プライバシー優先の処理
すべての比較はJavaScriptを使用してブラウザ内で行われます。テキストがデバイスを離れることはなく、設定ファイル、認証情報、プロプライエタリコードの差分を取る際に重要です。
📋
すぐにコピーできる出力
diff 出力は unified diff 形式に合致した標準的な + / - プレフィックスを使用します。結果をコミットメッセージ、コードレビューコメント、バグレポートに直接コピーできます。
🌐
ログイン・インストール不要
ブラウザがあればどのデバイスでも動作します。アカウント作成、拡張機能、デスクトップアプリは不要。ページを開いてすぐに比較を開始できます。

テキスト差分のユースケース

フロントエンド開発
ビルドステップの前後でminified CSSやHTML出力を比較し、生成されたマークアップやスタイルの意図しない変更を検出します。
バックエンドエンジニアリング
環境間(ステージング vs 本番)でAPI レスポンスの差分を取り、デプロイメントによる予期しないデータ変更がないことを確認します。
DevOps & インフラ
Kubernetesマニフェスト、Terraformプラン、Nginx設定を、本番クラスターやサーバーに適用する前に比較します。
QA & テスト
テスト出力を保存済みスナップショットファイルと差分を取ることで、期待するベースラインと一致しているか確認します。
データエンジニアリング
データベースマイグレーション間でCSVヘッダーやSQLスキーマ定義を比較し、カラムの追加やリネームが正しく行われたか確認します。
学習 & 課題
自分の解答を参考実装と行ごとに比較し、ロジックが期待するアプローチとどこで異なるかを見つけます。

diff 出力形式の比較

diff ツールはいくつかの形式で出力を生成します。以下の表は最も一般的な形式、それを生成するツール、各形式が有用な場面をまとめています。

形式ツール / ソース説明
Unified diffdiff -u / git diffPrefixes lines with + / - / space; includes @@ hunk headers
Side-by-sidediff -y / sdiffTwo columns, changed lines aligned horizontally
Context diffdiff -cShows changed lines with surrounding context, marked with ! / + / -
HTML diffPython difflibColor-coded HTML table with inline change highlights
JSON PatchRFC 6902Array of add/remove/replace operations on a JSON document

行 diff の仕組み:LCSアルゴリズム

このツールを含むほとんどの行 diff ツールは、最長共通部分列(LCS)アルゴリズムを使用します。LCS は、連続している必要はなく、同じ相対順序で両テキストに現れる行の最大セットを見つけます。LCS にない行が実際の差分です。

標準LCSアルゴリズムは動的計画法を使用し、O(m x n) 時間で実行されます(m と n は2つのテキストの行数)。大きなファイルでは、Myersの diff アルゴリズム(Gitが使用)などの最適化バリアントがこれを O(n + d^2) に削減します(d は差分の数)。ほとんどの行が共通の場合に高速です。

1. DPテーブルの構築
(m+1) x (n+1) の行列を作成します。各行ペアに対して、これまでに見つかった最長共通部分列の長さを格納します。等しい行は対角値を1増やします。
2. バックトラック
行列の右下隅から (0,0) まで逆方向に進みます。等しい行での対角移動は「変更なし」エントリを生成します。水平または垂直移動は「追加」または「削除」エントリを生成します。
3. 出力のレンダリング
各エントリを表示行にマッピングします:変更なしの行はプレフィックスなし、追加行は +、削除行は - です。視覚的な明確さのためにカラーコードを適用します。

コード例

JavaScript、Python、Go、コマンドラインでの行ごとのテキスト比較の実装例。各例は unified-style の diff 出力を生成します。

JavaScript
// Line-by-line diff using the LCS algorithm
function diffLines(a, b) {
  const linesA = a.split('\n')
  const linesB = b.split('\n')

  // Build LCS table
  const m = linesA.length, n = linesB.length
  const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0))
  for (let i = 1; i <= m; i++)
    for (let j = 1; j <= n; j++)
      dp[i][j] = linesA[i-1] === linesB[j-1]
        ? dp[i-1][j-1] + 1
        : Math.max(dp[i-1][j], dp[i][j-1])

  // Backtrack to produce diff
  const result = []
  let i = m, j = n
  while (i > 0 || j > 0) {
    if (i > 0 && j > 0 && linesA[i-1] === linesB[j-1]) {
      result.unshift({ type: 'equal', text: linesA[i-1] }); i--; j--
    } else if (j > 0 && (i === 0 || dp[i][j-1] >= dp[i-1][j])) {
      result.unshift({ type: 'add', text: linesB[j-1] }); j--
    } else {
      result.unshift({ type: 'remove', text: linesA[i-1] }); i--
    }
  }
  return result
}

const diff = diffLines("alpha\nbeta\ngamma", "alpha\nbeta changed\ngamma\ndelta")
// → [
//   { type: 'equal',  text: 'alpha' },
//   { type: 'remove', text: 'beta' },
//   { type: 'add',    text: 'beta changed' },
//   { type: 'equal',  text: 'gamma' },
//   { type: 'add',    text: 'delta' }
// ]
Python
import difflib

text_a = """alpha
beta
gamma""".splitlines()

text_b = """alpha
beta changed
gamma
delta""".splitlines()

# Unified diff (same format as git diff)
for line in difflib.unified_diff(text_a, text_b, fromfile='a.txt', tofile='b.txt', lineterm=''):
    print(line)
# --- a.txt
# +++ b.txt
# @@ -1,3 +1,4 @@
#  alpha
# -beta
# +beta changed
#  gamma
# +delta

# HTML side-by-side diff
d = difflib.HtmlDiff()
html = d.make_file(text_a, text_b, fromdesc='Original', todesc='Modified')
Go
package main

import (
	"fmt"
	"strings"
)

// Minimal LCS-based line diff
func diffLines(a, b string) {
	la := strings.Split(a, "\n")
	lb := strings.Split(b, "\n")
	m, n := len(la), len(lb)

	dp := make([][]int, m+1)
	for i := range dp {
		dp[i] = make([]int, n+1)
	}
	for i := 1; i <= m; i++ {
		for j := 1; j <= n; j++ {
			if la[i-1] == lb[j-1] {
				dp[i][j] = dp[i-1][j-1] + 1
			} else if dp[i-1][j] >= dp[i][j-1] {
				dp[i][j] = dp[i-1][j]
			} else {
				dp[i][j] = dp[i][j-1]
			}
		}
	}

	var result []string
	i, j := m, n
	for i > 0 || j > 0 {
		if i > 0 && j > 0 && la[i-1] == lb[j-1] {
			result = append([]string{" " + la[i-1]}, result...)
			i--; j--
		} else if j > 0 && (i == 0 || dp[i][j-1] >= dp[i-1][j]) {
			result = append([]string{"+" + lb[j-1]}, result...)
			j--
		} else {
			result = append([]string{"-" + la[i-1]}, result...)
			i--
		}
	}

	for _, line := range result {
		fmt.Println(line)
	}
}

// Output:
//  alpha
// -beta
// +beta changed
//  gamma
// +delta
CLI (diff / git)
# Compare two files with unified diff (3 lines of context)
diff -u original.txt modified.txt

# Git diff between working tree and last commit
git diff HEAD -- file.txt

# Git diff between two branches
git diff main..feature -- src/

# Side-by-side diff in the terminal
diff -y --width=120 original.txt modified.txt

# Color-coded diff (requires colordiff)
diff -u original.txt modified.txt | colordiff

よくある質問

行 diff と文字 diff の違いは何ですか?
行 diff はテキストを行ごとに比較します。行の任意の文字が変更されると、その行全体が削除としてマークされ、新バージョンが追加としてマークされます。文字 diff(またはワード diff)はより細かい粒度で動作し、行内で変更された特定の文字や単語をマークします。行 diff はコードレビューの標準です。文字 diff は文章編集においてより有用です。
git diff は内部的にどのように動作しますか?
Git はデフォルトでMyersの diff アルゴリズムを使用し、2つのファイル間の最短編集スクリプト(挿入と削除の最小数)を見つけます。Git は行番号を示す @@ ハンクヘッダー付きの unified diff 形式で結果を格納します。git diff を実行すると、Git は明示的に HEAD を渡さない限り、作業ツリーをインデックス(ステージングエリア)と比較します(最後のコミットではありません)。
テキスト差分ツールでバイナリファイルを比較できますか?
いいえ。テキスト差分ツールは改行文字で入力を分割し、文字列を比較します。バイナリファイルには任意のバイトシーケンスが含まれており、意味のない行分割が生成されます。バイナリ比較には、hexdiff ツールかファイルレベルのチェックサム比較(両ファイルに sha256sum)を使用してください。
このツールを使用するとデータがサーバーに送信されますか?
いいえ。このツールはブラウザ内で完全に実行されます。diff の計算はクライアントサイドで実行されるJavaScript LCS実装を使用します。テキストコンテンツを含むネットワークリクエストは行われません。ツールを使用中にブラウザのネットワークタブを開いて確認できます。
unified diff 形式とは何ですか?
unified diff は diff -u と git diff が使用する出力形式です。変更行を - (削除)と + (追加)プレフィックスで表示し、両ファイルの行番号範囲を指定する @@ ヘッダーが先行します。コンテキスト行(変更なし)はスペースプレフィックスを持ちます。unified diff はパッチ、プルリクエスト、コードレビューツールで最も一般的な形式です。
大量の差分がある大きなファイルを比較するにはどうすればよいですか?
数千行のファイルの場合、ブラウザベースのツールは動作しますが、LCSアルゴリズムが二乗スケールするため遅くなる可能性があります。非常に大きな差分には、最適化されたC実装を使用して出力をストリーミングできる diff や git diff などのコマンドラインツールの方が高速です。また、変更なしの行をフィルタリング(このツールで「変更なしの行を表示」をオフに)して変更箇所だけに集中することもできます。
三方向マージ diff とは何ですか?
三方向マージは、共通の祖先(ベース)に対してファイルの2つの変更バージョンを比較します。Git はこれを git merge と git rebase で使用します。ベースに対して各ブランチで行われた変更を特定し、それらを結合します。両ブランチが同じ行を変更した場合、Git はマージコンフリクトを報告します。三方向マージには3つの入力が必要ですが、標準の diff は2つのみ必要です。