Wie kann ich ein Side-by-Side-Diff erhalten, wenn ich "Git Diff" mache?

163

Wenn ich "git diff" eingebe, möchte ich ein Side-by-Side-Diff sehen, wie bei "diff -y", oder das Diff in einem interaktiven Diff-Tool wie "kdiff3" anzeigen. Wie kann das gemacht werden?

Mike
quelle

Antworten:

89

Obwohl Git eine interne Implementierung von diff hat, können Sie stattdessen ein externes Tool einrichten.

Es gibt zwei verschiedene Möglichkeiten, ein externes Diff-Tool anzugeben:

  1. Festlegen der GIT_EXTERNAL_DIFFund der GIT_DIFF_OPTSUmgebungsvariablen.
  2. Konfigurieren des externen Diff-Tools über git config

Siehe auch:

Dabei git diffüberprüft Git sowohl die Einstellungen der oben genannten Umgebungsvariablen als auch deren .gitconfigDatei.

Standardmäßig übergibt Git die folgenden sieben Argumente an das diff-Programm:

path  old-file  old-hex old-mode  new-file  new-hex new-mode

Normalerweise benötigen Sie nur die Parameter für alte und neue Dateien. Natürlich verwenden die meisten Diff-Tools nur zwei Dateinamen als Argument. Dies bedeutet, dass Sie ein kleines Wrapper-Skript schreiben müssen, das die Argumente, die Git für das Skript bereitstellt, übernimmt und an das externe Git-Programm Ihrer Wahl weitergibt.

Angenommen, Sie legen Ihr Wrapper-Skript unter ~/scripts/my_diff.sh:

#!/bin/bash
# un-comment one diff tool you'd like to use

# side-by-side diff with custom options:
# /usr/bin/sdiff -w200 -l "$2" "$5" 

# using kdiff3 as the side-by-side diff:
# /usr/bin/kdiff3 "$2" "$5"

# using Meld 
/usr/bin/meld "$2" "$5"

# using VIM
# /usr/bin/vim -d "$2" "$5"

Sie müssen das Skript dann ausführbar machen:

chmod a+x ~/scripts/my_diff.sh

Sie müssen Git dann mitteilen, wie und wo Sie Ihr benutzerdefiniertes Diff-Wrapper-Skript finden. Sie haben drei Möglichkeiten, dies zu tun: (Ich bevorzuge das Bearbeiten der .gitconfig-Datei)

  1. Verwenden von GIT_EXTERNAL_DIFF,GIT_DIFF_OPTS

    zB in Ihrer .bashrc- oder .bash_profile-Datei können Sie Folgendes einstellen:

    GIT_EXTERNAL_DIFF=$HOME/scripts/my_diff.sh
    export GIT_EXTERNAL_DIFF
    
  2. Verwenden von git config

    Verwenden Sie "git config", um zu definieren, wo sich Ihr Wrapper-Skript befindet:

    git config --global diff.external ~/scripts/my_diff.sh
    
  3. Bearbeiten Sie Ihre ~/.gitconfigDatei

    Sie können Ihre ~/.gitconfigDatei bearbeiten , um folgende Zeilen hinzuzufügen:

    [diff]
      external = ~/scripts/my_diff.sh
    

Hinweis:

Ähnlich wie bei der Installation Ihres benutzerdefinierten Diff-Tools können Sie auch ein benutzerdefiniertes Zusammenführungs-Tool installieren, das ein visuelles Zusammenführungswerkzeug sein kann, um die Visualisierung der Zusammenführung besser zu unterstützen. (siehe die progit.org Seite)

Siehe: http://fredpalma.com/518/visual-diff-and-merge-tool/ und https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration

Tilo
quelle
1
Behält dies die Farbe des Git-Terminals bei?
Sridhar Sarnobat
3
Das ist großartig, aber es startet einen neuen Viewer für jede Datei. Gibt es eine Möglichkeit, einen konsolidierten Unterschied zu erstellen meld?
HRJ
2
@ Tilo Ich erhalte eine Fehlermeldung für vim as im: Warnung: Die Ausgabe erfolgt nicht an ein Terminal
toter Programmierer
Kann die meldVersion für ein Verzeichnisdiff konfiguriert werden, bei dem ich auswählen kann, für welche Datei (en) ich das Diff anzeigen möchte? Derzeit wird meldfür jede Datei ein separater Befehl ausgeführt, und ich muss beenden meld, um die nächste Datei anzuzeigen. Ich hätte mir lieber meldeine Verzeichnisliste der geänderten Dateien gezeigt, wie sie sich verhalten, wenn meldsie von Mercurial verwendet werden.
Kasperd
163

Versuchen Sie es mit Git Difftool

Verwenden Sie git difftoolanstelle von git diff. Du wirst niemals zurückkehren.

UPDATE, um eine Beispielverwendung hinzuzufügen:

Hier ist ein Link zu einem anderen Stackoverflow, der Folgendes behandelt git difftool: Wie kann ich die Ausgabe von 'git diff' mit meinem bevorzugten Diff-Tool / Viewer anzeigen?

Für neuere Versionen von gitunterstützt der difftoolBefehl viele sofort einsatzbereite externe Diff-Tools. Zum Beispiel vimdiffwird automatisch unterstützt und kann über die Befehlszeile geöffnet werden durch:

cd /path/to/git/repo
git difftool --tool=vimdiff

Andere unterstützte externe Diff-Tools sind hier aufgelistet. git difftool --tool-helpDies ist eine Beispielausgabe:

'git difftool --tool=<tool>' may be set to one of the following:
        araxis
        kompare
        vimdiff
        vimdiff2

The following tools are valid, but not currently available:
        bc3
        codecompare
        deltawalker
        diffuse
        ecmerge
        emerge
        gvimdiff
        gvimdiff2
        kdiff3
        meld
        opendiff
        tkdiff
        xxdiff
Matt Ball
quelle
34
Oder vielleicht gehst du zurück, wenn du bekommst This message is displayed because 'diff.tool' is not configured.. Vielleicht aktualisieren Sie die Antwort mit minimaler Konfiguration dieses Dings, so dass nebeneinander Unterschiede im Terminal angezeigt werden. Was hat OP verlangt? GUI-Tools sind auf Remote-Servern, auf denen Sie eine Verbindung mit ssh herstellen, ziemlich nutzlos.
Petr
1
Interessanter Punkt, obwohl ich nicht glaube, dass ich persönlich jemals Git verwenden musste, während SSH es tat. Eines der schönen Dinge an DVCS ist der verteilte Teil: Zumindest in meinen Umgebungen ist es nie mühsam, das Repo, in dem ich herumstöbern möchte, lokal zu klonen.
Matt Ball
1
Zumindest in meiner Konfiguration, git difftoolbei vimdiffder die beiden Dateien / Puffer nicht immer richtig ausgerichtet sind.
Rohmer
1
Das ist schön, und so weiter unten in der Antwortliste: OI verwenden git difftool -y, um tkdiff prompt zu verhindern
harschvchawla
Verwandte: Machen Sie Ihre git difftoolin Windows & Linux verschmelzen : stackoverflow.com/a/48979939/4561887
Gabriel Staples
55

Sie können es auch versuchen git diff --word-diff. Es ist nicht gerade Seite an Seite, aber irgendwie besser, also ziehen Sie es vielleicht Ihrem tatsächlichen Bedarf an Seite an Seite vor.

mb14
quelle
12
Dies ist der einfachste Weg. Was noch besser ist, istgit diff --word-diff=color
Rolf
@Rolf --word-diff=color gibt mir einen ungültigen Optionsfehler. In welcher Version wurde es eingeführt?
Holloway
@Trengot Ich laufe Git 1.7.9, das ist von 02/2012
Rolf
4
Die standardmäßig installierte Version von @Rolf ist hier 1.7.1. Könnte den Unterschied erklären. git diff --color-wordsfunktioniert.
Holloway
4
Ja, das git diff --color-wordsist der Weg zu modernen Git-Versionen.
VasiliNovikov
41

ydiff

Früher genannt cdiff, kann dieses Tool nebeneinander , inkrementell und farbenfroh angezeigt werden.

Anstatt zu tun git diff, tun Sie:

ydiff -s -w0

Dies wird ydiffim Side-by-Side-Anzeigemodus für jede der Dateien mit Unterschieden gestartet .

Installieren mit:

python3 -m pip install --user ydiff

-oder-

brew install ydiff

Für git logkönnen Sie verwenden:

ydiff -ls -w0

-w0Erkennt automatisch Ihre Terminalbreite. Weitere ydiff Informationen und eine Demo finden Sie auf der GitHub-Repository-Seite .

Getestet in Git 2.18.0, ydiff 1.1.

ymattw
quelle
@ RyneEverett: Können Sie erklären, wie man das Äquivalent git diff | cdiff -szu icdiff macht?
Einpoklum
Laufen Sie einfach ydiff -svon einem git / svn / hg-Arbeitsbereich aus, Sie müssen nicht
einleiten
Wenn Sie den Diff im Git-Verlauf auf eine bestimmte Datei beschränken möchten, cd <git repo>führen Sie ihn ausydiff -ls <path/to/file>
slm
22

Sie können eine Seite-an-Seite zu tun diffmit sdiffwie folgt:

$ git difftool -y -x sdiff  HEAD^ | less

Wo HEAD^ist ein Beispiel, das Sie durch alles ersetzen sollten, gegen das Sie sich unterscheiden möchten.

Ich habe diese Lösung hier gefunden, wo es auch ein paar andere Vorschläge gibt. Diese eine Antwort ist jedoch die Frage des OP kurz und klar.

Eine Erklärung der Argumente finden Sie im man git-difftool .


Wenn Sie die Kommentare berücksichtigen, können Sie einen praktischen git sdiffBefehl erstellen, indem Sie das folgende ausführbare Skript schreiben:

#!/bin/sh
git difftool -y -x "sdiff -w $(tput cols)" "${@}" | less

Speichern Sie es als /usr/bin/git-sdiffund chmod -xes. Dann können Sie Folgendes tun:

$ git sdiff HEAD^
Sternenhimmel
quelle
Normalerweise mache ich "$ git difftool -x 'sdiff -s -w 240'" (oder was auch immer die Bildschirmbreite ist), wenn ich dieselben Zeilen unterdrücken möchte und es nur eine Datei gibt (sonst mache ich vimdiff)
HidekiAI
1
@HidekiAI Ich finde es schwierig, die Terminalbreite jedes Mal einzugeben, also verwende ich tput colsstattdessen zum Beispiel : git difftool -x "sdiff -s -w $(tput cols)".
Jaume
Kann es die Farbveränderungen hervorheben? Im Moment scheinen wir unsere Augen benutzen zu müssen, um zu erkennen, was tatsächlich die Veränderungen sind
Unpolarität
Ersetzen Sie sdiff durch icdiff, um eine schöne Farbanzeige zu erhalten.
Greg
10
export GIT_EXTERNAL_DIFF='meld $2 $5; echo >/dev/null'

dann einfach:

git diff
krzych
quelle
1
"verschmelzen". funktioniert auch! Und es zeigt alle Änderungen in einem konsolidierten Fenster.
HRJ
@HRJ das funktioniert perfekt! So einfach und praktisch :)
waldyrious
9

Wenn Sie in einem Browser nebeneinander Unterschiede sehen möchten , ohne GitHub einzubeziehen , könnte Ihnen git webdiff gefallen , ein Ersatz für git diff:

$ pip install webdiff
$ git webdiff

Dies bietet eine Reihe von Vorteilen gegenüber herkömmlichen GUI-Difftools tkdiff, da Sie damit Syntax hervorheben und Bildunterschiede anzeigen können.

Lesen Sie hier mehr darüber .

danvk
quelle
7

Ich benutze Colordiff .

Installieren Sie es unter Mac OS X mit

$ sudo port install colordiff

Unter Linux ist möglicherweise apt get install colordiffoder so etwas, abhängig von Ihrer Distribution.

Dann:

$ git difftool --extcmd="colordiff -ydw" HEAD^ HEAD

Oder erstellen Sie einen Alias

$ git alias diffy "difftool --extcmd=\"colordiff -ydw\""

Dann können Sie es verwenden

$ git diffy HEAD^ HEAD

Ich habe es "diffy" genannt, weil diff -yes das Side-by-Side-Diff in Unix ist. Colordiff fügt auch Farben hinzu, die schöner sind. In der Option -ydwist das yfür die Seite an Seite, das wist das Ignorieren von Leerzeichen und das dist das Erzeugen des minimalen Diff (normalerweise erhalten Sie ein besseres Ergebnis als Diff).

Luigi R. Viggiano
quelle
Hinzufügen -y, um die Launch 'colordiff' [Y/n]:Eingabeaufforderung zu überspringen .
Beni Cherniavsky-Paskin
Bist du sicher, dass es so ist git alias diffy "difftool --extcmd=\"colordiff -ydw\""? Sollte es nicht sein git config --global alias.diffy "difftool --extcmd=\"colordiff -ydw\""?
Unpolarität
6

Für Unix kombinieren Sie nur gitund das eingebaute diff:

git show HEAD:path/to/file | diff -y - path/to/file

Natürlich können Sie HEAD durch eine andere Git-Referenz ersetzen, und Sie möchten wahrscheinlich -W 170dem Befehl diff etwas Ähnliches hinzufügen .

Dies setzt voraus, dass Sie nur Ihren Verzeichnisinhalt mit einem früheren Commit vergleichen. Der Vergleich zwischen zwei Commits ist komplexer. Wenn Ihre Shell ist bash, können Sie "Prozessersetzung" verwenden:

diff -y -W 170 <(git show REF1:path/to/file) <(git show REF2:path/to/file)

wo REF1und REF2sind Git-Referenzen - Tags, Zweige oder Hashes.

Walker Hale IV
quelle
Vielen Dank - Ihr Befehl 'git show HEAD: Pfad / zu / Datei' war das, was ich brauchte, um meine eigene Lösung zu finden, 'vimdfiff <(git show HEAD: Pfad / zu / Datei) Pfad / zu / Datei'. Die Bits sind immer noch nicht richtig ausgerichtet, aber das ist die beste Lösung, die ich derzeit habe.
Talexb
5

Ich persönlich mag icdiff sehr !

Wenn Sie auf Mac OS Xmit HomeBrew, nur zu tun brew install icdiff.

Um die Dateibeschriftungen und andere coole Funktionen korrekt zu erhalten, habe ich in meinem ~/.gitconfig:

[pager]
    difftool = true
[diff]
    tool = icdiff
[difftool "icdiff"]
    cmd = icdiff --head=5000 --highlight --line-numbers -L \"$BASE\" -L \"$REMOTE\" \"$LOCAL\" \"$REMOTE\"

Und ich benutze es wie: git difftool

Jose Alban
quelle
3

Diese Frage tauchte auf, als ich nach einer schnellen Möglichkeit suchte, mithilfe der integrierten Git-Methode Unterschiede zu lokalisieren. Meine Lösungskriterien:

  • Schneller Start, benötigte eingebaute Optionen
  • Kann viele Formate leicht verarbeiten, XML, verschiedene Programmiersprachen
  • Identifizieren Sie schnell kleine Codeänderungen in großen Textdateien

Ich habe diese Antwort gefunden , um Farbe in Git zu bekommen.

Um nebeneinander diff statt line diff zu erhalten, habe ich die ausgezeichnete Antwort von mb14 auf diese Frage mit den folgenden Parametern optimiert :

$ git diff --word-diff-regex="[A-Za-z0-9. ]|[^[:space:]]"

Wenn Ihnen das zusätzliche [- oder {+ nicht gefällt, --word-diff=colorkann die Option verwendet werden.

$ git diff --word-diff-regex="[A-Za-z0-9. ]|[^[:space:]]" --word-diff=color

Dies half beim richtigen Vergleich mit json- und xml-Text und Java-Code.

Zusammenfassend lässt sich sagen, dass die --word-diff-regexOptionen zusammen mit den Farbeinstellungen eine hilfreiche Sichtbarkeit bieten, um beim Durchsuchen großer Dateien mit kleinen Zeilenänderungen ein farblich abgestimmtes Quellcodeerlebnis im Vergleich zum Standard-Zeilendifferenz zu erzielen.

Mike
quelle
3

Einige andere erwähnten bereits cdiff für Git Side-by-Side-Unterschiede, aber niemand gab eine vollständige Implementierung davon.

Setup cdiff:

git clone https://github.com/ymattw/cdiff.git
cd cdiff
ln -s `pwd`/cdiff ~/bin/cdiff
hash -r # refresh your PATH executable in bash (or 'rehash' if you use tcsh)
        # or just create a new terminal

Bearbeiten Sie ~ / .gitconfig, indem Sie die folgenden Zeilen einfügen:

[pager]
        diff = false
        show = false

[diff]
        tool = cdiff
        external = "cdiff -s $2 $5 #"

[difftool "cdiff"]
        cmd = cdiff -s \"$LOCAL\" \"$REMOTE\"

[alias]
        showw = show --ext-dif

Der Pager aus wird benötigt, damit cdiff mit Diff funktioniert. Es handelt sich im Wesentlichen um einen Pager, daher ist dies in Ordnung. Difftool funktioniert unabhängig von diesen Einstellungen.

Der Show-Alias ​​wird benötigt, da git show nur externe Diff-Tools über Argumente unterstützt.

Das '#' am Ende des Befehls diff external ist wichtig. Der Diff-Befehl von Git hängt ein $ @ (alle verfügbaren Diff-Variablen) an den Diff-Befehl an, aber wir wollen nur die beiden Dateinamen. Also rufen wir diese beiden explizit mit $ 2 und $ 5 auf und verstecken dann das $ @ hinter einem Kommentar, der sdiff sonst verwirren würde. Daraus resultiert ein Fehler, der wie folgt aussieht:

fatal: <FILENAME>: no such path in the working tree
Use 'git <command> -- <path>...' to specify paths that do not exist locally.

Git-Befehle, die jetzt nebeneinander Unterschiede erzeugen:

git diff <SHA1> <SHA2> 
git difftool <SHA1> <SHA2>
git showw <SHA>

Cdiff Verwendung:

'SPACEBAR' - Advances the page of the current file.
'Q'        - Quits current file, thus advancing you to the next file.

Sie haben jetzt Side-by-Side-Diff über Git Diff und Difftool. Und Sie haben den cdiff Python-Quellcode für die Anpassung von Hauptbenutzern, falls Sie ihn benötigen.

Eric
quelle
2

Hier ist ein Ansatz. Wenn Sie weniger durchpfeifen, wird die xterm-Breite auf 80 eingestellt, was nicht so heiß ist. Wenn Sie den Befehl jedoch mit z. B. COLS = 210 ausführen, können Sie Ihr erweitertes xterm verwenden.

gitdiff()
{
    local width=${COLS:-$(tput cols)}
    GIT_EXTERNAL_DIFF="diff -yW$width \$2 \$5; echo >/dev/null" git diff "$@"
}
Thomas Mellman
quelle
1
Komisch. Ich habe namentlich mit einem Pseudonym unterschrieben, aber das wurde ignoriert ... Danke, dass du mich rausgeholt hast, Stack Overflow. :(
Thomas Mellman
2

Öffnen Sie Intellij IDEA , wählen Sie im Toolfenster "Versionskontrolle" ein oder mehrere Commits aus, durchsuchen Sie geänderte Dateien und doppelklicken Sie darauf, um die Änderungen für jede Datei nebeneinander zu überprüfen.

Mit dem mitgelieferten Befehlszeilen-Launcher können Sie IDEA mit einem einfachen Befehl überall aufrufen idea some/path

Versionskontrollansicht diff view

Holger Brandl
quelle
1

Es gibt viele gute Antworten auf diesen Thread. Meine Lösung für dieses Problem bestand darin, ein Skript zu schreiben.

Nennen Sie diesen 'git-scriptname' (und machen Sie ihn ausführbar und fügen Sie ihn wie jedes Skript in Ihren PATH ein), und Sie können ihn wie einen normalen git-Befehl aufrufen, indem Sie ihn ausführen

$ git scriptname

Die eigentliche Funktionalität ist nur die letzte Zeile. Hier ist die Quelle:

#!/usr/bin/env zsh
#
#   Show a side-by-side diff of a particular file how it currently exists between:
#       * the file system
#       * in HEAD (latest committed changes)

function usage() {
    cat <<-HERE
    USAGE

    $(basename $1) <file>

    Show a side-by-side diff of a particular file between the current versions:

        * on the file system (latest edited changes)
        * in HEAD (latest committed changes)

HERE
}

if [[ $# = 0 ]]; then
    usage $0
    exit
fi

file=$1
diff -y =(git show HEAD:$file) $file | pygmentize -g | less -R
Jon Carter
quelle