Vergleichen Sie zwei Dateien

Unbegrenzte Dateien. Echtzeit Vergleiche. Kostenlos, für immer.
Original
Geändert

Privat und sicher

Alles passiert in Ihrem Browser. Ihre Dateien berühren niemals unsere Server.

Blitzschnell

Kein Hochladen, kein Warten. Konvertieren Sie, sobald Sie eine Datei ablegen.

Wirklich kostenlos

Kein Konto erforderlich. Keine versteckten Kosten. Keine Tricks bei der Dateigröße.

„Diffs“ sind die Lingua Franca der Veränderung. Sie sind die kompakten Erzählungen, die Ihnen sagen, was sich zwischen zwei Versionen einer Sache bewegt hat – Quellcode, Prosa, ein Datensatz – ohne Sie zu zwingen, alles noch einmal zu lesen. Hinter diesen wenigen Symbolen (+, -, @@) verbirgt sich ein tiefer Stapel von Algorithmen, Heuristiken und Formaten, die Optimalität, Geschwindigkeit und menschliches Verständnis in Einklang bringen. Dieser Artikel ist eine praktische, von Algorithmen zu Arbeitsabläufen führende Tour durch Diffs: wie sie berechnet, wie sie formatiert, wie Merge-Tools sie verwenden und wie man sie für bessere Überprüfungen optimiert. Unterwegs werden wir Behauptungen in Primärquellen und offiziellen Dokumenten verankern – denn winzige Details (wie ob Leerzeichen zählen) sind wirklich wichtig.

Was ein „Diff“ eigentlich ist

Formal beschreibt ein Diff ein kürzestes Bearbeitungsskript (SES), um eine „alte“ Sequenz durch Einfügungen und Löschungen in eine „neue“ umzuwandeln (und manchmal auch Ersetzungen, die als Löschen+Einfügen modelliert werden können). In der Praxis sind die meisten für Programmierer sichtbaren Diffszeilenorientiert und werden dann optional zur besseren Lesbarkeit auf Wörter oder Zeichen verfeinert. Die kanonischen Ausgaben sind die Formate Kontext und vereinheitlicht ; letzteres – was Sie normalerweise bei der Code-Überprüfung sehen – komprimiert die Ausgabe mit einem knappen Header und „Hunks“, die jeweils einen Bereich des Kontexts um die Änderungen herum zeigen. Das vereinheitlichte Format wird über -u/--unified ausgewählt und ist der De-facto-Standard für das Patchen; patch profitiert im Allgemeinen von Kontextzeilen , um Änderungen robust anzuwenden.

Das GNU-diff-Handbuch listet die Schalter auf, die Sie verwenden, wenn Sie weniger Rauschen und mehr Signal wünschen – das Ignorieren von Leerzeichen, das Erweitern von Tabs zur Ausrichtung oder das Anfordern eines „minimalen“ Bearbeitungsskripts, auch wenn es langsamer ist (Optionsreferenz). Diese Optionen ändern nicht, was es bedeutet, dass sich zwei Dateien unterscheiden; sie ändern, wie aggressiv der Algorithmus nach kleineren Skripten sucht und wie das Ergebnis den Menschen präsentiert wird.

Von LCS zu Myers: Wie Diffs berechnet werden

Die meisten Text-Diffs basieren auf der Längste gemeinsame Teilsequenz (LCS) -Abstraktion. Die klassische dynamische Programmierung löst LCS in O(mn) Zeit und Raum, aber das ist für große Dateien zu langsam und speicherintensiv. Hirschbergs Algorithmus zeigte, wie man optimale Ausrichtungen im linearen Raum (immer noch O(mn) Zeit) mit Divide-and-Conquer berechnet, einer grundlegenden platzsparenden Technik, die praktische Diff-Implementierungen beeinflusste.

Für Geschwindigkeit und Qualität war der Durchbruch Eugene W. Myers’ Algorithmus von 1986, der ein SES in O(ND) Zeit (N ≈ Gesamtzeilen, D ≈ Bearbeitungsdistanz) und annähernd linearem Raum findet. Myers modelliert Bearbeitungen in einem „Bearbeitungsgraphen“ und schreitet entlangam weitesten reichender Grenzen voran, was zu Ergebnissen führt, die sowohl schnell als auch nahe am Minimum im Zeilen-Diff-Setting sind. Deshalb bleibt „Myers“ in vielen Werkzeugen der Standard.

Es gibt auch die Hunt–Szymanski -Familie, die LCS beschleunigt, wenn nur wenige Positionen übereinstimmen (durch Vorindizierung von Übereinstimmungen und Verfolgung steigender Teilsequenzen), und historisch mit frühen diff-Varianten verbunden ist. Diese Algorithmen beleuchten Kompromisse: Bei Eingaben mit spärlichen Übereinstimmungen können sie subquadratisch laufen. Für einen Überblick aus der Praxis, der Theorie und Implementierung verbindet, siehe Neil Frasers Notizen.

Wenn „optimal“ nicht lesbar ist: Geduld- und Histogramm-Strategien

Myers zielt auf minimale Bearbeitungsskripte ab, aber „minimal“ ≠ „am besten lesbar“. Große Blöcke, die neu angeordnet oder dupliziert wurden, können einen reinen SES-Algorithmus zu ungeschickten Ausrichtungen verleiten. Hier kommt Patience-Diffins Spiel, das Bram Cohen zugeschrieben wird: Es verankert sich an einzigartigen, niederfrequenten Zeilen, um Ausrichtungen zu stabilisieren, und erzeugt oft Diffs, die Menschen als sauberer empfinden – insbesondere in Code mit verschobenen Funktionen oder neu organisierten Blöcken. Viele Werkzeuge bieten dies über eine „Geduld“-Option an (z. B.diff.algorithm).

Histogramm-Diff erweitert Patience um ein Frequenzhistogramm, um Elemente mit geringer Häufigkeit besser zu handhaben und dabei schnell zu bleiben (popularisiert in JGit). Wenn Sie jemals festgestellt haben, dass --histogram klarere Hunks für laute Dateien erzeugt, dann ist das beabsichtigt. Auf modernem Git können Sie den Algorithmus global oder pro Aufruf auswählen:git config diff.algorithm myers|patience|histogram oder git diff --patience.

Klarheit auf Wortebene, Leerraumkontrolle und Hervorhebung von verschobenem Code

Zeilen-Diffs sind prägnant, können aber winzige Bearbeitungen verdecken. Wort-Level-Diffs (--word-diff) färben Änderungen innerhalb von Zeilen, ohne die Überprüfung mit ganzen Zeileneinfügungen/-löschungen zu überfluten – ideal für Prosa, lange Zeichenketten oder Einzeiler.

Leerraum kann Diffs nach einer Neuformatierung überschwemmen. Git und GNU diff lassen Sie beide Leerzeichenänderungen ignorieren in unterschiedlichem Maße und die Leerraumoptionen von GNU diff (-b, -w, -B) helfen, wenn ein Formatierer läuft; Sie sehenlogische Bearbeitungen anstelle von Ausrichtungsrauschen.

Wenn Code vollständig verschoben wird, kann Git verschobene Blöcke hervorheben mit --color-moved, wodurch „verschoben“ visuell von „geändert“ getrennt wird, was Rezensenten hilft zu überprüfen, dass ein Verschieben keine unbeabsichtigten Bearbeitungen verborgen hat. Machen Sie es dauerhaft über diff.colorMoved.

Diffs im Dienste von Merges: Zwei-Wege- vs. Drei-Wege- und diff3

Ein Zwei-Wege-Diff vergleicht genau zwei Versionen; es kann nicht feststellen, ob beide Seiten dieselbe Basiszeile bearbeitet haben, daher kommt es oft zu übermäßigen Konflikten. Drei-Wege-Merging (von modernen VCSs verwendet) berechnet Diffs von einem gemeinsamen Vorfahren zu jeder Seite und gleicht dann die beiden Änderungssätze ab. Dies reduziert drastisch falsche Konflikte und bietet einen besseren Kontext. Der klassische algorithmische Kern hier ist diff3, das Änderungen von „O“ (Basis) zu „A“ und „B“ zusammenführt und bei Bedarf Konflikte markiert.

Akademische und industrielle Arbeit formalisiert und verbessert weiterhin die Korrektheit von Merges; zum Beispiel schlagen verifizierte Drei-Wege-Merges semantische Begriffe der Konfliktfreiheit vor. Im täglichen Git baut die moderne ort-Merge-Strategie auf Diffing und Umbenennungserkennung auf, um Merges mit weniger Überraschungen zu erzeugen. Für Benutzer sind die wichtigsten Tipps: Zeigen Sie Basiszeilen in Konflikten mit merge.conflictStyle=diff3an und integrieren Sie häufig, damit die Diffs klein bleiben.

Umbenennungserkennung und ihre Schwellenwerte

Traditionelle Diffs können Umbenennungen nicht „sehen“, da die Inhaltsadressierung Dateien als Blobs behandelt; sie sehen nur eine Löschung und eine Hinzufügung. Umbenennungserkennungs-Heuristiken überbrücken diese Lücke, indem sie die Ähnlichkeit zwischen hinzugefügten/entfernten Paaren vergleichen. In Git aktivieren oder optimieren Sie dies über -M/--find-renames[=<n>] (Standard ist ~50% Ähnlichkeit). Senken Sie ihn für verrauschtere Verschiebungen. Sie können Kandidatenvergleiche begrenzen mit diff.renameLimit (und merge.renameLimit während Merges). Um die Historie über Umbenennungen hinweg zu verfolgen, verwenden Sie git log --follow -- <path>. Das neuere Git führt auch eine Verzeichnis-Umbenennungserkennung durch, um Ordnerverschiebungen während Merges zu propagieren.

Binär- und Delta-Diffs: rsync, VCDIFF/xdelta, bsdiff

Nicht nur Text ändert sich. Für Binärdateien möchten Sie normalerweise Delta-Kodierung – geben Sie Kopier-/Hinzufüge-Anweisungen aus, um ein Ziel aus einer Quelle zu rekonstruieren. Der rsync-Algorithmus leistete Pionierarbeit bei der effizienten Fern-Differenzierung unter Verwendung von rollierenden Prüfsummen, um Blöcke über ein Netzwerk auszurichten und die Bandbreite zu minimieren.

Die IETF standardisierte ein generisches Delta-Format, VCDIFF (RFC 3284), das einen Bytecode aus ADD, COPY und RUN beschreibt, mit Implementierungen wie xdelta3 , das es für binäres Patchen verwendet. Für kompakte Patches auf ausführbaren Dateien erzeugt bsdiff oft sehr kleine Deltas über Suffix-Arrays und Komprimierung; wählen Sie es, wenn die Patch-Größe dominiert und die Erzeugung offline erfolgen kann.

Text-Diffs jenseits von Quellcode: Fuzzy-Matching und Patchen

Wenn Sie robustes Patchen angesichts gleichzeitiger Bearbeitungen oder leicht fehlausgerichteter Kontexte benötigen – denken Sie an Editoren oder kollaborative Systeme – ziehen Sie diff-match-patchin Betracht. Es verbindet Myers-artiges Differenzieren mit Bitap -Fuzzy-Matching, um Beinahe-Übereinstimmungen zu finden und Patches „nach bestem Bemühen“ anzuwenden, plus Pre-Diff-Beschleunigungen und Post-Diff-Bereinigungen, die ein winziges bisschen Minimalität für eine schönere menschliche Ausgabe eintauschen. Wie man Diff und Fuzzy-Patch in kontinuierlichen Synchronisationsschleifen kombiniert, erfahren Sie in Frasers Differential Synchronization.

Strukturierte Daten-Diffs: Tabellen und Bäume

Zeilen-Diffs auf CSV/TSV sind brüchig, da eine Ein-Zellen-Änderung wie eine ganze Zeilenbearbeitung aussehen kann. Tabellenbewusste Diff-Tools (daff) behandeln Daten als Zeilen/Spalten, geben Patches aus, die auf bestimmte Zellen abzielen, und rendern Visualisierungen, die Hinzufügungen, Löschungen und Änderungen offensichtlich machen (siehe die R-Vignette). Für schnelle Überprüfungen können spezialisierte CSV-Differenzierer Zell-für-Zell-Änderungen und Typ- Verschiebungen hervorheben; sie sind nicht algorithmisch exotisch, aber sie erhöhen das Überprüfungssignal, indem sie die Struktur vergleichen, die Sie tatsächlich interessiert.

Praktisches Git-Diff-Tuning: Eine Checkliste für den Prüfer

  • Wählen Sie den richtigen Algorithmus: Beginnen Sie mit Myers (Standard), versuchen Sie --patience , wenn Neuanordnungen oder verrauschte Blöcke die Ausgabe verwirren, oder --histogram für schnelle, lesbare Diffs bei sich wiederholendem Text. Legen Sie einen Standard mit git config diff.algorithm …fest.
  • Rauschen reduzieren: Verwenden Sie für reine Stil-Bearbeitungen Leerraum-Flags (-b, -w, --ignore-blank-lines), um sich auf wesentliche Änderungen zu konzentrieren. Außerhalb von Git siehe GNU diffs Leerraumkontrollen.
  • Innerhalb einer Zeile sehen: --word-diff hilft bei langen Zeilen und Prosa.
  • Verschobenen Code prüfen: --color-moved (oder diff.colorMoved) trennt „verschoben“ von „geändert“.
  • Umbenennungen handhaben: Fügen Sie beim Überprüfen von Refactorings -M hinzu oder passen Sie den Ähnlichkeitsschwellenwert an (-M90%, -M30%), um Umbenennungen zu erfassen; denken Sie daran, der Standard liegt bei etwa 50%. Für tiefe Bäume setzen Sie diff.renameLimit.
  • Historie über Umbenennungen hinweg verfolgen: git log --follow -- <path>.

Wie Merges tatsächlich Diffs verbrauchen (und was zu tun ist, wenn sie es nicht tun)

Ein Merge berechnet zwei Diffs (BASE→OURS, BASE→THEIRS) und versucht, beide auf BASE anzuwenden. Strategien wie ort orchestrieren dies im großen Stil, indem sie Umbenennungserkennung (einschließlich Verzeichnis-Verschiebungen) und Heuristiken einbeziehen, um Konflikte zu minimieren. Wenn Konflikte auftreten, --conflict=diff3 bereichert die Markierungen mit Basis-Kontext, der für das Verständnis der Absicht von unschätzbarem Wert ist. Das Pro Git-Kapitel über Fortgeschrittenes Merging führt durch Lösungsmuster, und die Git-Dokumentation listet Knöpfe wie -X ours und -X theirsauf. Um Zeit bei wiederkehrenden Konflikten zu sparen, aktivieren Sie rerere , um Ihre Lösungen aufzuzeichnen und wiederzugeben.

Jenseits von Dateien: Remote- und inkrementelle Szenarien

Wenn Sie große Assets über ein Netzwerk synchronisieren, sind Sie näher an der rsync -Welt als am lokalen diff. Rsync berechnet rollierende Prüfsummen, um übereinstimmende Blöcke remote zu entdecken, und überträgt dann nur das Notwendige. Für gepackte Deltas, VCDIFF/xdelta gibt Ihnen einen Standard-Bytecode und ausgereifte Werkzeuge; wählen Sie es, wenn Sie sowohl Encoder als auch Decoder kontrollieren. Und wenn die Patch-Größe von größter Bedeutung ist (z. B. Over-the-Air-Firmware), bsdiff tauscht CPU/Speicher zur Build-Zeit gegen sehr kleine Patches.

Ein kurzes Wort zu „fuzzy“ und „freundlich“

Bibliotheken wie diff-match-patch akzeptieren, dass in der realen Welt die Datei, die Sie patchen, möglicherweise abgedriftet ist. Durch die Kombination eines soliden Diffs (oft Myers) mit Fuzzy-Matching (Bitap) und konfigurierbaren Bereinigungsregeln können sie den richtigen Ort finden, um einen Patch anzuwenden und den Diff lesbarer zu machen – entscheidend für die kollaborative Bearbeitung und Synchronisierung.

Die „Tischeinsätze“, die Sie verinnerlichen sollten

  1. Kennen Sie Ihre Formate. Vereinheitlichte Diffs (-u/-U<n>) sind kompakt und patch-freundlich; sie sind das, was Code-Review und CI erwarten (Referenz).
  2. Kennen Sie Ihre Algorithmen. Myers für minimale Bearbeitungen schnell (Papier); Patience/Histogramm für Lesbarkeit bei Neuanordnungen oder verrauschten Blöcken (Geduld, Histogramm); Hirschberg für den linearen Platz-Trick (Papier); Hunt–Szymanski für die Beschleunigung bei spärlichen Übereinstimmungen (Papier).
  3. Kennen Sie Ihre Schalter. Leerraumkontrollen, Wort-Diff und Farb-Verschiebung sind Review-Multiplikatoren (git diff-Dokumentation; GNU-Leerraumoptionen).
  4. Kennen Sie Ihre Merges. Drei-Wege mit diff3 -Stil ist weniger verwirrend; ort plus Umbenennungserkennung reduziert den Churn; rerere spart Zeit.
  5. Wählen Sie das richtige Werkzeug für die Daten. Für CSV/Tabellen verwenden Sie daff; für Binärdateien verwenden Sie VCDIFF/xdelta oder bsdiff.

Anhang: kleines Befehlskochbuch

Weil das Muskelgedächtnis zählt:

# Zeigen Sie einen standardmäßigen vereinheitlichten Diff mit zusätzlichem Kontext an
  git diff -U5
  diff -u -U5 a b
  
  # Erhalten Sie Klarheit auf Wortebene für lange Zeilen oder Prosa
  git diff --word-diff
  
  # Ignorieren Sie Leerraumrauschen nach der Neuformatierung
  git diff -b -w --ignore-blank-lines
  diff -b -w -B a b
  
  # Heben Sie verschobenen Code während der Überprüfung hervor
  git diff --color-moved
  git config --global diff.colorMoved default
  
  # Bändigen Sie Refactorings mit Umbenennungserkennung und verfolgen Sie die Historie über Umbenennungen hinweg
  git diff -M
  git log --follow -- <file>
  
  # Bevorzugen Sie einen Algorithmus für die Lesbarkeit
  git diff --patience
  git diff --histogram
  git config --global diff.algorithm patience
  
  # Sehen Sie Basiszeilen in Konfliktmarkierungen
  git config --global merge.conflictStyle diff3

Schlussgedanke

Großartige Diffs gehen weniger darum, Minimalität zu beweisen, als vielmehr darum, das Verständnis des Prüfers zu maximieren bei minimalen kognitiven Kosten. Deshalb hat das Ökosystem mehrere Algorithmen (Myers, Patience, Histogramm), mehrere Präsentationen (vereinheitlicht, Wort-Diff, Farb-Verschiebung) und domänenspezifische Werkzeuge (daff für Tabellen, xdelta/bsdiff für Binärdateien) entwickelt. Lernen Sie die Kompromisse, optimieren Sie die Regler, und Sie werden mehr Zeit damit verbringen, über die Absicht nachzudenken und weniger Zeit damit, den Kontext aus roten und grünen Zeilen wieder zusammenzusetzen.


Ausgewählte Referenzen & weiterführende Literatur

Häufig gestellte Fragen

Was ist ein diff?

Ein diff ist ein Werkzeug oder eine Funktion, die in Versionskontrollsystemen verwendet wird, um die Unterschiede zwischen zwei Versionen oder Instanzen einer Datei hervorzuheben. Es wird üblicherweise verwendet, um Änderungen oder Updates, die im Laufe der Zeit an der Datei vorgenommen wurden, nachzuverfolgen.

Wie vergleicht ein diff zwei Dateien?

Ein diff vergleicht zwei Dateien Zeile für Zeile. Es scannt und paart jede Zeile in der ersten Datei mit ihrem Gegenstück in der zweiten Datei und vermerkt alle signifikanten Unterschiede wie Ergänzungen, Löschungen oder Änderungen.

Was ist ein Patch im Kontext von Diffs?

Ein Patch ist eine Datei, die die Unterschiede zwischen zwei Dateien enthält, wie sie vom diff-Werkzeug erstellt wurde. Sie kann auf eine Version einer Datei mit dem Befehl 'patch' angewendet werden, um diese auf eine neuere Version zu aktualisieren.

Was sind vereinheitlichte Diffs?

Vereinheitlichte Diffs sind ein Typ von diff-Dateiformat, das Änderungen in einem für Textdateien geeigneten Dateiformat darstellt. Es zeigt Löschungen aus der Originaldatei mit einem '-' vorangestellt und Ergänzungen zur Originaldatei mit einem '+' vorangestellt an.

Warum sind Diffs in Versionskontrollsystemen unerlässlich?

Diffs sind in Versionskontrollsystemen unerlässlich, weil sie Teams ermöglichen, Änderungen, die im Laufe der Zeit an einer Datei vorgenommen wurden, nachzuverfolgen. Diese Nachverfolgung erleichtert es, Konsistenz aufrechtzuerhalten, doppelte Arbeit zu vermeiden, Fehler oder Diskrepanzen zu erkennen und mehrere Versionen von Dateien effizient zu verwalten.

Was ist der LCS-Algorithmus in Diff-Werkzeugen?

Der Longest Common Subsequence (LCS) Algorithmus ist eine gängige Methode, die in Diff-Werkzeugen verwendet wird, um die längste Sequenz von Zeichen zu finden, die von links nach rechts in beiden ursprünglichen und modifizierten Dateien erscheinen. Dieser Algorithmus hilft bei der Identifizierung der wichtigsten Ähnlichkeiten und Unterschiede zwischen zwei Dateien.

Können Diff-Werkzeuge binäre Dateien vergleichen?

Die meisten Basis-Diff-Werkzeuge können nur Textdateien vergleichen. Allerdings sind spezialisierte Diff-Werkzeuge so konzipiert, dass sie binäre Dateien vergleichen können und die Unterschiede in einem lesbaren Format darstellen.

Welche gängigen Diff-Werkzeuge werden heute verwendet?

Zu den beliebtesten Diff-Werkzeugen gehören GNU diff, DiffMerge, KDiff3, WinMerge (Windows) und FileMerge (Mac). Viele Integrierte Entwicklungsumgebungen (IDEs) enthalten auch eingebaute diff-Hilfsprogramme.

Wie kann ich ein Diff in Git erstellen?

In Git können Sie ein Diff erstellen, indem Sie den Befehl `git diff` gefolgt von den beiden Versionen der Dateien, die Sie vergleichen möchten, verwenden. Die Ausgabe zeigt die Unterschiede zwischen den beiden Dateien.

Kann ich Diff-Werkzeuge mit Verzeichnissen und nicht nur mit Dateien verwenden?

Ja, viele Diff-Werkzeuge haben die Fähigkeit, Verzeichnisse zusätzlich zu einzelnen Dateien zu vergleichen. Diese Funktion kann besonders nützlich sein, wenn man Versionen eines großen Projekts mit mehreren Dateien vergleicht.