Без загрузки, 100% локально, без аккаунта

Статья

Сравнение фрагментов кода без их загрузки

Каждый раз, когда вы вставляете два файла в онлайн-инструмент для сравнения, этот код покидает ваш компьютер. Файлы конфигурации, запросы к базам данных, ключи API, скрытые во фрагменте .env, всё это попадает на сервер, который вы не контролируете. В этой статье рассматривается, как работают алгоритмы сравнения, что означают параметры детализации на практике и почему важно сохранять сравнение локальным.

Что вычисляет инструмент сравнения

Инструмент сравнения берёт два текста и находит минимальный набор изменений, который преобразует один в другой. Основная идея, наибольшая общая подпоследовательность (LCS): наидлиннейшая последовательность строк (или токенов), которая встречается в обоих текстах в том же порядке, даже если они не смежны. Всё, что не входит в эту общую подпоследовательность, является либо добавлением в новой версии, либо удалением из старой. Классический алгоритм для этого разработан Майерсом (1986) и находит кратчайший скрипт редактирования за время O((N+M)D), где N и M, длины двух текстов, а D, количество правок. На практике большинство инструментов добавляют шаг предварительной обработки для игнорирования общих начальных и конечных строк, сводя задачу к изменённой области. Результатом является патч: последовательность фрагментов, каждый из которых описывает непрерывный блок контекстных строк, удалений и добавлений. Это формат, используемый Unix diff, Git и большинством инструментов для проверки кода.

Диаграмма, показывающая два текстовых ввода, выровненных по наибольшей общей подпоследовательности, с соединёнными совпадающими строками и строками, помеченными как добавления или удаления

Детализация по строкам, словам и символам

Детализация сравнения определяет, что считается единицей сравнения. Построчное сравнение является стандартным в большинстве инструментов: каждая строка рассматривается как один токен. Это быстро и даёт результат, который легко читать в контексте, но отмечает всю строку как изменённую, даже если изменилось только одно слово в ней. Пословное сравнение разбивает каждую строку на слова перед выполнением LCS. Это даёт более детальную картину того, что изменилось внутри строки, что полезно для прозы, значений конфигурации или JSON. Посимвольное сравнение идёт ещё дальше и может выделить один изменённый символ внутри длинного идентификатора. Обработка пробелов добавляет шум. Строка, заканчивающаяся на CRLF, и та же строка, заканчивающаяся на LF, будут показаны как разные при строгом побайтовом сравнении. Большинство инструментов предлагают флаг для нормализации окончаний строк перед сравнением. Аналогично, конечные пробелы, отступы табуляцией против пробелов и пустые строки могут давать лишний вывод сравнения. Включение нормализации пробелов обычно является правильным стандартным выбором при сравнении кода из разных редакторов или операционных систем.

Угроза конфиденциальности при использовании онлайн-инструментов для сравнения

Онлайн-сервисы для сравнения и вставки текста удобны: откройте URL, вставьте два фрагмента и получите цветной вывод. Проблема в том, что вставляемый текст передаётся на сторонний сервер. В зависимости от сервиса этот текст может быть записан в журнал, проиндексирован, сохранён на неопределённый срок или передан аналитическим провайдерам. Это важнее всего, когда код содержит конфиденциальные данные. Жёстко закодированные учётные данные, внутренние имена хостов, проприетарная бизнес-логика или данные, позволяющие идентифицировать личность, могут оказаться в вставке. Даже без явных секретов структура внутреннего кода может раскрыть архитектурные решения, которые вы предпочли бы держать в тайне. Этот риск не гипотетический. Исследователи безопасности неоднократно находили учётные данные и внутренние токены в публичных вставках. Некоторые сервисы сохраняют вставки даже после того, как пользователь их удалил, поскольку копии существуют в кэшах или резервных копиях. Нет способа проверить, что удалённый сервис делает с текстом, как только он туда попадает. Единственная надёжная мера защиты, держать сравнение локальным, а значит запускать его в инструменте, который никогда не отправляет текст по сети.

Снимок экрана панели сети браузера, показывающий ноль исходящих запросов, пока два фрагмента кода сравниваются в инструменте text-diff

Практические случаи использования локального сравнения

Сравнение нужно не только для проверки кода. Несколько распространённых случаев, когда локальное сравнение полезно: Проверка правок в документе или файле конфигурации перед фиксацией. Сравнение двух версий Dockerfile, конфигурации Nginx или манифеста Kubernetes, чтобы точно понять, что изменилось между развёртываниями. Проверка расхождения конфигурации между средами. Если конфигурации продуктивной и тестовой сред должны быть идентичны, кроме имён хостов и секретов, сравнение сразу покажет любые непреднамеренные расхождения. Сравнение ответов API при отладке. Вставка двух полезных нагрузок JSON из REST или GraphQL API и выполнение пословного сравнения точно указывает на добавленные поля, изменённые значения или удалённые ключи без ручного просмотра сотен строк. Проверка кода, сгенерированного языковыми моделями, относительно базового варианта. Когда модель переписывает функцию, построчное сравнение показывает, какая логика изменилась, а какая осталась прежней, быстрее, чем независимое чтение обеих версий. Во всех этих случаях задействованный текст может быть конфиденциальным, и держать его подальше от удалённого сервера, очевидный выбор.

Работа в браузере без загрузки файлов

Инструмент text-diff на этом сайте выполняет всё вычисление сравнения в вашем браузере с использованием JavaScript. Вы вставляете два текста в две панели, и сравнение отображается немедленно, построчно, до 3000 строк с каждой стороны. Ничего не отправляется на сервер. Текст никогда не покидает ваше устройство. Реализация использует стандартный алгоритм на основе LCS, работающий со строками: каждая строка является токеном, и инструмент определяет, осталась ли она неизменной, добавлена или удалена, находя наибольшую общую подпоследовательность между двумя версиями. Неизменённые строки отображаются без подсветки, добавленные строки зелёным, удалённые красным, рядом со счётчиком добавлений и удалений. Сегодня нет режима сравнения по словам или по символам и нет переключателя нормализации пробелов, поэтому строка, отличающаяся только завершающими пробелами или стилем окончания строки, всё равно будет показана как изменённая. Поскольку вычисление выполняется на стороне клиента, оно работает в офлайн-режиме. Нет аккаунта, нет истории, нет хранения данных. Вы можете сравнить локальный файл конфигурации с шаблоном, проверить патч перед его применением или сопоставить два ответа API без того, чтобы какой-либо из этих текстов попал к третьей стороне.

Инструменты из этой статьи

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

Что лучше для кода: построчное или пословное сравнение?

Для большинства задач проверки кода построчное сравнение является стандартным и наиболее удобным для чтения, поскольку код структурирован по строкам. Пословное сравнение могло бы помочь, когда строки длинные и изменилась только небольшая часть, например в однострочном значении JSON, но этот инструмент сравнивает только на уровне строк: в таком случае используйте подсвеченную строку как указатель и найдите меньшее отличие внутри неё на глаз.

Почему онлайн-инструменты для сравнения представляют угрозу конфиденциальности, даже если используют HTTPS?

HTTPS защищает текст при передаче от перехвата, но не защищает его после того, как он достиг сервера. Оператор сервиса имеет полный доступ к вставленному содержимому и может записывать, хранить или передавать его. TLS обеспечивает безопасность транспортировки, но не определяет, что получатель делает с данными.

Хранит ли инструмент text-diff историю прошлых сравнений?

Нет. Инструмент не имеет серверной части и не выполняет сетевых запросов. После закрытия или перезагрузки вкладки текст исчезает. Нет аккаунта, нет сохранённой истории и нет журналов на стороне сервера.