Сравнение текстов онлайн: алгоритм LCS/Myers и 6 кейсов
Онлайн-инструмент text diff быстро отвечает на один вопрос: что именно изменилось между версией A и версией B? Вы вставляете два блока текста, инструмент запускает алгоритм поиска наибольшей общей подпоследовательности (LCS) и показывает side-by-side или унифицированное представление каждого добавления, удаления и правки. Обычно меньше чем за миллисекунду.
Это руководство для разработчиков на code review, SRE, сравнивающих срезы логов, юристов, ведущих редлайн контрактов, и редакторов, проверяющих правки. Внутри: алгоритмы (LCS, Myers, Patience), два стандартных представления, опции игнорирования, которые снимают 95 % жалоб «всё выглядит изменённым», случаи, когда лучше взять JSON diff, шесть готовых сценариев для копипасты и подводные камни, которые объясняются самим алгоритмом.
Хотите сразу сравнить два текста? Откройте Text Diff: инструмент работает целиком в браузере, без загрузки на сервер.
1. Что такое text diff?
Text diff — это минимальный набор вставок и удалений, который превращает один текст в другой, причём каждая строка помечается как добавленная, удалённая или неизменённая. Современные diff-инструменты делают второй проход на уровне слов или символов, поэтому правка в один символ подсвечивает только этот токен, а не всю строку целиком.
1.1 Почему посимвольного равенства (===) недостаточно
Вставьте одну строку в начало конфига из 200 строк, и наивное посимвольное сравнение сообщит, что каждый байт после точки вставки отличается. Текст не изменился, изменилось его положение. Алгоритм diff должен понять, что «следующие 199 строк остались теми же, просто сдвинулись на одну», и сообщить об одной-единственной вставке. Именно это даёт LCS, и именно поэтому git, GitHub и любой инструмент code review поставляются с ним.
1.2 Side-by-side и unified diff
Side-by-side помещает две версии в параллельные колонки и раскрашивает ячейки: зелёный для добавления, красный для удаления, жёлтый для модификации. Unified diff — более старый текстовый формат из GNU diff: одна колонка, маркеры - и +, три строки контекста вокруг каждого hunk. Одно и то же сравнение в двух представлениях. В разделе 4 разбирается, когда использовать каждое.
1.3 Где применяется text diff
Code review на GitHub и GitLab. Вывод локального git diff. Патчи, вставленные в Slack. Редлайн контрактов. Проверка переводов. CI snapshot-тесты, падающие с выводом +/-. Анализ таймлайна логов. Сравнение двух .env-файлов. Любая ситуация, где два блока текста нужно сопоставить построчно.
Откройте Text Diff, вставьте два текста и убедитесь во всём этом сами: каждое сравнение выполняется локально в вашем браузере.
2. Алгоритм внутри text diff (LCS + Myers + Patience)
2.1 Наибольшая общая подпоследовательность
Для двух последовательностей строк A и B наибольшая общая подпоследовательность (LCS) — это самый длинный список строк, которые встречаются в обеих в одном порядке, но не обязательно подряд. Если LCS известна, diff строится просто: строки A, которых нет в LCS, считаются удалёнными; строки B, которых нет в LCS, — добавленными; строки самой LCS остаются без изменений.
Классический LCS реализуется через таблицу динамического программирования размером N × M. Ячейка (i, j) хранит длину LCS первых i строк A и первых j строк B. Таблица заполняется слева направо, сверху вниз, затем выполняется обратный проход из правой нижней ячейки для восстановления edit script. Время и память O(N×M): нормально для двух файлов по тысяче строк, медленно для лога в сто тысяч строк.
2.2 Myers (1986)
Статья Юджина Майерса 1986 года «An O(ND) Difference Algorithm and Its Variations» переформулирует задачу как поиск кратчайшего пути в графе правок: узлы как позиции (i, j) в двух входах, горизонтальные переходы как удаления, вертикальные как вставки, диагональные как совпадения. Кратчайший путь и есть минимальный edit script.
Myers работает за O((N+M)D), где D — размер edit script. Когда два текста похожи (обычный случай для diff), D невелико и алгоритм по сути линеен. Это значение по умолчанию в git diff, GNU diff и движке PR-рендеринга GitHub. Для девяноста девяти процентов веб-ввода это правильный ответ.
2.3 Patience diff (Bram Cohen, 2005)
Patience diff использует другой подход: находит строки, которые встречаются ровно один раз в каждом входе (так называемые «уникальные якорные строки»), сопоставляет их и рекурсивно обрабатывает промежутки между якорями. Математика выглядит грязнее (худший случай по-прежнему плохой), но результат на коде читается намного лучше.
Почему? Myers минимизирует расстояние редактирования, что математически оптимально, но визуально ужасно, когда оптимальное выравнивание пересекает несвязанные скобки или пустые строки. Patience отказывается выравниваться по общему boilerplate (в каждом файле есть строки }, в каждом файле есть пустые строки), поэтому границы функций сохраняются. Bram Cohen придумал его для Bazaar; Git поставляет его как git diff --patience. Близкий алгоритм Histogram (git diff --histogram) немного быстрее при схожем качестве вывода.
Представьте две версии одного файла, где функция переехала. Myers может выровнять закрывающую скобку функции A с закрывающей скобкой функции B и доложить, что тела полностью разные. Patience «зацепится» за уникальные имена функций и покажет аккуратный move. Один и тот же вход, совершенно разное восприятие на review.
2.4 Сравнение алгоритмов
| Свойство | Myers (по умолчанию) | Patience | Histogram |
|---|---|---|---|
| Временная сложность | O((N+M)D) | ~O(N log N) в типичном случае | близко к Patience |
| Оптимальное edit distance | Да, кратчайший script | Нет, может быть длиннее | Нет, может быть длиннее |
| Естественность чтения на коде | Иногда неудачно выравнивает скобки и пустые строки | Отлично, якоря на уникальных строках | Отлично |
| Где используется | git по умолчанию, GNU diff, UI GitHub | git diff --patience, Bazaar | git diff --histogram |
| Когда подходит | Скорость и корректность на большинстве входов | Code review, diff рефакторингов | То же, что Patience, чуть быстрее |
2.5 Что делает этот инструмент
Text Diff использует классический LCS на динамическом программировании с двумя агрессивными оптимизациями: обрезка общего префикса и суффикса плюс второй проход LCS на уровне токенов для словесного diff внутри строки. Diff двух конфигов по две тысячи строк с одной изменённой строкой схлопывается до DP-таблицы 1×1 после обрезки и рендерится меньше чем за миллисекунду. Для типичного веб-ввода разница между Myers и DP незаметна: оба алгоритма завершаются быстрее, чем браузер успевает отрисовать результат.
3. Словесный diff внутри строки: почему правка в один символ подсвечивает всю строку
Вы меняете один идентификатор в строке, и вся строка загорается красным и зелёным. Баг? Нет, дизайн.
Diff сначала запускает LCS на уровне строк: «строка 14 заменена». Затем для каждой пары заменённых строк выполняется второй LCS на уровне токенов. Токены получаются разбиением по границам слов Unicode: последовательности букв и цифр остаются вместе, пробельные символы и знаки препинания становятся отдельными токенами. Второй LCS даёт минимальный edit script на уровне токенов внутри строки.
Рендерер рисует строку целиком в цвете подсветки, чтобы взгляд сразу её нашёл, а яркий фон накладывается только на изменённые токены. Неизменённые токены вокруг получают приглушённый вариант того же цвета: присутствуют, но визуально тихие. Взгляд приземляется ровно на правку.
Пример 1: переименование идентификатора. function getUser(id) превращается в function getUser(userId). Вся строка помечена как изменённая. Внутри строки яркую подсветку несут только id (зачёркнут красным) и userId (ярко-зелёный). Всё остальное приглушено.
Пример 2: изменение латентности в логе. POST /api/orders 201 88ms превращается в POST /api/orders 201 4200ms. Строка изменена. Внутри строки ярко горят только 88 и 4200. Путь, метод и status code остаются тусклыми, ровно то, что нужно при анализе таймлайна инцидента.
Когда изменилось слишком много токенов, словесная подсветка превращается в шум. Инструмент откатывается к парному представлению удаление + добавление: исходная строка показана как удалённая, новая как добавленная, без раскраски внутри строки. Порог примерно такой: «изменилось больше половины токенов».
Короче: построчный diff говорит, какая строка изменилась; словесный diff говорит, какие символы в этой строке несут изменение. Нажмите Sample в Text Diff, чтобы увидеть оба представления на одном и том же входе.
4. Side-by-side и unified diff: два представления, один diff
4.1 Представление side-by-side
Две колонки: оригинал слева, изменённая версия справа. Совпадающие строки выровнены по горизонтали. Добавленные строки появляются только в правой колонке с зелёным фоном; удалённые только в левой с красным фоном; пары изменённых строк стоят рядом с жёлтой полосой между ними и словесной подсветкой внутри.
Используйте side-by-side, когда diff будет читать человек: PR-review, обучение, демо, обсуждение правки контракта с нетехническим участником. Это представление для глаз.
Обратная сторона: оно не «переносится». Вы не вставите side-by-side в Slack и не дадите кому-то его применить. Его нельзя пропустить через patch. Для шаринга и применения нужен unified.
4.2 Формат unified diff
Unified diff — это plain-text-формат с пятидесятилетней историей, определённый GNU diff и стандартизованный в POSIX. Полный пример:
--- original
+++ modified
@@ -1,3 +1,4 @@
1. The service is provided as-is.
2. Either party may terminate with 30 days notice.
+2a. Termination notice must be in writing.
3. Disputes are resolved in California courts.
Первые две строки называют исходные файлы. Строка @@ -L,C +L,C @@ — заголовок hunk: -L,C означает «начиная с строки L оригинала, затронуто C строк»; +L,C делает то же самое для изменённой версии. Внутри hunk строки, начинающиеся с пробела, дают контекст (неизменённые), - означает удалено, + означает добавлено.
Три строки контекста сверху и снизу каждого изменения — значение GNU по умолчанию. Большинство инструментов позволяют изменить его флагом -U n: diff -U0 без контекста, diff -U10 для десяти строк. Заголовок hunk автоматически подстраивается под выбранное значение.
В Text Diff переключитесь на вкладку Unified, чтобы поменять представление, или нажмите Copy unified diff, чтобы положить патч в буфер обмена.
4.3 Где переносим unified diff
Unified diff путешествует. Это универсальная валюта текстового изменения.
| Назначение | Принимает unified diff? | Как |
|---|---|---|
GNU patch | Да | patch -p1 < diff.patch |
git apply | Да | git apply diff.patch |
| Комментарий PR-review на GitHub | Да (в блоке ```diff) | Отрисовывается в цвете |
| Комментарий MR на GitLab | Да | Тот же fenced-блок |
| PR на Bitbucket / Azure DevOps | Да | Тот же fenced-блок |
| Вставка в Slack / Discord | Частично | Отрисовывается как текст в code-блоке, без цвета |
| «Open Patch» в VS Code | Да | Применение через Source Control |
| Тело задачи в Jira / Linear | Частично | Работает в code-блоке, без кнопки apply |
Одни и те же девять строк текста ---/+++/@@ применяются через patch, через git apply, отрисовываются в трёх PR-платформах и переживают вставку в Slack. Ни один другой формат diff такого охвата не даёт.
4.4 Когда какое выбирать
Side-by-side для чтения, unified для шаринга и применения. Если diff читаете вы сами, колонки быстрее. Если на следующем шаге его потребит ревьюер, инструмент или команда patch, копируйте unified.
5. Опции игнорирования: пробелы, регистр, пустые строки, окончания строк
Большая часть жалоб «всё выглядит изменённым» — это шум. Четыре переключателя решают 95 % случаев.
- Игнорировать регистр сопоставляет
Aсa. Эквивалентgit diff -i. Подходит для сравнения переменных окружения, аудита стиля SQL-ключевых слов, везде, где принято писать то крупными, то мелкими буквами, но смысл идентичен. - Игнорировать все пробелы схлопывает каждый пробел, табуляцию и перевод строки до сравнения. Эквивалент
git diff -w. Лекарство от переформатирования tabs ↔ spaces, переразметки отступов и diff-шумов «мы перешли на Prettier», которые ломают счёт строк. Diff с игнором пробелов на таких изменениях обычно сокращается с 87 модификаций до 4. - Игнорировать концевые пробелы и табуляции удаляет только пробельные символы в конце строки. Эквивалент
git diff -b. Лекарство от CRLF-шума после копирования между Windows и Unix: концевые\rотфильтровываются, а содержимое сходится. - Игнорировать пустые строки убирает пустые строки перед сравнением. Лекарство от «я добавил один разрыв абзаца, и теперь параграф 12 выглядит совершенно иначе» в diff-ах прозы.
Конфиг на 200 строк, который рапортует о «87 модификациях», после Игнорировать все пробелы обычно опускается до «4 модификаций». Копирование Windows → Unix, помечающее все строки, с Игнорировать концевые пробелы падает до нуля. Каждая опция независима и сохраняется между сессиями.
CRLF и LF. Окончания строк в Windows: \r\n; в Unix: \n; в классическом Mac: \r. Откройте Windows-файл в Unix-редакторе, который не нормализует, и концевой \r останется. Каждая строка будет diff-иться как «содержимое совпадает, но в конце есть \r». Игнорировать концевые пробелы заглушает это без потери реальных правок.
Предупреждение. Опции игнорирования — обоюдоострое оружие. Включите Игнорировать регистр, и рефакторинг LOG.error → log.Error покажется идентичным. Включите Игнорировать все пробелы, и баг отступов в Python станет невидимым. Выбирайте переключатели под тот вопрос, который вы задаёте, и отключайте их, когда закончили.
6. Text diff, JSON diff и git diff: матрица решений
Text diff — это сопоставление по строкам и словам без понимания структуры. Это ровно то, что нужно для прозы, и ровно то, что не нужно для JSON.
6.1 Матрица решений
| Тип входа | Text diff | JSON diff | Git diff |
|---|---|---|---|
| Проза / Markdown / контракт | Лучший выбор | Не тот инструмент | Частично (работает только по отслеживаемым файлам) |
| Фрагмент кода (вставка одного файла) | Лучший выбор | Не тот инструмент | Частично (нужен репозиторий) |
| Код в репозитории (несколько файлов) | Частично | Не тот инструмент | Лучший выбор |
| JSON-ответ API | Не тот инструмент (ложные срабатывания на порядке ключей) | Лучший выбор | Не тот инструмент |
| YAML / TOML-конфиг | Частично (ложные срабатывания на порядке ключей) | Лучший выбор (после конвертации) | Частично |
| CSV построчно | Частично | Не тот инструмент | Не тот инструмент |
| Лог / heredoc | Лучший выбор | Не тот инструмент | Не тот инструмент |
| Бинарный файл | Не тот инструмент | Не тот инструмент | git diff --binary |
6.2 Когда text diff не тот инструмент
Три классические ошибки.
JSON с переупорядоченными ключами. {"a":1,"b":2} и {"b":2,"a":1} — это один и тот же JSON-документ. Text diff сообщит, что изменилась каждая строка, потому что строки действительно разные. Используйте JSON Diff: он понимает, что ключи JSON неупорядочены.
YAML-конфиги, прошедшие переформатирование. Поменяли одно значение, прогнали файл через форматировщик, и сместились отступы, порядок ключей и кавычки. Text diff сообщит о полной переписке. Сконвертируйте оба файла в JSON, а потом сравните через JSON Diff.
Многофайловые рефакторинги с переименованиями. Git отслеживает переименования, text diff нет. Если вы сравните два дерева, склеив файлы в один блоб, каждый межфайловый перенос покажется как удалено + добавлено. Используйте git diff (или git diff --find-renames=80%).
6.3 Когда text diff подходит идеально
Проза. Фрагменты кода, вставленные откуда угодно. Редлайны контрактов. Срезы логов. Проверка переводов, где сопоставляются предложения на естественном языке. .env-файлы, где порядок важен, потому что shell читает их сверху вниз. Всё, где смысл несут сами строки.
Подробный разбор того, как фильтровать шум в JSON-diff (timestamp-ы, request ID, автогенерированные UUID), читайте в статье Как игнорировать timestamp и ID при JSON diff.
7. Шесть реальных кейсов (с готовым вводом для копипасты)
7.1 Code review фрагмента: переименование функции
Вы делаете review PR. Автор переименовал id в userId и добавил guard clause. Вставьте обе версии:
// Original
function getUser(id) {
const u = db.users.find(x => x.id === id);
return u;
}
// Modified
function getUser(userId) {
if (!userId) return null;
const u = db.users.find(x => x.id === userId);
return u;
}
Diff показывает три изменённых строки и одну добавленную. Словесная подсветка отмечает каждый токен id → userId; новый guard clause появляется с зелёным фоном. Опции игнорирования выключены. Попробуйте в Text Diff и скопируйте unified-вывод как комментарий к review.
7.2 Редлайн контракта или политики: одна вставленная статья
Пятьдесят параграфов контракта, одна вставленная статья. Вставьте вчерашнюю версию слева, сегодняшнюю справа:
1. The service is provided as-is.
2. Either party may terminate with 30 days notice.
3. Disputes are resolved in California courts.
1. The service is provided as-is.
2. Either party may terminate with 30 days notice.
2a. Termination notice must be in writing.
3. Disputes are resolved in California courts.
Diff отрисовывает сорок девять неизменённых строк и одну добавленную (+2a. Termination notice must be in writing.). Экспортируйте unified diff как след legal review.
7.3 Расследование таймлайна логов
Вы подозреваете регрессию по латентности. Снимите срезы access-логов до и во время инцидента:
GET /api/users 200 14ms
POST /api/orders 201 88ms
GET /api/orders/42 200 21ms
GET /api/users 200 14ms
POST /api/orders 201 4200ms
GET /api/orders/42 500 21ms
Словесная подсветка вытаскивает 88 → 4200 (скачок латентности в 50 раз) и 200 → 500 (endpoint детализации заказа начал падать). Для более серьёзной работы с логами (выборка полей, группировка по endpoint, расчёт перцентилей) связывайте diff с Шпаргалкой по jq, если ваши логи в JSON.
7.4 Проверка переводов: сохранение плейсхолдеров
Вы наняли новое агентство переводов и хотите убедиться, что новый текст структурно соответствует старому. Вставьте старый перевод слева, новый справа. Включите Игнорировать концевые пробелы / табуляции, потому что переводчики систематически добавляют лишний пробел в конце строк.
Diff подтверждает, что каждый плейсхолдер {username}, {count} и %s стоит на своём месте; меняется только текст на естественном языке. Пропавший плейсхолдер появится как удалённый токен в словесном diff, пойман до релиза. Если нужно сравнить сами форматы плейсхолдеров, Шпаргалка Regex покрывает \{\w+\} и подобные конструкции. Попробуйте в Text Diff.
7.5 Аудит конфига или .env: production против staging
Сравните два .env-файла. Включите Игнорировать пустые строки, чтобы абзацная группировка не сбивала выравнивание секций. Diff покажет, какие ключи отличаются значением, какие существуют в одном окружении и отсутствуют в другом и где разошлись комментарии. Пять минут, которые экономят сессию отладки «в staging работает, в prod не работает».
7.6 Правки прозы или черновика
Редактор вернул черновик. Вставьте оригинал слева, отредактированную версию справа. Словесный diff покажет, какие предложения переписаны, какие не тронуты и какие абзацы добавлены. Принимайте или отклоняйте правки по одной, без Track Changes, без Word-файла, без проприетарных форматов.
8. Типичные ловушки и их симптоматическое чтение
Поведение алгоритма объясняет почти всю боль пользователя. Пять частых жалоб и их реальный смысл.
Ловушка 1: «После копирования Windows → Unix каждая строка красная». Симптом: каждая строка в diff помечена как изменённая, хотя содержимое выглядит идентично. Причина: концевые \r от окончаний CRLF. Решение: включить Игнорировать концевые пробелы / табуляции. Diff схлопнется до реальных изменений.
Ловушка 2: «Я вставил JSON, и 100 % строк отличаются». Симптом: два JSON-объекта, которые должны быть эквивалентны, показаны как полностью изменённые. Причина: переупорядочены ключи. Text diff считает порядок строк значимым, для JSON он не значим. Решение: для любого JSON-ввода используйте JSON Diff.
Ловушка 3: «Переформатирование tabs ↔ spaces взорвало diff». Симптом: 87 модификаций, и все они в отступах. Причина: форматировщик изменил начальные пробельные символы у каждой строки. Решение: Игнорировать все пробелы схлопнет шум и поднимет на поверхность реальные смысловые изменения.
Ловушка 4: «Diff говорит „идентичны”, но cmp не согласен». Симптом: diff сообщает об отсутствии различий, а побайтовое сравнение их находит. Причина: опция игнорирования, оставшаяся включённой с прошлой сессии, маскирует реальные изменения. Решение: откройте панель опций игнорирования, выключите каждый переключатель и пересравните.
Ловушка 5: «Короткая правка показывается как remove + add». Симптом: небольшое изменение выглядит как отдельная удалённая строка плюс отдельная добавленная вместо подсветки внутри строки. Причина: доля изменённых токенов перешла порог inline-режима, и рендерер откатился к парному представлению. Это дизайн, а не баг. Переключитесь в Unified, чтобы увидеть классическую пару -/+, которую ждут patch-инструменты.
9. Приватность, производительность и когда уходить в command line
Каждое сравнение в Text Diff выполняется на JavaScript внутри браузера. Никакой загрузки, никаких временных файлов, никаких серверных логов, никакой аналитики по вставленному тексту. Безопасно для проприетарного кода, внутренних контрактов, приватных логов: всего, что вы не вставили бы в сторонний сервис.
Практические лимиты: примерно 5000 строк или 1 МБ на сторону. Live-diff отключается выше 200 КБ суммарно и переключается на ручную кнопку Diff, чтобы набор текста не блокировал страницу. Выше 5000 строк ввод обрезается и показывается предупреждение. Лимиты существуют потому, что diff выполняется на основном потоке (без web worker), и накладные расходы на worker handoff и сериализацию на маленьком вводе превысили бы стоимость самого diff.
Когда ввод перерастает браузер, спускайтесь в command line:
# Unified diff between two files
diff -u a.txt b.txt
# Same, but using git's diff engine (Patience, Histogram, color)
git diff --no-index a.txt b.txt
git diff --no-index --patience a.txt b.txt
# Streaming diff viewer for huge files (Rust, side-by-side, syntax-aware)
delta a.txt b.txt
Переключайтесь в command line для многомегабайтных логов, бинарных файлов, многофайловых репозиторных diff, для синтаксис-осведомлённой раскраски как у delta и всюду, где нужно пайпить вывод diff в другой инструмент.
10. Unicode, CJK и RTL: заметки о международном text diff
Токенизатор разбивает по границам слов Unicode по трём категориям: серии слов (\p{L} буквы и \p{N} цифры), не-словесная пунктуация и пробельные символы. Каждая категория порождает собственные токены, поэтому hello, world! становится hello, ,, , world, !: пять токенов.
Для содержимого CJK (китайский, японский, корейский) каждый иероглиф или знак каны — отдельный токен. Поменяйте один символ в китайском предложении, и подсветку внутри строки понесёт только этот символ, остальная часть строки останется приглушённой. Структура на уровне абзаца по-прежнему построчная, поэтому переписка предложения, добавляющая разрыв строки, отобразится как правка на уровне строки, а не на уровне токенов.
Для RTL-языков (арабский, иврит) diff использует логические CSS-направления (ms-, me- вместо ml-, mr-). В RTL-локалях полоса и колонки строк естественно зеркалятся; внутри каждой ячейки diff направление текста следует содержимому, поэтому арабские строки рендерятся справа налево, а маркеры + и - остаются на start-полосе.
Нормализация окончаний строк распознаёт \r\n (Windows), \n (Unix) и одиночный \r (старый Mac OS вплоть до версии 9). Все три варианта разбиваются как отдельные строки, поэтому файл, сконвертированный с одной платформы на другую, не схлопывается в одну мега-строку.
11. FAQ
Как работает онлайн text diff?
Text diff разбивает оба входа на строки, запускает алгоритм LCS (обычно Myers за O((N+M)D)), чтобы найти минимальный набор вставок и удалений, после чего подсвечивает добавленные (зелёный), удалённые (красный) и неизменённые (серый) строки. Второй LCS на уровне токенов отмечает изменённые слова внутри каждой изменённой строки. Text Diff выполняет всё сравнение локально в вашем браузере.
Чем text diff отличается от JSON diff?
Text diff сравнивает построчно: идеален для прозы, кода, логов и контрактов. JSON Diff понимает модель данных JSON: порядок ключей не важен, типы строгие (1 ≠ "1"), массивы могут сопоставляться по ключу. Вставьте JSON в text diff, и переупорядоченные ключи или пробельные символы всплывут как изменения, которые JSON Diff игнорирует. Используйте text diff для неструктурированного контента, JSON Diff для ответов API и конфигов.
Почему diff показывает целые строки изменёнными, если я поменял только одно слово?
На самом деле нет: строка подсвечена, потому что в ней что-то изменилось, но внутри подсветки яркий фон несут только изменённые токены (зелёный для добавленных, красное зачёркивание для удалённых). Это словесный diff внутри строки: контекст строки остаётся читаемым, а взгляд приземляется на саму правку. Когда в строке изменилось слишком много для словесной подсветки, diff откатывается к отдельной паре удаление + добавление, чтобы структура осталась чистой.
Как игнорировать пробелы, регистр или пустые строки в diff?
Откройте панель опций игнорирования. Игнорировать регистр приравнивает A и a. Игнорировать все пробелы схлопывает каждый пробел, табуляцию и перевод строки, эквивалент git diff -w. Игнорировать концевые пробелы и табуляции зеркалит git diff -b и заглушает CRLF-шум. Игнорировать пустые строки убирает пустые строки, чтобы изменение разбивки на абзацы не ломало выравнивание diff. Каждая опция независима и сохраняется между сессиями.
Что такое формат unified diff?
Unified diff — это текстовый формат ---/+++/@@ -L,C +L,C @@, представленный GNU diff в конце 1980-х и используемый git, GitHub, GitLab и Unix-командой patch. В каждом hunk показываются три строки контекста вокруг изменения, с - для удалённых и + для добавленных. Скопируйте unified-вывод в комментарий PR, вставьте в git apply или выполните patch -p1 < diff.patch, и патч применится чисто.
Myers и Patience: какой алгоритм diff лучше для code review?
Myers — значение по умолчанию в git diff и GNU diff: быстрый и математически минимальный, но иногда выравнивает несвязанные пустые строки или закрывающие скобки и порождает diff, которые «странно читаются». Patience (Bram Cohen, 2005) якорится на строках, встречающихся ровно один раз в каждом входе, и рекурсивно обрабатывает промежутки между якорями, поэтому границы функций сохраняются. Используйте git diff --patience (или --histogram для похожего результата, чуть быстрее), когда делаете review рефакторингов.
Отправляется ли вставленный текст на сервер?
Нет. Каждое сравнение в Text Diff выполняется локально на JavaScript внутри браузера. Ваш текст никогда не загружается, не логируется, не сохраняется на диск и не отправляется третьим лицам. В localStorage сохраняются только UI-настройки (режим представления и переключатели опций игнорирования), чтобы страница помнила их при следующем визите. Сам текст не сохраняется никогда. Проверьте через DevTools → Network: при нажатии Diff не уходит ни одного запроса.
Насколько большими могут быть входы?
Практический лимит около 5000 строк или 1 МБ на сторону. Live-diff отключается выше 200 КБ суммарно и переключается на ручную кнопку Diff. Выше 5000 строк ввод обрезается с предупреждением. Для многомегабайтных файлов переключайтесь на diff -u a.txt b.txt, git diff --no-index a.txt b.txt или delta: они работают потоково и справляются с гигабайтами.