Skip to content
Powrót do bloga
Poradniki

Text Diff online: porównanie dwóch tekstów (LCS/Myers + 6 przypadków)

Porównaj dwa teksty online — widok side-by-side i unified diff, algorytm LCS/Myers, kiedy wybrać text czy JSON diff oraz 6 przypadków code review.

14 min czytania

Text Diff online: porównanie dwóch tekstów (LCS/Myers + 6 przypadków)

Narzędzie do porównywania tekstów online odpowiada na jedno pytanie: co tak naprawdę zmieniło się między wersją A a wersją B? Wystarczy wkleić dwa bloki tekstu, narzędzie uruchamia algorytm Longest Common Subsequence i pokazuje widok side-by-side lub unified diff z każdą wstawką, każdym usunięciem i każdą edycją. Zwykle poniżej milisekundy.

Ten przewodnik jest dla deweloperów robiących code review, dla SRE porównujących wycinki logów, dla prawników nanoszących redline w umowach i dla redaktorów oceniających zmiany. Omawia algorytmy (LCS, Myers, Patience), dwa standardowe widoki i opcje ignorowania, które wyciszają 95% skarg w stylu „wszystko wygląda na zmienione”. Pokazuje, kiedy zamiast text diff sięgnąć po JSON diff, daje sześć gotowych przypadków z danymi do skopiowania i tłumaczy pułapki przez zachowanie samego algorytmu.

Chcesz od razu porównać dwa teksty? Otwórz Text Diff — narzędzie działa wyłącznie w przeglądarce, bez żadnego uploadu.

1. Czym jest text diff?

Text diff to najmniejszy zbiór wstawek i usunięć, który przekształca jeden tekst w drugi, z każdą linią oznaczoną jako dodana, usunięta lub niezmieniona. Współczesne diffy dokładają drugi przebieg na poziomie słów lub znaków, dzięki czemu edycja jednego znaku podświetla tylko ten token, a nie całą linię.

1.1 Dlaczego porównanie znak po znaku (===) nie wystarcza

Wystarczy wstawić jedną linię na początek 200-liniowego pliku konfiguracyjnego, a naiwne porównanie znaków zaraportuje każdy bajt po punkcie wstawienia jako odmienny. Tekst się nie zmienił, zmieniło się jego położenie. Algorytm diff musi rozpoznać, że „następne 199 linii to wciąż te same linie, tylko przesunięte o jedną”, i zgłosić pojedyncze wstawienie. To rozpoznanie daje właśnie LCS, dlatego git, GitHub i każde narzędzie do code review ma własną implementację.

1.2 Side-by-side vs unified diff

Widok side-by-side ustawia obie wersje w równoległych kolumnach i koloruje komórki: zielony dla dodanych, czerwony dla usuniętych, żółty dla zmodyfikowanych. Unified diff to starszy format tekstowy z GNU diff — jedna kolumna, znaczniki - i +, trzy linie kontekstu wokół każdego hunka. To samo porównanie, dwie prezentacje. Sekcja 4 wyjaśnia, kiedy używać którego.

1.3 Gdzie text diff się sprawdza

Code review na GitHub i GitLab. Lokalny git diff. Patche wklejane na Slack. Redline w umowach. Kontrola tłumaczeń. Snapshot testy CI, które padają z wynikiem +/-. Analiza osi czasu logów. Porównywanie dwóch plików .env. Wszystko, gdzie dwa bloki tekstu trzeba dopasować linia po linii.

Otwórz Text Diff i wklej dwa teksty, żeby zobaczyć to w działaniu — każde porównanie wykonuje się lokalnie w przeglądarce.

2. Algorytm za text diff (LCS + Myers + Patience)

2.1 Longest Common Subsequence

Dla dwóch ciągów linii A i B Longest Common Subsequence to najdłuższa lista linii, które pojawiają się w obu, w tej samej kolejności, ale niekoniecznie obok siebie. Mając LCS, sam diff jest prosty: linie w A spoza LCS są usunięte, linie w B spoza LCS są dodane, linie należące do LCS są niezmienione.

Klasyczny LCS działa jako tablica programowania dynamicznego o rozmiarze N × M. Komórka (i, j) przechowuje długość LCS pierwszych i linii A i pierwszych j linii B. Wypełnia się tablicę od lewej do prawej, od góry do dołu, a następnie cofa od prawego dolnego rogu, by zrekonstruować skrypt edycji. Czas i pamięć to O(N×M): w porządku dla dwóch plików po tysiąc linii, wolno dla logu na sto tysięcy linii.

2.2 Myers (1986)

Praca Eugene’a Myersa z 1986 roku „An O(ND) Difference Algorithm and Its Variations” przeformułowuje problem jako najkrótszą ścieżkę w grafie edycji: węzły to pozycje (i, j) w obu wejściach, ruchy poziome to usunięcia, ruchy pionowe to wstawienia, ruchy po przekątnej to dopasowania. Najkrótsza ścieżka to minimalny skrypt edycji.

Myers działa w czasie O((N+M)D), gdzie D to rozmiar skryptu edycji. Gdy dwa teksty są podobne, a tak zwykle bywa przy diffach, D jest niewielkie, a algorytm w praktyce liniowy. To domyślna opcja w git diff, GNU diff i rendererze PR na GitHubie. Dla 99% wejść w przeglądarce jest to najlepszy wybór.

2.3 Patience diff (Bram Cohen, 2005)

Patience diff podchodzi do problemu inaczej: znajduje linie, które w każdym wejściu występują dokładnie raz (tzw. „unique anchor lines”), zestawia je w pary i rekurencyjnie analizuje przerwy między kotwicami. Matematycznie wygląda to brzydziej (pesymistyczna złożoność pozostaje słaba), ale wynik czyta się znacznie lepiej w kodzie.

Dlaczego? Myers minimalizuje odległość edycyjną, co jest matematycznie optymalne, lecz wizualnie tragiczne, gdy optymalne dopasowanie krzyżuje niepowiązane nawiasy klamrowe albo puste linie. Patience odmawia dopasowywania się do typowych powtórzeń (każdy plik ma linie }, każdy plik ma puste linie), więc granice funkcji pozostają nietknięte. Bram Cohen wymyślił to dla Bazaara, Git oferuje to jako git diff --patience. Bardzo zbliżony algorytm Histogram (git diff --histogram) jest nieco szybszy przy podobnej jakości wyniku.

Wyobraź sobie dwie wersje tego samego pliku, w którym przesunięto funkcję. Myers może dopasować zamykający nawias funkcji A do zamykającego nawiasu funkcji B i zgłosić ciała jako całkowicie różne. Patience zakotwiczy się na unikatowych nazwach funkcji i raportuje czyste przeniesienie. To samo wejście, zupełnie inne doświadczenie review.

2.4 Porównanie algorytmów

WłaściwośćMyers (domyślny)PatienceHistogram
Złożoność czasowaO((N+M)D)~O(N log N) w typowym przypadkupodobna do Patience
Optymalna odległość edycyjnaTak, najkrótszy skryptNie, może być dłuższyNie, może być dłuższy
Czyta się naturalnie w kodzieCzasem źle dopasowuje nawiasy i puste linieŚwietnie — kotwiczy na unikatowych liniachŚwietnie
Używany przezgit domyślnie, GNU diff, GitHub UIgit diff --patience, Bazaargit diff --histogram
Najlepszy doSzybkość i poprawność dla większości wejśćCode review, diff refaktoryzacjiJak Patience, nieco szybszy

2.5 Co robi to narzędzie

Text Diff wykorzystuje klasyczne LCS w programowaniu dynamicznym z dwiema agresywnymi optymalizacjami: trymowaniem wspólnego prefiksu i sufiksu oraz drugim przebiegiem LCS na poziomie tokenów dla diffu słów wewnątrz linii. Porównanie dwóch konfiguracji po dwa tysiące linii z jedną zmianą po trymowaniu zwija się do tablicy DP 1×1 i renderuje się w czasie krótszym niż milisekunda. Dla typowych wejść w przeglądarce wybór między Myers a DP jest niewidoczny: oba kończą się szybciej, niż przeglądarka zdąży odmalować wynik.

3. Inline diff słów wewnątrz linii — dlaczego zmiana jednego znaku podświetla całą linię

Zmieniasz jeden identyfikator w linii i cała linia zapala się na czerwono i zielono. Bug? Nie, projekt.

Diff najpierw uruchamia LCS na poziomie linii: „linia 14 została zastąpiona”. Następnie dla każdej zamienionej pary uruchamia drugie LCS na poziomie tokenów. Tokeny powstają przez podział na granicach słów Unicode: sekwencje liter i cyfr zostają razem, a białe znaki i interpunkcja stają się osobnymi tokenami. Drugie LCS daje minimalny skrypt edycji na poziomie tokenów wewnątrz tej linii.

Renderer rysuje całą linię w kolorze podświetlenia, żeby oko ją znalazło, a następnie maluje jasnym tłem tylko zmienione tokeny. Niezmienione tokeny wokół nich noszą stłumioną wersję tego samego koloru — są obecne, ale wizualnie ciche. Wzrok od razu trafia w konkretną edycję.

Przykład 1: zmiana nazwy identyfikatora. function getUser(id) staje się function getUser(userId). Cała linia oznaczona jako zmodyfikowana. Wewnątrz linii inline podświetlenie obejmuje tylko id (przekreślone na czerwono) i userId (jasny zielony). Reszta pozostaje stłumiona.

Przykład 2: zmiana opóźnienia w logu. POST /api/orders 201 88ms staje się POST /api/orders 201 4200ms. Linia jest zmodyfikowana. Inline jasne są tylko 88 i 4200. Ścieżka, metoda i kod statusu pozostają stłumione — dokładnie to, czego potrzebuje czytający oś czasu incydentu.

Gdy zmienia się zbyt wiele tokenów, podświetlanie na poziomie słów staje się szumem. Narzędzie przechodzi wtedy w prezentację „para usunięcie + dodanie”: oryginalna linia jako usunięta, nowa jako dodana, bez kolorowania wewnątrz linii. Próg wynosi z grubsza „ponad połowa tokenów się różni”.

Podsumowanie: diff liniowy mówi, która linia się zmieniła; diff słowny mówi, które znaki w tej linii niosą zmianę. Kliknij Sample wewnątrz Text Diff, aby zobaczyć oba widoki na identycznym wejściu.

4. Side-by-side vs unified diff — dwa widoki, jeden diff

4.1 Widok side-by-side

Dwie kolumny: oryginał po lewej, zmodyfikowany po prawej. Pasujące linie są wyrównane poziomo. Linie dodane pojawiają się tylko w prawej kolumnie z zielonym tłem; linie usunięte tylko w lewej z czerwonym tłem; pary zmodyfikowane stoją obok siebie z żółtym marginesem i inline podświetlonymi tokenami słów.

Widok side-by-side wybierz, gdy diff będzie czytał człowiek — review PR-a, nauczanie, demo, omówienie zmiany w umowie z osobą nietechniczną. To widok dla oczu.

Minus: nie można go przekazać dalej. Nie wkleisz renderowania side-by-side na Slack tak, żeby ktokolwiek mógł to zaaplikować. Nie przepuścisz tego przez patch. Do dzielenia się i aplikowania potrzebny jest unified diff.

4.2 Format unified diff

Unified diff to pięćdziesięcioletni format tekstowy zdefiniowany przez GNU diff i ustandaryzowany w POSIX. Pełny przykład:

--- 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.

Pierwsze dwie linie nazywają pliki źródłowe. Linia @@ -L,C +L,C @@ to nagłówek hunka: -L,C oznacza, że począwszy od linii L oryginału obejmuje C linii; +L,C mówi to samo dla wersji zmodyfikowanej. Wewnątrz hunka linie zaczynające się od spacji to kontekst (niezmienione), - to usunięte, + to dodane.

Trzy linie kontekstu nad i pod każdą zmianą to domyślna wartość GNU. Większość narzędzi pozwala to zmienić przez -U ndiff -U0 bez kontekstu, diff -U10 z dziesięcioma liniami. Nagłówek hunka odzwierciedla to, co wybierzesz.

W Text Diff kliknij zakładkę Unified, żeby przełączyć widok, lub Copy unified diff, żeby wrzucić patch do schowka.

4.3 Gdzie unified diff jest przenośny

Unified diff podróżuje. To uniwersalna waluta zmiany tekstowej.

CelAkceptuje unified diff?Jak
GNU patchTakpatch -p1 < diff.patch
git applyTakgit apply diff.patch
Komentarz review PR na GitHubieTak (w bloku ```diff)Renderuje z kolorem
Komentarz MR na GitLabieTakTen sam blok ogrodzony
PR na Bitbucket / Azure DevOpsTakTen sam blok ogrodzony
Wklejka na Slack / DiscordCzęściowoRenderuje jako tekst w bloku kodu, bez koloru
VS Code „Open Patch”TakApply patch z poziomu Source Control
Treść zgłoszenia w Jira / LinearCzęściowoDziała w bloku kodu, brak przycisku Apply

Te same dziewięć linii tekstu ---/+++/@@ aplikuje się przez patch, przez git apply, renderuje na trzech platformach PR i przeżywa wklejkę na Slacka. Żaden inny format diffa nie ma takiego zasięgu.

4.4 Który wybrać kiedy

Side-by-side do review, unified do dzielenia się i aplikowania. Jeśli sam czytasz diff, kolumny są szybsze. Jeśli ktokolwiek lub cokolwiek po stronie odbiorczej musi to skonsumować — reviewer, narzędzie, komenda patch — skopiuj format unified.

5. Opcje ignorowania — białe znaki, wielkość liter, puste linie, znaki końca linii

Większość skarg „wszystko wygląda na zmienione” to szum. Cztery przełączniki rozwiązują 95% z nich.

  1. Ignoruj wielkość liter mapuje A na a. Odpowiednik git diff -i. Używaj przy porównaniu zmiennych środowiskowych, audycie stylu słów kluczowych SQL, wszędzie gdzie konwencja stosuje krzykliwe wielkie litery zamiast spokojnych małych, lecz znaczenie jest identyczne.
  2. Ignoruj wszystkie białe znaki zwija każdą spację, tabulator i znak nowej linii przed porównaniem. Odpowiednik git diff -w. Lekarstwo na refactor taby ↔ spacje, przepisane wcięcia i diffy w stylu „przeszliśmy na Prettiera”, które niszczą liczbę linii. Diff z ignorowaniem białych znaków zazwyczaj spada z 87 modyfikacji do 4.
  3. Ignoruj końcowe spacje i tabulatory ścina tylko białe znaki na końcu linii. Odpowiednik git diff -b. Lekarstwo na szum CRLF po kopiowaniu między maszynami Windows i Unix — końcowe znaki \r są odfiltrowywane i właściwa treść się zgadza.
  4. Ignoruj puste linie odrzuca puste linie przed diffem. Lekarstwo na „dodałem jeden akapit i teraz akapit 12 wygląda zupełnie inaczej” w diffach prozy.

200-liniowa konfiguracja, która raportuje „87 modyfikacji”, zwykle spada do „4 modyfikacji” po włączeniu Ignoruj wszystkie białe znaki. Kopia z Windows na Unix, która zapala każdą linię, spada do zera z Ignoruj końcowe spacje. Każdy przełącznik jest niezależny i utrzymuje się między sesjami.

CRLF vs LF. Końce linii w Windows to \r\n, w Uniksie \n, w klasycznym Macu \r. Otwórz plik z Windows w edytorze Uniksowym, który nie normalizuje, a w treści zostanie końcowy \r. Każda linia będzie różnić się jako „treść się zgadza, ale na końcu jest \r”. Ignoruj końcowe spacje wycisza ten szum bez gubienia rzeczywistych zmian.

Jedno ostrzeżenie. Opcje ignorowania to broń obosieczna. Włączysz Ignoruj wielkość liter i refactor, który zmienia LOG.error na log.Error, wygląda identycznie. Włączysz Ignoruj wszystkie białe znaki i błąd wcięcia w Pythonie staje się niewidoczny. Dobieraj przełączniki do pytania, które zadajesz, a potem je wyłączaj, gdy skończysz.

6. Text diff vs JSON diff vs git diff — macierz decyzyjna

Text diff to dopasowanie linii i słów bez rozumienia struktury. To dokładnie to, czego chcesz dla prozy, i dokładnie to, czego nie chcesz dla JSON.

6.1 Macierz decyzyjna

Typ wejściaText diffJSON diffGit diff
Proza / Markdown / umowaNajlepszyZłe narzędzieCzęściowo (tylko śledzone pliki)
Wycinek kodu (wklejka jednego pliku)NajlepszyZłe narzędzieCzęściowo (wymaga repo)
Kod w repo (wiele plików)CzęściowoZłe narzędzieNajlepszy
Odpowiedź API JSONZłe narzędzie (false positive na kolejności kluczy)NajlepszyZłe narzędzie
Konfiguracja YAML / TOMLCzęściowo (false positive na kolejności kluczy)Najlepszy (po konwersji)Częściowo
CSV linia po liniiCzęściowoZłe narzędzieZłe narzędzie
Log / heredocNajlepszyZłe narzędzieZłe narzędzie
Plik binarnyZłe narzędzieZłe narzędziegit diff --binary

6.2 Kiedy text diff to złe narzędzie

Trzy klasyczne pomyłki.

JSON z przestawionymi kluczami. {"a":1,"b":2} i {"b":2,"a":1} to ten sam dokument JSON. Text diff zgłosi każdą linię jako zmienioną, bo linie naprawdę są różne. Sięgnij po JSON Diff — rozumie, że klucze JSON nie mają kolejności.

Konfigi YAML po reformatowaniu. Zmień jedną wartość, przepuść plik przez formatter i wcięcia, kolejność kluczy oraz cudzysłowy poprzesuwają się. Text diff zgłosi kompletne przepisanie. Skonwertuj oba pliki najpierw do JSON, a potem porównaj przez JSON Diff.

Refactor wielu plików ze zmianami nazw. Git śledzi zmiany nazw; text diff nie. Jeśli porównujesz dwa drzewa, sklejając pliki w jeden blob, każde przeniesienie między plikami pokazuje się jako usunięte + dodane. Lepiej użyć git diff (lub git diff --find-renames=80%).

6.3 Kiedy text diff trafia idealnie

Proza. Wycinki kodu wklejone skądkolwiek. Redline w umowach. Wycinki logów. Kontrola tłumaczenia, gdy zestawiasz zdania w naturalnym języku. Pliki .env, gdzie kolejność ma znaczenie, bo shelle czytają je od góry do dołu. Wszystko, gdzie znaczenie niosą same linie.

Po szczegóły filtrowania szumu z diffów JSON — znaczników czasu, request ID, automatycznie generowanych UUID-ów — sięgnij do Jak ignorować znaczniki czasu i ID w JSON Diff.

7. Sześć przypadków z życia (z gotowymi do wklejenia danymi)

7.1 Wycinek code review — zmiana nazwy funkcji

Reviewujesz PR. Autor zmienił id na userId i dodał klauzulę strażniczą. Wklej obie wersje:

// 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 pokazuje trzy zmodyfikowane linie plus jedną dodaną. Inline podświetlanie słów zaznacza każdy token iduserId; nowa klauzula strażnicza pojawia się z zielonym tłem. Opcje ignorowania wyłączone. Wypróbuj to w Text Diff i skopiuj wynik unified jako komentarz review.

7.2 Redline umowy lub polityki — jedna wstawiona klauzula

Pięćdziesiąt akapitów umowy, jedna wstawiona klauzula. Wklej wczorajszą wersję po lewej i dzisiejszą po prawej:

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 zrenderuje czterdzieści dziewięć niezmienionych linii i jedną dodaną (+2a. Termination notice must be in writing.). Wyeksportuj unified diff jako ślad audytowy review prawnego.

7.3 Analiza osi czasu logów

Podejrzewasz regresję opóźnień. Weź wycinek logów dostępu sprzed incydentu i z jego trwania:

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

Inline podświetlenie wydobywa 884200 (skok opóźnienia 50×) i 200500 (endpoint szczegółów zamówienia zaczął padać). Do bogatszej pracy z logami (wyciąganie pól, grupowanie po endpointach, liczenie percentyli) sparuj diff z Ściąga jq, jeśli logi są w JSON.

7.4 Kontrola tłumaczenia — zachowanie placeholderów

Zatrudniono nową agencję tłumaczeniową i chcesz zweryfikować, że nowa kopia strukturalnie odpowiada starej. Wklej stare tłumaczenie po lewej, nowe po prawej. Włącz Ignoruj końcowe spacje / tabulatory, bo tłumacze rutynowo zostawiają zabłąkaną spację na końcu stringów.

Diff potwierdza, że każdy placeholder {username}, {count} i %s pozostaje na miejscu, zmienia się wyłącznie tekst naturalny. Brakujący placeholder pojawia się jako usunięty token w inline diffie i można go złapać, zanim trafi do produkcji. Do porównania samych formatów placeholderów Ściąga Regex omawia \{\w+\} i pokrewne. Wypróbuj to w Text Diff.

7.5 Audyt konfiguracji lub .env — produkcja vs staging

Porównaj dwa pliki .env. Włącz Ignoruj puste linie, żeby grupowanie akapitowe nie rozjeżdżało sekcji. Diff pokaże, które klucze różnią się wartością, które klucze istnieją w jednym środowisku i nie istnieją w drugim oraz gdzie komentarze rozjechały się z rzeczywistością. Pięć minut, które oszczędzą sesji debugowania „działa na stagingu, nie działa na produkcji”.

7.6 Proza lub poprawka draftu

Redaktor zwrócił draft. Wklej oryginał po lewej i wersję po edycji po prawej. Inline diff słów pokazuje dokładnie, które zdania zostały przepisane, których nie ruszono i które akapity dodano. Akceptuj lub odrzucaj zmiany pojedynczo — bez funkcji Track Changes, bez pliku Word, bez własnościowego formatu.

8. Częste pułapki i jak czytać je jako objawy

Zachowanie algorytmu tłumaczy większość problemów. Pięć typowych skarg i to, co naprawdę znaczą.

Pułapka 1: „Każda linia jest czerwona po kopiowaniu z Windows na Unix”. Każda linia w diffie pokazuje się jako zmieniona, choć treść wygląda identycznie. Powód: końcowe znaki \r z końców linii CRLF. Włącz Ignoruj końcowe spacje / tabulatory, a diff zostawi tylko rzeczywiste zmiany.

Pułapka 2: „Wkleiłem JSON i 100% linii się różni”. Dwa obiekty JSON, które powinny być równoważne, pokazują się jako kompletnie zmienione, bo zmieniła się kolejność kluczy. Text diff traktuje kolejność linii jako istotną, JSON nie. Użyj JSON Diff dla każdego wejścia w JSON.

Pułapka 3: „Reformatowanie taby ↔ spacje rozsadziło diff”. 87 modyfikacji, wszystkie to wcięcia, bo formatter zmienił wiodące białe znaki w każdej linii. Ignoruj wszystkie białe znaki zwinie szum i wydobędzie prawdziwe zmiany semantyczne.

Pułapka 4: „Diff mówi identyczne, ale cmp się nie zgadza”. Diff raportuje brak różnic, lecz porównanie bajt po bajcie pokazuje, że pliki się różnią. Powód: opcja ignorowania pozostawiona z poprzedniej sesji maskuje rzeczywiste zmiany. Otwórz panel opcji ignorowania, wyłącz każdy przełącznik i przelicz diff od nowa.

Pułapka 5: „Jedna krótka edycja pokazuje się jako usunięcie + dodanie”. Drobna zmiana pojawia się jako osobna usunięta linia i osobna dodana zamiast inline podświetlenia. Proporcja zmienionych tokenów przekroczyła próg inline, więc renderer przeszedł na prezentację par linii. To projekt, nie błąd. Przełącz na widok Unified, by zobaczyć klasyczną parę -/+, której oczekują narzędzia patch.

9. Prywatność, wydajność i kiedy sięgnąć po wiersz poleceń

Każde porównanie w Text Diff wykonuje się w JavaScript wewnątrz przeglądarki. Bez uploadu, bez plików tymczasowych, bez logów na serwerze, bez analityki nad wklejanym tekstem. Bezpieczne dla własnościowego kodu, wewnętrznych umów, prywatnych logów: wszystkiego, czego nie chciałoby się wkleić w cudzy serwis.

Praktyczne limity: około 5000 linii lub 1 MB na stronę. Live diff wyłącza się powyżej 200 KB w sumie i przełącza na ręczny przycisk Diff, żeby pisanie nie blokowało strony. Powyżej 5000 linii wejście jest przycinane, a użytkownik dostaje ostrzeżenie. Limity istnieją, bo diff działa na głównym wątku (brak web workera), a przekazanie do workera wraz z serializacją kosztowałyby więcej niż sam diff na małych wejściach.

Gdy wejście wyrasta z przeglądarki, zejdź do wiersza poleceń:

# 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

Przejdź na wiersz poleceń przy wielomegabajtowych logach, plikach binarnych, diffach repozytoriów wielu plików, wszędzie tam, gdzie chcesz kolorowania świadomego składni jak delta, oraz wszędzie, gdzie wynik diffa musisz przekazać dalej do innego narzędzia.

10. Unicode, CJK i RTL — uwagi o międzynarodowym text diff

Tokenizer dzieli na granicach słów Unicode według trzech kategorii: ciągi słowne (\p{L} litery i \p{N} cyfry), interpunkcja spoza słów oraz białe znaki. Każda kategoria produkuje własne tokeny, więc hello, world! staje się hello, ,, , world, !, czyli pięć tokenów.

Dla treści CJK (chiński, japoński, koreański) każdy ideogram lub znak kana jest własnym tokenem. Zmiana jednego znaku w zdaniu po chińsku sprawia, że tylko ten znak nosi inline podświetlenie, a reszta linii pozostaje stłumiona. Struktura akapitowa wciąż opiera się na liniach, więc przepisanie zdania, które dorzuca podział linii, pokazuje się jako edycja liniowa, a nie tokenowa.

Dla języków RTL (arabski, hebrajski) diff używa logicznych kierunków CSS (ms-, me- zamiast ml-, mr-). Na lokalizacjach RTL margines i kolumny linii naturalnie się odbijają; wewnątrz każdej komórki diffu kierunek tekstu idzie za treścią, więc napisy po arabsku renderują się prawo-do-lewa, a znaczniki + i - pozostają wyrównane do marginesu początkowego.

Normalizacja znaków końca linii rozpoznaje \r\n (Windows), \n (Unix) i samo \r (stare Mac OS do wersji 9). Wszystkie trzy są dzielone jako osobne linie, więc plik przekonwertowany z jednej platformy na drugą nie zwija się w jedną megalinię.

11. FAQ

Jak działa text diff online?

Text diff dzieli oba wejścia na linie, uruchamia algorytm Longest Common Subsequence (typowo Myers w O((N+M)D)), by znaleźć najmniejszy zbiór wstawek i usunięć, a następnie podświetla linie dodane (zielony), usunięte (czerwony) i niezmienione (szary). Drugie LCS na poziomie tokenów zaznacza zmienione słowa wewnątrz każdej zmodyfikowanej linii. Text Diff wykonuje całe porównanie lokalnie w przeglądarce.

Czym text diff różni się od JSON diff?

Text diff porównuje linia po linii, idealnie do prozy, kodu, logów i umów. JSON Diff rozumie model danych JSON: kolejność kluczy jest nieistotna, typy są ścisłe (1"1"), tablice można dopasować po kluczu. Wklej JSON do text diffa, a zmiana kolejności kluczy lub białe znaki wypłyną jako zmiany, które JSON Diff zignoruje. Sięgaj po text diff przy nieustrukturyzowanej treści, po JSON Diff przy odpowiedziach API i konfiguracjach.

Dlaczego diff pokazuje całe linie jako zmienione, gdy zmieniłem tylko jedno słowo?

Nie pokazuje — linia jest podświetlona, bo coś w niej się zmieniło, ale wewnątrz podświetlenia jasne tło noszą tylko zmienione tokeny (zielony dla dodanych, czerwone przekreślenie dla usuniętych). To inline diff słów wewnątrz linii: kontekst linii pozostaje czytelny, a wzrok ląduje na konkretnej edycji. Gdy w linii zmieniło się zbyt wiele, by podświetlanie słów było użyteczne, diff przechodzi na osobną parę usunięcie + dodanie, by struktura pozostała czysta.

Jak ignorować białe znaki, wielkość liter lub puste linie w diffie?

Włącz panel opcji ignorowania. Ignoruj wielkość liter sprawia, że A i a są równe. Ignoruj wszystkie białe znaki zwija każdą spację, tabulator i znak nowej linii — odpowiednik git diff -w. Ignoruj końcowe spacje i tabulatory odzwierciedla git diff -b i wycisza szum CRLF. Ignoruj puste linie odrzuca puste linie, by zmiany w odstępach akapitów przestały rozjeżdżać diff. Każda opcja jest niezależna i utrzymuje się między sesjami.

Czym jest format unified diff?

Unified diff to format tekstowy ---/+++/@@ -L,C +L,C @@ wprowadzony przez GNU diff pod koniec lat 80. i używany przez git, GitHub, GitLab oraz uniksową komendę patch. Każdy hunk pokazuje trzy linie kontekstu wokół zmiany, z - dla usuniętych i + dla dodanych. Skopiuj wynik unified do komentarza PR, wklej w git apply lub uruchom patch -p1 < diff.patch — zaaplikuje się bez problemu.

Myers vs Patience: który algorytm diff jest lepszy do code review?

Myers to domyślny wybór w git diff i GNU diff: szybki i matematycznie minimalny, ale czasem dopasowuje niepowiązane puste linie albo zamykające nawiasy, produkując diffy „dziwne w odbiorze”. Patience (Bram Cohen, 2005) kotwiczy się na liniach, które w każdym wejściu występują dokładnie raz, i schodzi rekurencyjnie między kotwicami, dzięki czemu granice funkcji pozostają nietknięte. Sięgaj po git diff --patience (lub --histogram dla podobnych rezultatów, nieco szybciej) przy review refaktoryzacji.

Czy wklejany tekst trafia na jakikolwiek serwer?

Nie. Każde porównanie w Text Diff działa lokalnie w JavaScript wewnątrz przeglądarki. Tekst nigdy nie jest wysyłany, logowany, zapisywany na dysku ani przekazywany żadnej trzeciej stronie. Tylko preferencje UI (tryb widoku i przełączniki opcji ignorowania) zapisują się w localStorage, aby strona pamiętała je przy następnej wizycie. Tekst nigdy. Sprawdź w DevTools → Network: gdy klikasz Diff, nie wychodzi żadne żądanie.

Jak duże mogą być oba wejścia?

Praktyczny limit to około 5000 linii lub 1 MB na stronę. Live diff wyłącza się powyżej 200 KB w sumie i przełącza na ręczny przycisk Diff. Powyżej 5000 linii wejście jest przycinane z ostrzeżeniem. Dla wielomegabajtowych plików przesiądź się na diff -u a.txt b.txt, git diff --no-index a.txt b.txt lub delta — działają strumieniowo i radzą sobie z gigabajtami.

Powiązane artykuły

Zobacz wszystkie artykuły