Änderungen mit "git diff" vergleichen

Bei einem Vergleich werden zwei Eingabe-Datasets herangezogen und die Unterschiede zwischen ihnen ausgegeben. git diff ist ein vielseitiger Git-Befehl, durch dessen Ausführung ein Vergleich von Git-Datenquellen durchgeführt wird. Diese Datenquellen können Commits, Branches, Dateien und vieles mehr sein. In diesem Artikel werden wir auf typische git diff-Aufrufe und Muster von Vergleichsworkflows eingehen. Der git diff-Befehl wird häufig zusammen mit git status und git log verwendet, um den aktuellen Status eines Git-Repositorys zu analysieren.
 

Diffs lesen: Ausgaben

Rohausgabeformat

Die folgenden Beispiele werden in einem einfachen Repository ausgeführt. Das Repository wird mit den nachstehenden Befehlen erstellt:

$:> mkdir diff_test_repo
$:> cd diff_test_repo
$:> touch diff_test.txt
$:> echo "this is a git diff test example" > diff_test.txt
$:> git init .
Initialized empty Git repository in /Users/kev/code/test/.git/
$:> git add diff_test.txt
$:> git commit -am"add diff test file"
[master (root-commit) 6f77fc3] add diff test file
1 file changed, 1 insertion(+)
create mode 100644 diff_test.txt

Wenn wir an dieser Stelle git diff ausführen, gibt es keine Ausgabe. Das ist ein normales Verhalten, da es keine Änderungen im Repository anzuzeigen gibt. Sobald das Repository erstellt wurde und wir die Datei diff_test.txt hinzugefügt haben, können wir die Inhalte in der Datei ändern und mit der Diff-Ausgabe experimentieren.

$:> echo "this is a diff example" > diff_test.txt

Durch die Ausführung dieses Befehls wird der Inhalt der Datei diff_test.txt geändert. Sobald sie modifiziert wurde, können wir einen Diff anzeigen und die Ausgabe analysieren. Wenn jetzt git diff ausgeführt wird, wird folgende Ausgabe bereitgestellt:

diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

Sehen wir uns nun eine detailliertere Aufschlüsselung der Diff-Ausgabe an.

1. Vergleich der Eingabe

diff --git a/diff_test.txt b/diff_test.txt

Diese Zeile zeigt die Eingabequellen des Diff an. Wir können erkennen, dass a/diff_test.txt und b/diff_test.txt an Diff übergeben wurden.

2. Metadaten

index 6b0c6cf..b37e70a 100644

Diese Zeile zeigt einige interne Git-Metadaten an. Diese Information wirst du höchstwahrscheinlich nicht brauchen. Die Zahlen in dieser Ausgabe entsprechen den Hash-Kennungen der Git-Objektversion.

3. Markierungen für Änderungen

--- a/diff_test.txt
+++ b/diff_test.txt

Diese Zeilen stellen eine Legende dar, die jeder Diff-Eingabequelle Symbole zuordnet. In diesem Fall werden Änderungen in a/diff_test.txt durch --- und Änderungen in b/diff_test.txt durch +++ gekennzeichnet.

4. Diff-Blöcke

Die verbleibende Diff-Ausgabe ist eine Liste mit verschiedenen Diff-Blöcken. Ein Vergleich zeigt nur die Abschnitte der Datei an, die Änderungen enthalten. Im vorliegenden Beispiel haben wir nur einen Block, da wir mit einem einfachen Szenario arbeiten. Blöcke haben ihre eigene granulare Ausgabesemantik.

@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

Die erste Zeile ist der Blockheader. Jedem Block ist ein von @@-Symbolen umschlossener Header vorangestellt. Der Inhalt des Headers ist eine Zusammenfassung der Änderungen, die an der Datei vorgenommen wurden. In unserem vereinfachten Beispiel haben wir -1 +1, was bedeutet, dass es in Zeile eins Änderungen gab. In einem realistischeren Vergleich würdest du Header wie etwa folgenden sehen:

@@ -34,6 +34,8 @@

Bei diesem Header-Beispiel wurden 6 Zeilen ab Zeilennummer 34 extrahiert. Außerdem wurden 8 Zeilen ab Zeile 34 hinzugefügt.

Der verbleibende Inhalt des Diff-Blocks zeigt die kürzlichen Änderungen an. Jeder geänderten Zeile wird ein + oder - vorangestellt, was darauf hinweist, von welcher Version der Diff-Ausgabe die Änderungen stammen. Wie vorhin besprochen weist - auf Änderungen in a/diff_test.txt und + auf Änderungen in b/diff_test.txt hin.

Änderungen hervorheben

1. git diff --color-words

git diff verfügt ebenfalls über einen speziellen Modus zur Hervorhebung von Änderungen, der eine bessere Granularität bietet: ‐‐color-words. Dieser Modus tokenisiert durch Leerzeichen hinzugefügte und entfernte Zeilen und vergleicht diese dann.

$:> git diff --color-words
diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
this is a git difftest example

Die Ausgabe zeigt jetzt nur die farbkodierten Wörter an, die geändert wurden.

2. git diff-highlight

Wenn du die Git-Quelle klonst, findest du ein Unterverzeichnis namens contrib. Es enthält einige zu Git gehörende Tools und andere interessante Dinge, die noch nicht zum Git-Kern gehören. Eines davon ist ein Perl-Skript namens diff-highlight. Diff-highlight bringt gleiche Zeilen von Diff-Ausgaben zusammen und hebt Teilwortfragmente hervor, die geändert wurden.

$:> git diff | /your/local/path/to/git-core/contrib/diff-highlight/diff-highlight
diff --git a/diff_test.txt b/diff_test.txt
index 6b0c6cf..b37e70a 100644
--- a/diff_test.txt
+++ b/diff_test.txt
@@ -1 +1 @@
-this is a git diff test example
+this is a diff example

Jetzt haben wir unseren Diff auf die kleinste mögliche Änderung abgespeckt.

Binärdateien vergleichen

Neben den Textdatei-Dienstprogrammen, die wir bisher gezeigt haben, kann git diff auch für Binärdateien durchgeführt werden. Allerdings ist die Standardausgabe nicht besonders hilfreich.

$:> git diff
Binary files a/script.pdf and b/script.pdf differ

Git hat ein Feature, mit dem du einen Shellbefehl spezifizieren kannst, um Inhalte in deinen Binärdateien zu transformieren, bevor der Vergleich durchgeführt wird. Dazu sind jedoch einige vorbereitende Maßnahmen erforderlich. Lege zunächst einen textconv-Filter fest, der beschreibt, wie eine bestimmte Art von Binärdatei in Text konvertiert wird. Wir verwenden ein einfaches Dienstprogramm namens pdftohtml (über Homebrew erhältlich), um meine PDFs in ein visuell lesbares HTML-Format zu konvertieren. Du kannst dies für ein einzelnes Repository einrichten, indem du deine Datei .git/config bearbeitest, oder global, indem du ~ /.gitconfig bearbeitest.

[diff "pdfconv"]
textconv=pdftohtml -stdout

Danach musst du lediglich ein oder mehrere Dateimuster mit unserem pdfconv-Filter zuordnen. Hierzu erstellst du eine .gitattributes-Datei im Stamm deines Repositorys.

*.pdf diff=pdfconv

Nach der Konfiguration wird git diff zunächst die Binärdatei mithilfe des festgelegten Konverterskripts ausführen und die Konverterausgabe vergleichen. Du kannst dieselbe Technik anwenden, um nützliche Vergleiche von allen möglichen Arten an Binärdateien zu erhalten, wie ZIP- und JAR-Dateien und anderen Archiven. Durch die Verwendung von unzip -l (oder ähnlich) anstelle von pdf2html werden Pfade angezeigt, die zwischen Commits-Images hinzugefügt oder entfernt wurden. Mit exiv2 kannst du Änderungen von Metadaten wie Dokumente zu Bildabmessungen anzeigen. Es gibt Konvertierungstools, um ODF-, DOC- und andere Dokumentformate in Nur-Text umzuwandeln. Falls es keine formalen Konverter gibt, können häufig Strings für Binärdateien verwendet werden.

Vergleich von Dateien: git diff file

Dem Befehl git diff kann eine explizite Dateipfadoption übergeben werden. Wenn ein Dateipfad an git diff übergeben wird, wird der Vergleichsvorgang auf die spezifizierte Datei ausgelegt. Die nachstehenden Beispiele zeigen diesen Verwendungstyp.

git diff HEAD ./path/to/file

Dieses Beispiel ist auf ./path/to/file ausgelegt und wird bei Aufruf die spezifischen Änderungen im Arbeitsverzeichnis mit dem Index vergleichen und Änderungen anzeigen, die noch nicht bereitgestellt sind. git diff führt den Vergleich standardmäßig mit HEAD aus. Wird HEAD wie im obigen Beispiel weggelassen, hat git diff ./path/to/file denselben Effekt.

git diff --cached ./path/to/file

Wenn git diff mit der Option --cached aufgerufen wird, werden die bereitgestellten Änderungen mit dem lokalen Repository verglichen. Die Option --cached bedeutet dasselbe wie --staged.

Vergleich aller Änderungen

Bei einem Aufruf von git diff ohne Dateipfad werden Änderungen im gesamten Repository verglichen. Die obigen, dateispezifischen Beispiele können mit dem Argument ./path/to/file aufgerufen werden und liefern dieselben Ausgabeergebnisse für alle Dateien im lokalen Repository.

Änderungen seit dem letzten Commit

Der Befehl git diff zeigt dir standardmäßig Änderungen seit dem letzten Commit, die nicht committet wurden.

git diff

Dateien zwischen zwei verschiedenen Commits vergleichen

An git diff können Git-Verweise auf Commits übertragen werden, die verglichen werden sollen. Einige Beispielverweise sind HEAD, Tags und Branch-Namen. Jeder Commit in Git verfügt über eine Commit-ID, die du durch die Ausführung von GIT LOG erhalten kannst. Du kannst diese Commit-ID auch an git diff übergeben.

git log --prety=oneline
957fbc92b123030c389bf8b4b874522bdf2db72c add feature
ce489262a1ee34340440e55a0b99ea6918e19e7a rename some classes
6b539f280d8b0ec4874671bae9c6bed80b788006 refactor some code for feature
646e7863348a427e1ed9163a9a96fa759112f102 add some copy to body
$:> git diff 957fbc92b123030c389bf8b4b874522bdf2db72c ce489262a1ee34340440e55a0b99ea6918e19e7a

Vergleich von Branches

Vergleich von zwei Branches

Branches werden wie alle anderen Verweiseingaben mit git diff verglichen.

git diff branch1..other-feature-branch

In diesem Beispiel wird der Punktoperator vorgestellt. Die zwei Punkte darin zeigen an, dass es sich bei der Vergleichseingabe um die Enden beider Branches handelt. Derselbe Effekt tritt auf, wenn die Punkte ausgelassen und stattdessen ein Leerzeichen zwischen den Branches gesetzt wird. Es gibt im Übrigen einen Operator mit drei Punkten:

git diff branch1...other-feature-branch

Der Operator mit drei Punkten initiiert den Vergleich, indem er den ersten Eingabeparameter branch1 ändert. Dadurch wird aus branch1 ein Verweis des Vorgänger-Commits, der von den zwei Vergleichseingaben gemeinsam genutzt wird, dem gemeinsamen Vorgänger von branch1 und anderen Feature Branches. Der letzte Eingabeparameter bleibt unverändert wie die Enden anderer Feature Branches.

Vergleich von Daten aus zwei Branches

Um eine bestimmte Datei über verschiedene Branches hinweg zu vergleichen, übergibst du den Pfad der Datei als drittes Argument direkt an git diff.

git diff master new_branch ./diff_test.txt

Zusammenfassung

Auf dieser Seite wurden die Vergleichsprozesse in Git und der Befehl git diff besprochen. Wir haben erklärt, wie die git diff-Ausgabe und die verschiedenen darin enthaltenen Daten gelesen werden. Wir haben Beispiele gezeigt, wie die git diff-Ausgabe mit Hervorhebungen und Farbe geändert werden kann. Es wurden verschiedene Vergleichsmethoden besprochen, z. B. der Vergleich von Dateien in Branches und in bestimmten Commits. Neben dem git diff-Befehl haben wir auch git log und git checkout verwendet.

Möchtest du Git kennenlernen?

Sieh dir dieses interaktive Tutorial an.

Jetzt loslegen