Стаття
Порівняння фрагментів коду без завантаження
Кожного разу, коли ви вставляєте два файли в онлайн-інструмент diff, цей код покидає ваш комп'ютер. Конфігураційні файли, запити до бази даних, ключі API, заховані у фрагменті .env: все це потрапляє на сервер, яким ви не керуєте. Ця стаття пояснює, як працюють алгоритми diff, що означають параметри гранулярності на практиці та чому важливо тримати порівняння локальним.
Що обчислює diff
Інструмент diff бере два тексти та знаходить мінімальний набір змін, що перетворює один на інший. Основна ідея полягає в найдовшій спільній підпослідовності (LCS): найдовшій послідовності рядків (або токенів), що з'являється в обох текстах в однаковому порядку, навіть якщо не є суміжними. Все, що не входить до цієї спільної підпослідовності, є або додаванням у новій версії, або видаленням зі старої. Класичний алгоритм для цього запропонований Маєрсом (1986), який знаходить найкоротший сценарій редагування за час O((N+M)D), де N та M є довжинами двох текстів, а D є кількістю редагувань. На практиці більшість інструментів додають крок попередньої обробки для ігнорування однакових початкових і кінцевих рядків, зводячи задачу до зміненої ділянки. Результатом є патч: послідовність блоків, кожен з яких описує суміжний блок контекстних рядків, видалень та додавань. Це формат, що використовується Unix diff, Git та більшістю інструментів перегляду коду.

Гранулярність за рядками, словами та символами
Гранулярність diff визначає, що вважається одиницею порівняння. Рядковий diff є стандартним у більшості інструментів: кожен рядок розглядається як один токен. Він швидкий і виводить результат, який легко читається в контексті, але позначає весь рядок як змінений, навіть якщо відрізняється лише одне слово в ньому. Порівняння на рівні слів розбиває кожен рядок на слова перед запуском LCS. Це дає детальніше уявлення про те, що змінилося в рядку, що корисно для прози, значень конфігурації або JSON. Порівняння на рівні символів іде далі й може виділити один змінений символ всередині довгого ідентифікатора. Обробка пробілів додає шум. Рядок, що закінчується на CRLF, і той самий рядок, що закінчується на LF, відображатимуться як різні при строгому порівнянні байтів. Більшість інструментів пропонують прапорець для нормалізації кінців рядків перед порівнянням. Так само кінцеві пробіли, відступи табуляцією замість пробілів та порожні рядки можуть призводити до хибних різниць. Увімкнення нормалізації пробілів зазвичай є правильним вибором за замовчуванням при порівнянні коду з різних редакторів або операційних систем.
Ризик конфіденційності при використанні онлайн-інструментів diff
Онлайн-сервіси diff та pastebin зручні: відкрий URL, встав два фрагменти, отримай кольоровий вивід. Проблема в тому, що вставлений текст передається на сторонній сервер. Залежно від сервісу, цей текст може бути записаний у журнал, проіндексований, збережений на невизначений термін або переданий провайдерам аналітики. Це найбільш важливо, коли код містить конфіденційний матеріал. Жорстко закодовані облікові дані, внутрішні імена хостів, пропрієтарна бізнес-логіка або персональні дані можуть потрапити у вставку. Навіть без явних секретів структура внутрішнього коду може розкрити архітектурні рішення, які ви вважаєте за краще тримати в таємниці. Ризик не є гіпотетичним. Дослідники з безпеки неодноразово знаходили облікові дані та внутрішні токени у публічних вставках. Деякі сервіси зберігають вставки навіть після того, як користувач їх видаляє, оскільки копії існують у кешах або резервних копіях. Немає способу перевірити, що сторонній сервіс робить з текстом після його отримання. Єдиним надійним способом захисту є зберігання diff локально, тобто запуск його в інструменті, що ніколи не надсилає текст через мережу.

Практичне використання локального diff
Diff корисний не лише для перегляду коду. Кілька поширених випадків, коли локальний diff є корисним: Перегляд змін у документі або конфігураційному файлі перед фіксацією. Порівняння двох версій Dockerfile, конфігурації Nginx або маніфесту Kubernetes для точного розуміння того, що змінилося між розгортаннями. Перевірка відхилення конфігурації між середовищами. Якщо конфігурації production і staging мають бути ідентичними, крім імен хостів і секретів, diff відразу показує будь-яке ненавмисне відхилення. Порівняння відповідей API під час налагодження. Вставка двох JSON-корисних навантажень з REST або GraphQL API та запуск порівняння на рівні слів точно визначає додані поля, змінені значення або видалені ключі без ручного читання сотень рядків. Перегляд коду, згенерованого мовною моделлю, відносно базового рівня. Коли модель переписує функцію, рядковий diff показує, яка логіка змінилася, а яка залишилася такою ж, швидше, ніж читати обидві версії незалежно. В усіх цих випадках залучений текст може бути конфіденційним, і зберігати його поза стороннім сервером є розумним вибором.
Порівняння у браузері без завантаження
Інструмент text-diff на цьому сайті виконує всі обчислення diff у вашому браузері за допомогою JavaScript. Ви вставляєте два тексти в дві панелі, і diff відображається негайно, рядок за рядком, до 3000 рядків з кожного боку. Нічого не надсилається на сервер. Текст ніколи не покидає ваш пристрій. Реалізація використовує стандартний алгоритм на основі LCS, що працює з рядками: кожен рядок є токеном, і інструмент визначає, чи він незмінний, доданий чи видалений, знаходячи найдовшу спільну підпослідовність між двома версіями. Незмінні рядки відображаються без виділення, додані рядки зеленим, видалені рядки червоним, поряд із поточним підрахунком доданих і видалених рядків. Наразі немає режиму порівняння на рівні слів чи символів і немає перемикача нормалізації пробілів, тож рядок, що відрізняється лише кінцевими пробілами чи стилем закінчення рядка, все одно показується як змінений. Оскільки обчислення виконується на стороні клієнта, воно працює офлайн. Немає облікового запису, немає історії, немає збереження даних. Ви можете порівняти локальний конфігураційний файл із шаблоном, переглянути патч перед застосуванням або перевірити дві відповіді API без того, щоб будь-який із цих текстів потрапив до третьої сторони.
Інструменти з цієї статті
Поширені запитання
Що краще для коду: рядковий чи словесний diff?
Для більшості задач перегляду коду рядковий diff є стандартним і найлегшим для читання, оскільки код структурований рядками. Словесний diff міг би допомогти, коли рядки довгі і змінилася лише невелика частина, наприклад у однорядковому значенні JSON, але цей інструмент порівнює лише на рівні рядків; у такому випадку використовуйте виділений рядок як орієнтир і на око знайдіть меншу відмінність усередині нього.
Чому онлайн-інструменти diff становлять ризик для конфіденційності навіть при використанні HTTPS?
HTTPS захищає текст під час передачі від підслуховування, але не захищає його після того, як він досяг сервера. Оператор сервісу має повний доступ до вставленого вмісту і може записувати, зберігати або передавати його. TLS стосується безпеки передачі, а не того, що отримувач робить з даними.
Чи зберігає інструмент text-diff будь-яку історію минулих порівнянь?
Ні. Інструмент не має бекенду і не робить жодних мережевих запитів. Після закриття або перезавантаження вкладки текст зникає. Немає облікового запису, збереженої історії та серверних журналів.