Перейти к содержимому
LeedyBox
Поддержать

Как работает сравнение текстов

Diff отвечает на один вопрос: что нужно изменить, чтобы превратить первый текст во второй? В этом руководстве объясняется, как инструменты diff находят ответ, как читать их результат и как подготовить две версии, чтобы в результате были видны важные изменения, а не шум.

Что показывает diff

Большинство инструментов diff, включая сравнение текста LeedyBox, сравнивают тексты построчно. Каждая строка результата относится к одному из трёх видов: неизменённая (есть в обеих версиях), удалённая (только в оригинале) или добавленная (только в новой версии). Отдельного вида «изменённая» нет, поэтому строка, в которой поменяли одно слово, появляется дважды — как удалённая и как добавленная:

  Dear customer,
- Your order ships on Monday.
+ Your order ships on Tuesday.
  Kind regards

Метки следуют давней традиции: - для удалённых, + для добавленных и пробел для неизменённых строк. Цвета, обычно красный и зелёный, дублируют ту же информацию.

Как сопоставляются строки

Инструмент diff ищет самую длинную последовательность строк, которые встречаются в обоих текстах в одном порядке, — наибольшую общую подпоследовательность. Эти строки остаются неизменёнными, всё остальное помечается как удалённое или добавленное. Если оригинал — A, B, C, D, а новый текст — A, C, B, D, наибольшая общая последовательность состоит из трёх строк, например A, B, D, поэтому C показывается как перемещённая: удалённая в одном месте и добавленная в другом.

Часто существует несколько одинаково длинных ответов, и инструменты выбирают между ними по-разному. Поэтому одна и та же пара файлов может давать немного разные диффы в двух программах. Git по умолчанию использует алгоритм Майерса и предлагает альтернативы patience и histogram, которые часто дают более читаемый результат для кода с множеством строк из одной закрывающей скобки.

Поиск наибольшей общей последовательности требует работы, растущей пропорционально произведению числа строк одного текста на число строк другого. Инструмент LeedyBox сначала откладывает одинаковые строки в начале и в конце, сравнивает остальное и останавливается с сообщением, если это произведение превышает 4 000 000, например при примерно 2 000 против 2 000 различающихся строк.

Как читать унифицированные диффы Git и код-ревью

Системы контроля версий показывают только изменённые части файла в формате унифицированного диффа:

--- a/config.yml
+++ b/config.yml
@@ -12,4 +12,5 @@
 server:
-  port: 8080
+  port: 8081
+  timeout: 30
 database:

Строки --- и +++ называют старый и новый файл. Заголовок блока @@ -12,4 +12,5 @@ означает: в старом файле блок начинается со строки 12 и занимает 4 строки, в новом — начинается со строки 12 и занимает 5 строк. Несколько неизменённых строк вокруг каждого изменения, по умолчанию три, дают контекст. У инструмента, показывающего весь текст, как у LeedyBox, нет заголовков блоков, потому что видна каждая строка; по той же причине его результат нельзя применить как патч.

Как подготовить тексты к полезному сравнению

Diff сравнивает символы, а не смысл. Мелкие невидимые различия делают строки разными и могут скрыть настоящие изменения:

  • Пробелы и табуляции в конце строк или табуляции в одной версии и пробелы в другой. Удалите концевые пробелы и используйте в обеих одинаковые отступы.
  • Невидимые символы, например неразрывный пробел или пробел нулевой ширины, — частые гости в тексте, скопированном с веб-страниц и из текстовых редакторов.
  • Формы Юникода. Буква с диакритикой, например é, может храниться как один символ или как e плюс комбинируемый знак. Текст из имён файлов macOS или некоторых PDF часто использует вторую форму.
  • Типографские кавычки и тире. Текстовые редакторы заменяют " на « » или “ ”, а - на –, поэтому вставленная копия больше не совпадает с исходным простым текстом.
  • Концы строк. Windows завершает строки символами CR LF, а macOS и Linux — LF. Браузеры превращают каждый перенос строки в текстовом поле в LF, поэтому в инструменте LeedyBox это различие не видно, но оно видно в инструментах, сравнивающих файлы напрямую.
  • Форматирование данных и кода. Заново выровненный JSON или ключи в другом порядке делают почти каждую строку другой. Сначала отформатируйте обе версии одинаково, например с отсортированными ключами и одинаковыми отступами.

Сравнение обычных текстов

В обычных документах целый абзац часто является одной длинной строкой, поэтому одно изменённое слово помечает весь абзац как удалённый и добавленный. Помогают две привычки. Перед сравнением поставьте каждое предложение на отдельную строку, чтобы выделялось только изменённое. Или используйте инструмент, сравнивающий слова внутри строк, например git diff --word-diff или режим рецензирования в текстовых редакторах.

У текста, скопированного из PDF, своя ловушка: строки разрываются там, где их разорвала вёрстка страницы, а слова могут быть перенесены с дефисом в конце строки. Прежде чем сравнивать абзац с исходным документом, снова соедините его строки.

Чего не скажет построчный diff

  • Перемещения. Абзац, перенесённый в другое место, выглядит удалённым в одном месте и добавленным в другом. Некоторые инструменты, например git с --color-moved, отмечают перемещённые блоки отдельно.
  • Смысл. Два текста, говорящие одно и то же разными словами, полностью различаются, а изменение в один символ, например пропущенное «not», выглядит мелким, но может перевернуть смысл фразы.
  • Двоичное содержимое. Документы Word, PDF и изображения — не простой текст. Сначала извлеките текст или используйте функцию сравнения программы, в которой они созданы.

Конфиденциальность при сравнении документов

Договоры, файлы конфигурации и журналы часто содержат имена, ключи или пароли. Некоторые онлайн-сервисы сравнения сохраняют вставленный текст на своих серверах, иногда под общедоступной ссылкой. Сравнение текста LeedyBox работает в вашем браузере и не отправляет и не сохраняет текст, но всё равно стоит удалить секреты, прежде чем вставлять куда-либо файл конфигурации.

Частые вопросы

Почему весь абзац помечен как изменённый, если я поправил одно слово?

Абзац — это одна строка, а построчные диффы сравнивают строки целиком. Перед сравнением разбейте текст на предложения или короткие строки или используйте сравнение по словам.

Можно ли игнорировать различия в пробелах?

Инструмент LeedyBox сравнивает строки точно. Сначала приведите оба текста в порядок, например удалите концевые пробелы и замените табуляции пробелами; для файлов git предлагает параметры вроде --ignore-space-change.

Как сравнить два документа Word?

В Word есть встроенная функция сравнения, которая показывает и изменения форматирования. Чтобы сравнить только формулировки, скопируйте текст обоих документов в инструмент сравнения текста.

Что такое трёхстороннее слияние (three-way merge)?

Когда два человека правят один и тот же оригинал, инструмент слияния сравнивает каждую версию с общим оригиналом. Изменения в разных местах объединяются автоматически, а изменения одних и тех же строк отмечаются как конфликты, которые должен разрешить человек.