Porównywacz Tekstów

Porównaj dwa teksty obok siebie i wyróżnij różnice linia po linii

Wypróbuj przykład

Tekst A

Tekst B

Działa lokalnie · Bezpieczne do wklejania sekretów
Działa lokalnie · Bezpieczne do wklejania sekretów

Czym jest Text Diff?

Text diff (skrót od 'difference', czyli różnica) to wynik porównania dwóch bloków tekstu z oznaczeniem linii dodanych, usuniętych lub niezmienionych. Koncepcja wywodzi się z narzędzia Unix diff, wydanego po raz pierwszy w 1974 roku w ramach Version 5 Unix. Dziś diff jest podstawą systemów kontroli wersji, takich jak Git — każdy commit przechowuje diff zamiast pełnej kopii każdego pliku.

Algorytm diff wyznacza Najdłuższy Wspólny Podciąg (LCS) między dwiema sekwencjami linii. Linie należące do LCS są oznaczane jako niezmienione. Linie obecne w tekście oryginalnym, ale nie w LCS, są oznaczane jako usunięte. Linie obecne w tekście zmodyfikowanym, ale nie w LCS, są oznaczane jako dodane. Wynikiem jest minimalny zestaw zmian potrzebnych do przekształcenia jednego tekstu w drugi.

Wynik diff może mieć kilka formatów. Unified diff (domyślny format dla git diff) poprzedza usunięte linie minusem, a dodane linie plusem. Diff side-by-side wyświetla oba teksty w równoległych kolumnach. To narzędzie stosuje porównanie linia po linii z wyjściem kodowanym kolorami: zielony dla dodań, czerwony dla usunięć, neutralny dla linii niezmiennych. Niezmienione linie są domyślnie wyświetlane bez prefiksu, ale można je ukryć, aby skupić się wyłącznie na zmianach.

Dlaczego warto używać tego narzędzia?

Porównywanie tekstu w terminalu wymaga instalacji narzędzi diff i obsługi opcji wiersza poleceń. Narzędzie diff w przeglądarce całkowicie eliminuje to tarcie.

Natychmiastowe porównanie
Wklej dwa bloki tekstu i od razu zobaczysz wyróżnione różnice. Bez tworzenia plików, bez zapamiętywania poleceń, bez ręcznego parsowania wyjścia.
🔒
Przetwarzanie z priorytetem prywatności
Całe porównanie odbywa się w przeglądarce przy użyciu JavaScript. Twój tekst nigdy nie opuszcza urządzenia — co ma znaczenie przy porównywaniu plików konfiguracyjnych, danych dostępowych lub kodu własnościowego.
📋
Wyjście gotowe do skopiowania
Wyjście diff używa standardowych prefiksów + / -, które odpowiadają formatowi unified diff. Możesz skopiować wynik bezpośrednio do wiadomości commit, komentarzy code review lub zgłoszeń błędów.
🌐
Bez konta i instalacji
Działa na każdym urządzeniu z przeglądarką. Bez rejestracji, bez rozszerzenia, bez aplikacji desktopowej. Otwórz stronę i zacznij porównywać.

Zastosowania narzędzia Text Diff

Frontend Development
Porównaj zminifikowany CSS lub HTML przed i po kroku budowania, aby wykryć niezamierzone zmiany w generowanym kodzie lub stylach.
Backend Engineering
Porównaj odpowiedzi API między środowiskami (staging vs produkcja), aby sprawdzić, czy wdrożenie nie wprowadziło nieoczekiwanych zmian danych.
DevOps i Infrastruktura
Porównaj manifesty Kubernetes, plany Terraform lub konfiguracje Nginx przed zastosowaniem zmian na klastrze lub serwerze produkcyjnym.
QA i Testowanie
Sprawdź, czy wyjście testów zgadza się z oczekiwanymi wzorcami, porównując rzeczywisty wynik ze zapisanym plikiem snapshot.
Data Engineering
Porównaj nagłówki CSV lub definicje schematu SQL między migracjami bazy danych, aby upewnić się, że kolumny zostały poprawnie dodane lub zmienione.
Nauka i Kursy
Porównaj swoje rozwiązanie z implementacją wzorcową linia po linii, aby znaleźć miejsce, w którym Twoja logika rozmija się z oczekiwanym podejściem.

Porównanie formatów wyjścia diff

Narzędzia diff produkują wyjście w kilku formatach. Poniższa tabela podsumowuje najpopularniejsze z nich, źródła ich generowania oraz sytuacje, w których każdy jest przydatny.

FormatNarzędzie / ŹródłoOpis
Unified diffdiff -u / git diffPrefixes lines with + / - / space; includes @@ hunk headers
Side-by-sidediff -y / sdiffTwo columns, changed lines aligned horizontally
Context diffdiff -cShows changed lines with surrounding context, marked with ! / + / -
HTML diffPython difflibColor-coded HTML table with inline change highlights
JSON PatchRFC 6902Array of add/remove/replace operations on a JSON document

Jak działa diff linii: algorytm LCS

Większość narzędzi do porównywania linii, w tym to narzędzie, używa algorytmu Najdłuższego Wspólnego Podciągu (LCS). LCS wyznacza największy zbiór linii, które pojawiają się w obu tekstach w tej samej kolejności względnej, bez wymagania ciągłości. Linie nie należące do LCS stanowią właściwe różnice.

Standardowy algorytm LCS używa programowania dynamicznego i działa w czasie O(m x n), gdzie m i n to liczby linii obu tekstów. Dla dużych plików zoptymalizowane warianty, takie jak algorytm Myersa (używany przez Git), redukują złożoność do O(n + d^2), gdzie d to liczba różnic — co sprawia, że jest szybki, gdy większość linii jest wspólna.

1. Budowa tabeli DP
Tworzę macierz (m+1) x (n+1). Dla każdej pary linii przechowywana jest długość najdłuższego wspólnego podciągu wyznaczonego dotychczas. Równe linie zwiększają wartość na przekątnej o 1.
2. Cofanie śladu
Przechodzę od dolnego prawego rogu macierzy z powrotem do (0,0). Ruchy po przekątnej na równych liniach dają wpisy 'niezmieniony'. Ruchy poziome lub pionowe dają wpisy 'dodana' lub 'usunięta'.
3. Renderowanie wyjścia
Każdy wpis mapuję na wiersz wyświetlany: niezmienione linie nie mają prefiksu, dodane linie mają +, usunięte linie mają -. Stosuje się kodowanie kolorami dla przejrzystości wizualnej.

Przykłady kodu

Implementacje porównywania tekstu linia po linii w JavaScript, Pythonie, Go i wierszu poleceń. Każdy przykład produkuje wyjście w stylu unified diff.

JavaScript
// Line-by-line diff using the LCS algorithm
function diffLines(a, b) {
  const linesA = a.split('\n')
  const linesB = b.split('\n')

  // Build LCS table
  const m = linesA.length, n = linesB.length
  const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0))
  for (let i = 1; i <= m; i++)
    for (let j = 1; j <= n; j++)
      dp[i][j] = linesA[i-1] === linesB[j-1]
        ? dp[i-1][j-1] + 1
        : Math.max(dp[i-1][j], dp[i][j-1])

  // Backtrack to produce diff
  const result = []
  let i = m, j = n
  while (i > 0 || j > 0) {
    if (i > 0 && j > 0 && linesA[i-1] === linesB[j-1]) {
      result.unshift({ type: 'equal', text: linesA[i-1] }); i--; j--
    } else if (j > 0 && (i === 0 || dp[i][j-1] >= dp[i-1][j])) {
      result.unshift({ type: 'add', text: linesB[j-1] }); j--
    } else {
      result.unshift({ type: 'remove', text: linesA[i-1] }); i--
    }
  }
  return result
}

const diff = diffLines("alpha\nbeta\ngamma", "alpha\nbeta changed\ngamma\ndelta")
// → [
//   { type: 'equal',  text: 'alpha' },
//   { type: 'remove', text: 'beta' },
//   { type: 'add',    text: 'beta changed' },
//   { type: 'equal',  text: 'gamma' },
//   { type: 'add',    text: 'delta' }
// ]
Python
import difflib

text_a = """alpha
beta
gamma""".splitlines()

text_b = """alpha
beta changed
gamma
delta""".splitlines()

# Unified diff (same format as git diff)
for line in difflib.unified_diff(text_a, text_b, fromfile='a.txt', tofile='b.txt', lineterm=''):
    print(line)
# --- a.txt
# +++ b.txt
# @@ -1,3 +1,4 @@
#  alpha
# -beta
# +beta changed
#  gamma
# +delta

# HTML side-by-side diff
d = difflib.HtmlDiff()
html = d.make_file(text_a, text_b, fromdesc='Original', todesc='Modified')
Go
package main

import (
	"fmt"
	"strings"
)

// Minimal LCS-based line diff
func diffLines(a, b string) {
	la := strings.Split(a, "\n")
	lb := strings.Split(b, "\n")
	m, n := len(la), len(lb)

	dp := make([][]int, m+1)
	for i := range dp {
		dp[i] = make([]int, n+1)
	}
	for i := 1; i <= m; i++ {
		for j := 1; j <= n; j++ {
			if la[i-1] == lb[j-1] {
				dp[i][j] = dp[i-1][j-1] + 1
			} else if dp[i-1][j] >= dp[i][j-1] {
				dp[i][j] = dp[i-1][j]
			} else {
				dp[i][j] = dp[i][j-1]
			}
		}
	}

	var result []string
	i, j := m, n
	for i > 0 || j > 0 {
		if i > 0 && j > 0 && la[i-1] == lb[j-1] {
			result = append([]string{" " + la[i-1]}, result...)
			i--; j--
		} else if j > 0 && (i == 0 || dp[i][j-1] >= dp[i-1][j]) {
			result = append([]string{"+" + lb[j-1]}, result...)
			j--
		} else {
			result = append([]string{"-" + la[i-1]}, result...)
			i--
		}
	}

	for _, line := range result {
		fmt.Println(line)
	}
}

// Output:
//  alpha
// -beta
// +beta changed
//  gamma
// +delta
CLI (diff / git)
# Compare two files with unified diff (3 lines of context)
diff -u original.txt modified.txt

# Git diff between working tree and last commit
git diff HEAD -- file.txt

# Git diff between two branches
git diff main..feature -- src/

# Side-by-side diff in the terminal
diff -y --width=120 original.txt modified.txt

# Color-coded diff (requires colordiff)
diff -u original.txt modified.txt | colordiff

Często zadawane pytania

Jaka jest różnica między diff linii a diff znaków?
Diff linii porównuje tekst linia po linii: jeśli jakikolwiek znak w linii się zmieni, cała linia jest oznaczana jako usunięta, a nowa wersja jako dodana. Diff znaków (lub diff słów) działa na bardziej szczegółowym poziomie, oznaczając konkretne znaki lub słowa, które zmieniły się w ramach linii. Diff linii jest standardem w code review; diff znaków jest bardziej przydatny przy edycji tekstów pisanych prozą.
Jak git diff działa wewnętrznie?
Git używa domyślnie algorytmu Myersa, który wyznacza najkrótszy skrypt edycji (minimalną liczbę wstawień i usunięć) między dwoma plikami. Git przechowuje wynik w formacie unified diff z nagłówkami @@ wskazującymi numery linii. Gdy uruchamiasz git diff, Git porównuje drzewo robocze z indeksem (obszarem staging), nie z ostatnim commitem — chyba że jawnie podasz HEAD.
Czy mogę porównywać pliki binarne narzędziem do diff tekstu?
Nie. Narzędzia do diff tekstu dzielą dane wejściowe na znakach nowej linii i porównują ciągi znaków. Pliki binarne zawierają dowolne sekwencje bajtów, które dają bezsensowny podział na linie. Do porównania binarnego użyj narzędzia hex diff lub porównania sum kontrolnych na poziomie pliku (sha256sum na obu plikach).
Czy moje dane są wysyłane na serwer podczas korzystania z tego narzędzia?
Nie. To narzędzie działa w całości w Twojej przeglądarce. Obliczanie diff korzysta z implementacji LCS w JavaScript wykonywanej po stronie klienta. Żadne żądania sieciowe nie są wykonywane z Twoją treścią tekstową. Możesz to zweryfikować, otwierając zakładkę Network w przeglądarce podczas używania narzędzia.
Czym jest format unified diff?
Unified diff to format wyjściowy używany przez diff -u i git diff. Pokazuje zmienione linie z prefiksami - (usunięte) i + (dodane), poprzedzonymi nagłówkami @@ określającymi zakresy numerów linii w obu plikach. Linie kontekstowe (niezmienione) mają prefiks spacji. Unified diff jest najczęściej stosowanym formatem dla patchy, pull requestów i narzędzi do code review.
Jak porównywać duże pliki z wieloma różnicami?
W przypadku plików z tysiącami linii narzędzie przeglądarkowe działa, ale może być wolniejsze, ponieważ algorytm LCS skaluje się kwadratowo. Dla bardzo dużych diffów narzędzia wiersza poleceń, takie jak diff lub git diff, są szybsze dzięki zoptymalizowanym implementacjom w C i możliwości strumieniowania wyjścia. Możesz też ukryć niezmienione linie (wyłącz opcję 'Pokaż niezmienione linie' w tym narzędziu), aby skupić się wyłącznie na zmianach.
Czym jest diff scalania trójstronnego?
Scalanie trójstronne porównuje dwie zmodyfikowane wersje pliku z ich wspólnym przodkiem (bazą). Git używa tej techniki podczas git merge i git rebase. Identyfikuje zmiany wprowadzone w każdej gałęzi względem bazy i łączy je. Gdy obie gałęzie modyfikują tę samą linię, Git zgłasza konflikt scalania. Scalanie trójstronne wymaga trzech danych wejściowych, podczas gdy standardowy diff potrzebuje tylko dwóch.