Как работает сравнение текстов
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)?
Когда два человека правят один и тот же оригинал, инструмент слияния сравнивает каждую версию с общим оригиналом. Изменения в разных местах объединяются автоматически, а изменения одних и тех же строк отмечаются как конфликты, которые должен разрешить человек.