Wie kann ich Unterschiede pro Zeichen in einer einheitlichen Diff-Datei visualisieren?

122

Angenommen, ich erhalte einen Patch mit git format-patch. Die Datei ist im Grunde ein einheitlicher Diff mit einigen Metadaten. Wenn ich die Datei in Vim öffne, kann ich sehen, welche Zeilen geändert wurden, aber ich kann nicht sehen, welche Zeichen in den geänderten Zeilen unterschiedlich sind. Kennt jemand eine Möglichkeit (in Vim oder einer anderen kostenlosen Software, die unter Ubuntu ausgeführt wird), Unterschiede pro Zeichen zu visualisieren?

Ein Gegenbeispiel, bei dem Diff pro Zeichen visualisiert wird, ist die Ausführung vimdiff a b.

Update Fr Nov 12 22:36:23 UTC 2010

diffpatch ist hilfreich für das Szenario, in dem Sie mit einer einzelnen Datei arbeiten.

Update Do 16. Juni 17:56:10 UTC 2016

Schauen Sie sich Diff-Highlight in Git 2.9 an . Dieses Skript macht genau das , wonach ich ursprünglich gesucht habe.

Adam Monsen
quelle
Dies könnte besser sein auf
superuser.com
12
Vielleicht. Ich habe mich für stackoverflow.com entschieden, da in den FAQ erwähnt wird, dass hier Fragen zu "von Programmierern häufig verwendeten Softwaretools" gestellt werden
Adam Monsen,
7
Ich bin mir nicht sicher, ob dies Ihre Frage direkt beantwortet, aber es git diff --color-wordsist sehr nützlich, um zu sehen, welche Wörter sich innerhalb von Zeilen geändert haben, und nicht um die übliche einheitliche Diff-Ausgabe. Es ist jedoch eher wortbasiert als zeichenbasiert. Wenn der Inhalt, den Sie unterscheiden, nicht viel Leerzeichen enthält, ist die Ausgabe möglicherweise weniger ordentlich. (Bearbeitet: Ups, ich sehe, dass ich falsch verstanden habe, wonach Sie fragen - trotzdem wäre dieser Kommentar vielleicht für jemanden nützlich.)
Mark Longair

Antworten:

13

Angesichts Ihrer Verweise auf Vim in der Frage bin ich mir nicht sicher, ob dies die gewünschte Antwort ist :), aber Emacs kann dies tun. Öffnen Sie die Datei , die diff enthält, stellen Sie sicher , dass Sie in diff-mode(wenn die Datei mit dem Namen ist foo.diffoder foo.patchgeschieht dies automatisch, andernfalls geben M-x diff-mode RET), gehen Sie auf die Hunk Sie interessiert sind und treffen C-c C-bfür refine-hunk. Oder gehen Sie die Datei einzeln durch M-n; Dadurch wird die Verfeinerung automatisch durchgeführt.

Legoscia
quelle
1
Funktioniert bei mir! Heh, ich habe Vim 10 Jahre lang benutzt, aber ich habe gerade Emacs installiert. :)
Adam Monsen
Aber Emacs unterstützt das Lesen von stdin nicht, ich kann es nicht tun, zBgit log master.. -p | emacs -
Hi-Angel
1
@ Hi-Angel Sie können Emacs öffnen und eingeben M-!, um den Befehl auszuführen und die Ausgabe in einem Puffer zu erfassen.
Legoscia
172

In git können Sie ohne Commit zusammenführen. Führen Sie zuerst Ihren Patch zusammen und führen Sie dann Folgendes aus:

git diff --word-diff-regex=.

Beachten Sie den Punkt nach dem Gleichheitszeichen.

yingted
quelle
139
Besser : git diff --color-words=..
ntc2
4
@ ntc2 Du solltest deinem Kommentar eine Antwort geben.
Tyler Collier
1
Bitte beachten Sie, dass mein ursprünglicher Anwendungsfall davon ausgeht, dass Sie nur eine Patch-Datei , kein Git-Repo oder sogar Basis- / modifizierte Versionen haben. Deshalb habe ich die Antwort von @ legoscia akzeptiert ... sie beschreibt genau, was angefordert wurde.
Adam Monsen
2
@ ntc2 git diff --color-words=.und git diff --color-words .funktioniert anders. Besser ist git diff --color-words ..
Abhisekp
2
@abhisekp: danke für das Bild. Ich denke, ich habe es herausgefunden: das git diff --color-words .ist wirklich das gleiche wie git diff --color-words -- .! Das heißt, das .wird als Pfad interpretiert. Sie können mit überprüfen mkdir x y; echo foo > x/test; git add x/test; git commit -m test; echo boo > x/test; cd y; git diff --color-words=.; git diff --color-words .; git diff --color-words -- ..
ntc2
145

Hier sind einige Versionen mit weniger verrauschten Ausgaben als git diff --word-diff-regex=<re>und, die weniger Eingabe erfordern als, aber äquivalent zu git diff --color-words --word-diff-regex=<re>.

Einfach (hebt Platzänderungen hervor):

git diff --color-words

Einfach (hebt einzelne Zeichenänderungen hervor; hebt keine Leerzeichenänderungen hervor):

git diff --color-words=.

Komplexer (hebt Raumänderungen hervor):

git diff --color-words='[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'

Allgemein:

git diff --color-words=<re>

wo <re> ein regulärer Ausdruck „Worte“ zum Zweck der Identifizierung von Veränderungen definieren.

Diese sind insofern weniger laut, als sie die geänderten "Wörter" färben, wohingegen nur --word-diff-regex=<re>umgebende "Wörter" mit farbigen -/+Markierungen umgeben sind.

ntc2
quelle
9
Ich selbst mag --color-words, ohne das =.Teil.
Tyler Collier
1
git diff --color-words='\w'würde besser mit Diakritika arbeiten (git v1.7.10.4)
nr
1
Ihre komplexere Version funktioniert hervorragend. Ich habe angehängt --word-diff=plain, zusätzlich Löschungen und Surround-Ergänzungen zu haben [-und zu -]umgeben . Da das manuelle warnt, obwohl, tatsächliche Vorkommen dieser Trennzeichen in der Quelle nicht in irgendeiner Weise entkommen{++}
Tobias Kienzler
2
Ihre komplexere Version leider nicht zB Einzug Änderungen scheint zu markieren, ich habe geöffnet eine Frage zu diesem
Tobias Kienzler
Diese Antwort ist großartig! Gibt es jedoch eine Möglichkeit, den Hintergrund dieser Änderungen tatsächlich in grün / rot zu ändern?
WoLfPwNeR
45
git diff --color-words="[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+"

Der obige Regex ( von Thomas Rast ) trennt Diff-Fragmente auf Interpunktions- / Zeichenebene (obwohl er nicht so laut ist wie --word-diff-regex=.).

Ich schrieb einen Screenshot der resultierenden Ausgabe hier .


Aktualisieren:

Dieser Artikel enthält einige großartige Vorschläge. Insbesondere verfügt der contrib/Baum des Git-Repo über ein diff-highlightPerl-Skript, das feinkörnige Highlights anzeigt.

Schnellstart zur Verwendung:

$ curl https://git.kernel.org/cgit/git/git.git/plain/contrib/diff-highlight/diff-highlight > diff-highlight
$ chmod u+x diff-highlight
$ git diff --color=always HEAD~10 | diff-highlight | less -R
Justin M. Keyes
quelle
5
Sie können es auf--color-words=[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'
Eddified
Ich musste dort 'am Anfang des Wertes hinzufügen . Ansonsten habe ich einen Fehler bekommen. Außerdem benutze ich einfach --color-wordsdas gleiche Verhalten wie bei der Verwendung dieses regulären Ausdrucks.
GCB
3
@gcb Der Textinhalt ist wichtig. Wenn Ihre Änderungen durch Leerzeichen getrennt sind, gibt es keinen Unterschied. Aber wenn Sie sich ändern, wenn Sie etwas ändern foo.bar, werden foo.quxSie den Unterschied sehen.
Justin M. Keyes
5
Einfacher : git diff --color-words='[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'.
Ntc2
1
Ich hatte Git mit Homebrew installiert und hatte dieses Skript bereits bei /usr/local/share/git-core/contrib/diff-highlight/diff-highlight. Dies scheint darauf hinzudeuten, dass Homebrews Git den gesamten Beitrag in installiert /usr/local/share/git-core/contrib/. Also schließlich funktionierte das Folgende für michgit diff --color=always | /usr/local/share/git-core/contrib/diff-highlight/diff-highlight
Ashutosh Jindal
6

Wenn Sie nichts gegen die Installation von NodeJS haben, gibt es ein Paket namens "diff-so-fantasievoll" ( https://github.com/so-fancy/diff-so-fancy ), das sehr einfach zu installieren ist und perfekt funktioniert:

npm install -g diff-so-fancy
git diff --color | diff-so-fancy | less -R

Edit: Habe gerade herausgefunden, dass es tatsächlich ein Wrapper für das offizielle Diff-Highlight ist ... Zumindest ist es für Perlophobe wie mich einfacher zu installieren und die GitHub-Seite ist gut dokumentiert :)

Walnutz
quelle
2

Ich kenne kein Werkzeug zur Unterscheidung von Zeichen pro Zeichen, aber es gibt ein Werkzeug zur Unterscheidung von Wörtern pro Wort: wdiff.

Siehe Beispiele Top 4 File Difference Tools unter UNIX / Linux - Diff, Colordiff, Wdiff, Vimdiff .

Der Nerd
quelle
wdiff ist interessant, danke! Um meine ursprüngliche Frage zu klären, suche ich nach etwas, das eine verbesserte Syntaxhervorhebung für eine einzelne Datei bietet, die zufällig im einheitlichen Diff-Format vorliegt.
Adam Monsen
Etwas offtopisch (über Wort-für-Wort-Unterschiede, ohne eine bereits vorhandene Diff-Ausgabe zu verbessern), aber ich habe die folgenden Kombinationen am besten für Wort-für-Wort-Visualisierungen gefunden: * wdiff old_file new_file | cdiff * vimdiff , dann in vim :windo wincmd K, um zum vertikalen Fensterlayout zu wechseln (untereinander) von nebeneinander. Dieses Layout ist viel besser für Dateien mit langen Zeilen.
Aleksander Adamowski
2
BTW, einige andere Werkzeuge lohnt sich, nicht in dem verlinkten Artikel erwähnt: wdiff2, mdiffund das Online - Tool von Google .
Aleksander Adamowski
1

Nach ein wenig Recherche stelle ich fest, dass diese Frage kürzlich zweimal auf der Haupt-Mailingliste von Vim aufgetaucht ist. Das NrrwRgn-Plugin wurde beide Male erwähnt (machen Sie zwei enge Regionen und unterscheiden Sie sie). Die Verwendung von NrrwRgn, wie von Christian Brabandt beschrieben, ist eher eine Problemumgehung als eine Lösung, aber vielleicht ist das gut genug.

Ich habe NrrwRgn ausprobiert und es war zusammen mit: diffthis in der Tat nützlich, um Unterschiede pro Zeichen innerhalb von Teilen einer einzelnen Datei zu veranschaulichen. Aber es dauerte viele Tastenanschläge. Mein Vimscript ist ziemlich verrostet, aber es könnte wahrscheinlich ein Skript sein. Möglicherweise könnte NrrwRgn erweitert werden, um die gewünschte Funktionalität bereitzustellen.

Gedanken?

Adam Monsen
quelle