Come posso ottenere una differenza side-by-side quando faccio "git diff"?


163

Quando scrivo "git diff", mi piacerebbe vedere un diff side-by-side, come con "diff -y", o mi piacerebbe visualizzare il diff in uno strumento interattivo come "kdiff3". Come si può fare?




Risposte:


89

Sebbene Git abbia un'implementazione interna di diff, puoi invece impostare uno strumento esterno.

Esistono due modi diversi per specificare uno strumento diff esterno:

  1. impostando il GIT_EXTERNAL_DIFFe ilGIT_DIFF_OPTS ambiente variabili.
  2. configurazione dello strumento diff esterno tramite git config

Guarda anche:

Quando si esegue un git diff, Git controlla sia le impostazioni delle variabili di ambiente sopra che le sue.gitconfig file.

Per impostazione predefinita, Git passa i seguenti sette argomenti al programma diff:

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

In genere sono necessari solo i parametri old-file e new-file. Naturalmente la maggior parte degli strumenti diff prende solo due nomi di file come argomento. Questo significa che devi scrivere un piccolo script wrapper, che prende gli argomenti che Git fornisce allo script e li passa al programma git esterno di tua scelta.

Diciamo che hai messo il tuo script wrapper sotto ~/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"

devi quindi rendere eseguibile quello script:

chmod a+x ~/scripts/my_diff.sh

devi quindi dire a Git come e dove trovare il tuo script wrapper diff personalizzato. Hai tre scelte su come farlo: (Preferisco modificare il file .gitconfig)

  1. Utilizzando GIT_EXTERNAL_DIFF,GIT_DIFF_OPTS

    ad es. nel tuo file .bashrc o .bash_profile puoi impostare:

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

    usa "git config" per definire dove trovare lo script wrapper:

    git config --global diff.external ~/scripts/my_diff.sh
    
  3. Modifica il tuo ~/.gitconfig file

    puoi modificare il tuo ~/.gitconfigfile per aggiungere queste righe:

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

Nota:

Analogamente all'installazione del tuo strumento diff personalizzato, puoi anche installare uno strumento di unione personalizzato, che potrebbe essere uno strumento di fusione visiva per aiutare a visualizzare meglio l'unione. (vedi la pagina progit.org)

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


1
Questo mantiene la colorazione terminale git?
Sridhar Sarnobat,

3
Questo è fantastico, ma avvia un nuovo visualizzatore per ogni file. Un modo per creare una diff consolidata, diciamo meld?
HRJ,

2
@Tilo Ricevo un errore per vim come im: Avviso: l'output non è verso un terminale
programmatore guasto

La meldversione può essere configurata per fare una directory diff, dove posso scegliere per quale / i file voglio vedere il diff? Attualmente esegue un meldcomando separato per ogni file e devo chiudere meldper vedere il file successivo. Preferirei meldmostrarmi un elenco di directory di file modificati come si comporta quando meldviene utilizzato da Mercurial.
Kasperd,

163

Prova git difftool

Usa git difftoolinvece di git diff. Non tornerai mai indietro.

AGGIORNA per aggiungere un esempio di utilizzo:

Ecco un link ad un altro stackoverflow che parla di git difftool: Come posso visualizzare l'output 'git diff' con il mio strumento / visualizzatore diff preferito?

Per le versioni più recenti di git, il difftoolcomando supporta immediatamente molti strumenti diff esterni. Ad esempio, vimdiffè supportato automaticamente e può essere aperto dalla riga di comando:

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

Altri strumenti di diff esterni supportati sono elencati tramite git difftool --tool-helpqui è un esempio di output:

'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

34
O forse tornerai se ci riesci This message is displayed because 'diff.tool' is not configured.. Forse aggiorna la risposta con il minimo come configurare questa cosa, in modo che mostri differenze affiancate nel terminale, qual è ciò che OP ha richiesto? Gli strumenti della GUI sono abbastanza inutili sul server remoto a cui ti connetti usando ssh.
Petr,

1
Punto interessante, anche se non credo di aver mai avuto bisogno personalmente di usare git mentre SSH lo avrebbe fatto. Una delle cose belle di DVCS è la parte Distribuita: almeno nei miei ambienti non è mai una seccatura clonare localmente qualsiasi repository che voglio curiosare.
Matt Ball,

1
Almeno nella mia configurazione, git difftoolcon vimdiffnon sempre allineare correttamente i due file / buffer.
Rohmer,

1
È bello, e così in basso nella lista delle risposte: OI uso git difftool -yper prevenire il prompt di
tkdiff

Correlati: crea la tua fusione git difftoolin Windows e Linux: stackoverflow.com/a/48979939/4561887
Gabriel Staples

57

Puoi anche provare git diff --word-diff. Non è esattamente fianco a fianco, ma in qualche modo migliore, quindi potresti preferirlo al tuo reale bisogno fianco a fianco.


12
Questo è il modo più semplice. La cosa ancora migliore ègit diff --word-diff=color
Rolf,

@Rolf --word-diff=colormi dà un errore di opzione non valido. In quale versione è stata introdotta?
Holloway,

@Trengot Corro git 1.7.9 che è dal 02/2012
Rolf

4
La versione installata predefinita di @Rolf qui è la 1.7.1. Potrebbe spiegare la differenza. git diff --color-wordsfunziona.
Holloway,

4
Sì, git diff --color-wordsè la strada da percorrere nelle moderne versioni di git.
VasiliNovikov,

41

ydiff

Precedentemente chiamato cdiff, questo strumento può mostrare differenze affiancate , incrementali e colorate .

Invece di fare git diff, fai:

ydiff -s -w0

Questo si avvierà ydiffin modalità di visualizzazione affiancata per ciascuno dei file con differenze.

Installa con:

python3 -m pip install --user ydiff

-o-

brew install ydiff

Per git log, puoi usare:

ydiff -ls -w0

-w0rileva automaticamente la larghezza del tuo terminale. Vedi la ydiff pagina del repository GitHub per dettagli e demo.

Testato in Git 2.18.0, ydiff 1.1.


@RyneEverett: puoi spiegare come fare l'equivalente git diff | cdiff -scon icdiff?
einpoklum,

ydiff -s
Esegui

se vuoi limitare il diff a un file specifico attraverso la cronologia di Git, cd <git repo>e poi eseguiydiff -ls <path/to/file>
slm

22

Si può fare un side-by-side diffcon sdiffil seguente:

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

dov'è HEAD^un esempio che dovresti sostituire con qualunque cosa tu voglia diff.

Ho trovato questa soluzione qui dove ci sono anche un paio di altri suggerimenti. Tuttavia, questa risposta è la domanda del PO in modo succinto e chiaro.

Vedi l' uomo git-difftool per una spiegazione degli argomenti.


Prendendo in considerazione i commenti, puoi creare un comodo git sdiffcomando scrivendo il seguente script eseguibile:

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

Salvalo come /usr/bin/git-sdiffe chmod -x. Quindi sarai in grado di fare questo:

$ git sdiff HEAD^

Di solito faccio "$ git difftool -x 'sdiff -s -w 240'" (o qualunque sia la larghezza dello schermo) se / quando voglio sopprimere le stesse linee e c'è solo un file (altrimenti faccio vimdiff)
HidekiAI

1
@HidekiAI Trovo un dolore di tipo terminale larghezza ogni volta, per cui uso tput cols, invece, ad esempio: git difftool -x "sdiff -s -w $(tput cols)".
Jaume,

può evidenziare i cambiamenti di colore? In questo momento sembra che dobbiamo usare i nostri occhi per individuare quali sono effettivamente i cambiamenti
polarità il

Sostituisci sdiff con icdiff per ottenere un bel display a colori.
Greg

10
export GIT_EXTERNAL_DIFF='meld $2 $5; echo >/dev/null'

quindi semplicemente:

git diff

1
"fusione". funziona anche! E mostra tutte le modifiche in una finestra consolidata.
HRJ,

@HRJ che funziona perfettamente! Così semplice e pratico :)
waldyrious il

9

Se desideri visualizzare le differenze side-by-side in un browser senza coinvolgere GitHub, potresti goderti git webdiff , un sostituto drop-in per git diff:

$ pip install webdiff
$ git webdiff

Ciò offre una serie di vantaggi rispetto ai difftools della GUI tradizionale, tkdiffin quanto può darti l'evidenziazione della sintassi e mostrare le differenze dell'immagine.

Leggi di più qui .


7

Uso colordiff .

Su Mac OS X, installalo con

$ sudo port install colordiff

Su Linux è forse apt get install colordiffo qualcosa del genere, a seconda della tua distribuzione.

Poi:

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

O crea un alias

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

Quindi puoi usarlo

$ git diffy HEAD^ HEAD

L'ho chiamato "diffy" perché diff -yè la differenza side-by-side in unix. Colordiff aggiunge anche colori, che sono più belli. Nell'opzione -ydw, yè per side-by-side, wè per ignorare gli spazi bianchi e dè per produrre il minimo diff (di solito si ottiene un risultato migliore come diff)


aggiungi -yper saltare il Launch 'colordiff' [Y/n]:prompt.
Beni Cherniavsky-Paskin,

ne sei sicuro git alias diffy "difftool --extcmd=\"colordiff -ydw\""? Non dovrebbe essere git config --global alias.diffy "difftool --extcmd=\"colordiff -ydw\""?
polarità

6

Per unix, combinando just gite il built-in diff:

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

Ovviamente, puoi sostituire HEAD con qualsiasi altro riferimento git e probabilmente vorrai aggiungere qualcosa di simile -W 170al comando diff.

Ciò presuppone che stai solo confrontando i contenuti della tua directory con un commit passato. Il confronto tra due commit è più complesso. Se la tua shell è bash, puoi usare la "sostituzione del processo":

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

dove REF1e REF2sono riferimenti git - tag, rami o hash.


Grazie - il tuo comando 'git show HEAD: path / to / file' era quello di cui avevo bisogno per trovare la mia soluzione, 'vimdfiff <(git show HEAD: path / to / file) path / to / file'. I bit non sono ancora allineati correttamente, ma questa è la soluzione migliore che ho adesso.
talexb,

5

Personalmente mi piace davvero icdiff !

Se siete in Mac OS Xcon HomeBrew, basta fare brew install icdiff.

Per ottenere correttamente le etichette dei file, oltre ad altre interessanti funzioni, ho nel mio ~/.gitconfig:

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

E lo uso come: git difftool


3

Questa domanda è emersa quando stavo cercando un modo rapido per usare git builtin in modo da individuare le differenze. I miei criteri di soluzione:

  • Avvio rapido, opzioni integrate necessarie
  • Può gestire facilmente molti formati, XML, diversi linguaggi di programmazione
  • Identifica rapidamente piccole modifiche al codice in file di testo di grandi dimensioni

Ho trovato questa risposta per ottenere colore in git.

Per affiancare diff invece che diff line ho modificato l'eccellente risposta di mb14 su questa domanda con i seguenti parametri:

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

Se non ti piace il extra [- o {+, è --word-diff=colorpossibile utilizzare l'opzione .

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

Ciò ha contribuito a ottenere un corretto confronto sia con il testo json e xml che con il codice java.

In sintesi, le --word-diff-regexopzioni hanno una visibilità utile insieme alle impostazioni del colore per ottenere un'esperienza di codice colore affiancata rispetto al diff di linea standard, quando si sfogliano file di grandi dimensioni con piccoli cambiamenti di linea.


3

Molti altri hanno già menzionato cdiff per git side-by-side diffing, ma nessuno ne ha dato piena attuazione.

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

Modifica ~ / .gitconfig inserendo queste righe:

[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

Il cercapersone disattivato è necessario affinché cdiff funzioni con Diff, è comunque essenzialmente un cercapersone, quindi va bene. Difftool funzionerà indipendentemente da queste impostazioni.

L'alias show è necessario perché git show supporta solo strumenti diff esterni tramite argomento.

Il '#' alla fine del comando esterno diff è importante. Il comando diff di Git aggiunge $ @ (tutte le variabili diff disponibili) al comando diff, ma vogliamo solo i due nomi di file. Quindi chiamiamo quei due in modo esplicito con $ 2 e $ 5, quindi nascondiamo $ @ dietro un commento che altrimenti confonderebbe sdiff. Il risultato è un errore simile a:

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

Comandi Git che ora producono la differenza side-by-side:

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

Utilizzo di Cdiff:

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

Ora hai diff side-by-side via git diff e difftool. E hai il codice sorgente cdiff python per la personalizzazione di power user se ne hai bisogno.


2

Ecco un approccio. Se installi meno, la larghezza xterm è impostata su 80, che non è così caldo. Ma se si procede con il comando, ad esempio COLS = 210, è possibile utilizzare xterm espanso.

gitdiff()
{
    local width=${COLS:-$(tput cols)}
    GIT_EXTERNAL_DIFF="diff -yW$width \$2 \$5; echo >/dev/null" git diff "$@"
}

1
Divertente. Ho firmato per nome con uno pseudonimo ma che è stato ignorato ... Grazie per avermi fatto uscire, Stack Overflow. :(
Thomas Mellman,

2

Apri Intellij IDEA , seleziona uno o più commit nella finestra dello strumento "Controllo versione", sfoglia i file modificati e fai doppio clic su di essi per controllare le modifiche fianco a fianco per ogni file.

Con il programma di avvio della riga di comando in bundle è possibile portare IDEA ovunque con un semplice idea some/path

vista controllo versione vista diff


1

Ci sono molte buone risposte su questo thread. La mia soluzione a questo problema era scrivere una sceneggiatura.

Assegna un nome a "git-scriptname" (e rendilo eseguibile e inseriscilo nel tuo PERCORSO, come qualsiasi script), e puoi invocarlo come un normale comando git eseguendo

$ git scriptname

La funzionalità effettiva è solo l'ultima riga. Ecco la fonte:

#!/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

1

Questa potrebbe essere una soluzione un po 'limitata, ma fa il lavoro usando il diffcomando del sistema senza strumenti esterni:

diff -y  <(git show from-rev:the/file/path) <(git show to-rev:the/file/path)
  • filtra solo le righe di modifica utilizzate --suppress-common-lines(se ladiff l'opzione è supportata).
  • nessun colore in questo caso, solo il solito diff pennarelli
  • può modificare la larghezza della colonna --width=term-width; in Bash puoi ottenere la larghezza come $COLUMNSo tput cols.

Questo può essere racchiuso in un helper git-script anche per una maggiore comodità, ad esempio un utilizzo come questo:

git diffy the/file/path --from rev1 --to rev2
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.