Comment puis-je obtenir un différentiel côte à côte lorsque je fais "git diff"?

163

Quand je tape "git diff", j'aimerais voir un diff côte à côte, comme avec "diff -y", ou j'aime afficher le diff dans un outil de diff interactif comme "kdiff3". Comment cela peut-il être fait?

Mike
la source

Réponses:

89

Bien que Git ait une implémentation interne de diff, vous pouvez configurer un outil externe à la place.

Il existe deux manières différentes de spécifier un outil de comparaison externe:

  1. la définition des GIT_EXTERNAL_DIFFet les GIT_DIFF_OPTSvariables d' environnement.
  2. configuration de l'outil de diff externe via git config

Voir également:

Lors de l' git diffexécution de a, Git vérifie à la fois les paramètres des variables d'environnement ci-dessus et son .gitconfigfichier.

Par défaut, Git transmet les sept arguments suivants au programme diff:

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

Vous n'avez généralement besoin que des paramètres ancien et nouveau fichier. Bien sûr, la plupart des outils de diff ne prennent que deux noms de fichiers comme argument. Cela signifie que vous devez écrire un petit script wrapper, qui prend les arguments fournis par Git au script et les transmet au programme git externe de votre choix.

Disons que vous mettez votre wrapper-script sous ~/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"

vous devez ensuite rendre ce script exécutable:

chmod a+x ~/scripts/my_diff.sh

vous devez ensuite indiquer à Git comment et où trouver votre script de wrapper de diff personnalisé. Vous avez trois choix pour faire cela: (je préfère éditer le fichier .gitconfig)

  1. Utilisation GIT_EXTERNAL_DIFF,GIT_DIFF_OPTS

    Par exemple, dans votre fichier .bashrc ou .bash_profile, vous pouvez définir:

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

    utilisez "git config" pour définir où votre script wrapper peut être trouvé:

    git config --global diff.external ~/scripts/my_diff.sh
    
  3. Modifier votre ~/.gitconfigfichier

    vous pouvez éditer votre ~/.gitconfigfichier pour ajouter ces lignes:

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

Remarque:

De la même manière que pour installer votre outil de comparaison personnalisé, vous pouvez également installer un outil de fusion personnalisé, qui pourrait être un outil de fusion visuel pour mieux vous aider à visualiser la fusion. (voir la page progit.org)

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

Tilo
la source
1
Est-ce que cela conserve la coloration du terminal git?
Sridhar Sarnobat
3
C'est génial, mais cela lance une nouvelle visionneuse pour chaque fichier. Un moyen de créer un diff consolidé, par exemple meld?
HRJ
2
@Tilo J'obtiens une erreur pour vim comme im: Attention: la sortie n'est pas vers un terminal
programmeur mort
La meldversion peut-elle être configurée pour faire une différence de répertoire, où je peux choisir pour quel (s) fichier (s) je veux voir la différence? Actuellement, il exécute une meldcommande distincte pour chaque fichier et je dois quitter meldpour voir le fichier suivant. Je préférerais meldme montrer une liste de répertoires des fichiers modifiés comme il se comporte lorsqu'il meldest utilisé à partir de Mercurial.
kasperd le
163

Essayez git difftool

Utilisez à la git difftoolplace de git diff. Vous ne reviendrez jamais.

MISE À JOUR pour ajouter un exemple d'utilisation:

Voici un lien vers un autre stackoverflow qui parle de git difftool: Comment afficher la sortie de 'git diff' avec mon outil / visionneuse de diff préféré?

Pour les versions plus récentes de git, la difftoolcommande prend en charge de nombreux outils de comparaison externes prêts à l'emploi. Par exemple, il vimdiffest automatiquement pris en charge et peut être ouvert à partir de la ligne de commande par:

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

D'autres outils de diff externes pris en charge sont répertoriés via git difftool --tool-helpvoici un exemple de sortie:

'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
la source
34
Ou peut-être que vous y retournerez si vous obtenez This message is displayed because 'diff.tool' is not configured.. Peut-être mettre à jour la réponse avec un minimum de procédure pour configurer cette chose, afin qu'elle affiche les différences côte à côte dans le terminal, ce que OP a demandé? Les outils GUI sont tout à fait inutiles sur le serveur distant où vous vous connectez en utilisant ssh.
Petr
1
Point intéressant, bien que je ne pense pas avoir personnellement jamais eu besoin d'utiliser git en SSH. Une des bonnes choses à propos de DVCS est la partie distribuée: au moins dans mes environnements, ce n'est jamais un problème de cloner localement le dépôt que je veux fouiller.
Matt Ball
1
Au moins dans ma configuration, git difftoolavec vimdiffn'aligne pas toujours correctement les deux fichiers / tampons.
Rohmer
1
C'est bien, et ainsi de suite dans la liste de réponses: OI utilise git difftool -ypour empêcher l'invite
tkdiff
Connexes: faites fusionner votre git difftoolsous Windows et Linux: stackoverflow.com/a/48979939/4561887
Gabriel Staples
57

Vous pouvez également essayer git diff --word-diff. Ce n'est pas exactement côte à côte, mais mieux, donc vous pourriez le préférer à votre besoin réel côte à côte.

mb14
la source
12
C'est le moyen le plus simple. Ce qui est encore mieux c'estgit diff --word-diff=color
Rolf
@Rolf --word-diff=colorme donne une erreur d'option non valide. Dans quelle version a-t-il été introduit?
Holloway
@Trengot I run git 1.7.9 qui est de 02/2012
Rolf
4
La version installée par défaut de @Rolf ici est 1.7.1. Pourrait expliquer la différence. git diff --color-wordsfonctionne.
Holloway
4
Oui, git diff --color-wordsc'est la voie à suivre pour les versions git modernes.
VasiliNovikov
41

ydiff

Anciennement appelé cdiff, cet outil peut afficher des différences côte à côte , incrémentielles et colorées .

Au lieu de faire git diff, faites:

ydiff -s -w0

Cela se lancera ydiffen mode d'affichage côte à côte pour chacun des fichiers avec des différences.

Installer avec:

python3 -m pip install --user ydiff

-ou-

brew install ydiff

Pour git log, vous pouvez utiliser:

ydiff -ls -w0

-w0détecte automatiquement la largeur de votre terminal. Consultez la ydiff page du référentiel GitHub pour plus de détails et une démonstration.

Testé dans Git 2.18.0, ydiff 1.1.

ymattw
la source
@RyneEverett: Pouvez-vous expliquer comment faire l'équivalent de git diff | cdiff -swith icdiff?
einpoklum
Exécutez simplement à ydiff -spartir d'un espace de travail git / svn / hg, vous n'avez pas à
entrer
si vous souhaitez limiter la différence à un fichier spécifique via l'historique de Git, cd <git repo>puis exécutezydiff -ls <path/to/file>
slm
22

Vous pouvez faire un côte à côte en diffutilisant sdiffcomme suit:

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

HEAD^est un exemple que vous devez remplacer par tout ce que vous voulez comparer.

J'ai trouvé cette solution ici où il y a également quelques autres suggestions. Cependant, cette réponse est la question du PO de manière succincte et claire.

Voir le man git-difftool pour une explication des arguments.


En prenant les commentaires à bord, vous pouvez créer une git sdiffcommande pratique en écrivant le script exécutable suivant:

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

Enregistrez-le sous /usr/bin/git-sdiffet chmod -xil. Ensuite, vous pourrez faire ceci:

$ git sdiff HEAD^
starfry
la source
Je fais habituellement "$ git difftool -x 'sdiff -s -w 240'" (ou quelle que soit la largeur de l'écran) si / quand je veux supprimer les mêmes lignes et qu'il n'y a qu'un seul fichier (sinon je fais vimdiff)
HidekiAI
1
@HidekiAI Je trouve une douleur à taper la borne largeur à chaque fois, donc j'utiliser à la tput colsplace, par exemple: git difftool -x "sdiff -s -w $(tput cols)".
jaume
peut-il mettre en évidence les changements de couleur? À l'heure actuelle, il semble que nous devons utiliser nos yeux pour repérer quels sont réellement les changements
nonopolarité
Remplacez sdiff par icdiff pour obtenir un bel écran couleur.
Greg
10
export GIT_EXTERNAL_DIFF='meld $2 $5; echo >/dev/null'

puis simplement:

git diff
Krzych
la source
1
«fusionner. fonctionne aussi! Et il montre tous les changements dans une fenêtre consolidée.
HRJ
@HRJ qui fonctionne parfaitement! Si simple et pratique :)
waldyrious
9

Si vous souhaitez voir des différences côte à côte dans un navigateur sans impliquer GitHub, vous pouvez profiter de git webdiff , un remplacement instantané pour git diff:

$ pip install webdiff
$ git webdiff

Cela offre un certain nombre d'avantages par rapport aux outils de difftools GUI traditionnels, tkdiffen ce sens qu'il peut vous donner une coloration syntaxique et afficher des différences d'image.

En savoir plus ici .

danvk
la source
7

J'utilise colordiff .

Sous Mac OS X, installez-le avec

$ sudo port install colordiff

Sur Linux, c'est peut-être apt get install colordiffou quelque chose comme ça, en fonction de votre distribution.

Ensuite:

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

Ou créez un alias

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

Ensuite, vous pouvez l'utiliser

$ git diffy HEAD^ HEAD

Je l'ai appelé "diffy" parce que diff -yc'est le différentiel côte à côte sous Unix. Colordiff ajoute également des couleurs plus jolies. Dans l'option -ydw, le yest pour le côte à côte, le west d'ignorer les espaces blancs et le dest de produire le diff minimal (généralement vous obtenez un meilleur résultat en diff)

Luigi R. Viggiano
la source
ajouter -ypour ignorer l' Launch 'colordiff' [Y/n]:invite.
Beni Cherniavsky-Paskin
êtes-vous sûr que c'est le cas git alias diffy "difftool --extcmd=\"colordiff -ydw\""? Cela ne devrait-il pas être le cas git config --global alias.diffy "difftool --extcmd=\"colordiff -ydw\""?
nonopolarité le
6

Pour unix, en combinant juste gitet intégré diff:

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

Bien sûr, vous pouvez remplacer HEAD par toute autre référence git, et vous voudrez probablement ajouter quelque chose comme -W 170la commande diff.

Cela suppose que vous comparez simplement le contenu de votre répertoire avec une validation antérieure. La comparaison entre deux commits est plus complexe. Si votre shell est, bashvous pouvez utiliser la "substitution de processus":

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

REF1et REF2sont des références git - balises, branches ou hachages.

Walker Hale IV
la source
Merci - votre commande 'git show HEAD: chemin / vers / fichier' était ce dont j'avais besoin pour trouver ma propre solution, 'vimdfiff <(git show HEAD: chemin / vers / fichier) chemin / vers / fichier'. Les bits ne sont toujours pas alignés correctement, mais c'est la meilleure solution que j'ai en ce moment.
talexb
5

Personnellement, j'aime vraiment icdiff !

Si vous êtes d' Mac OS Xaccord HomeBrew, faites-le brew install icdiff.

Pour obtenir correctement les étiquettes de fichiers, ainsi que d'autres fonctionnalités intéressantes, j'ai dans mon ~/.gitconfig:

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

Et je l'utilise comme: git difftool

Jose Alban
la source
3

Cette question est apparue lorsque je cherchais un moyen rapide d'utiliser la manière intégrée git pour localiser les différences. Mes critères de solution:

  • Démarrage rapide, options intégrées nécessaires
  • Peut gérer facilement de nombreux formats, xml, différents langages de programmation
  • Identifiez rapidement les petits changements de code dans les gros fichiers texte

J'ai trouvé cette réponse pour obtenir de la couleur dans git.

Pour obtenir côte à côte diff au lieu de ligne diff, j'ai modifié l'excellente réponse de mb14 à cette question avec les paramètres suivants:

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

Si vous n'aimez pas le supplément [- ou {+, l'option --word-diff=colorpeut être utilisée.

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

Cela a aidé à obtenir une comparaison correcte avec le texte json et xml et le code java.

En résumé, les --word-diff-regexoptions ont une visibilité utile avec les paramètres de couleur pour obtenir une expérience de code source colorisée côte à côte par rapport au diff de ligne standard, lors de la navigation dans de gros fichiers avec de petits changements de ligne.

Mike
la source
3

Plusieurs autres ont déjà mentionné le cdiff pour git côte à côte, mais personne n'en a donné une implémentation complète.

CDiff d'installation:

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

Editez ~ / .gitconfig en insérant ces lignes:

[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

Le pager off est nécessaire pour que cdiff fonctionne avec Diff, c'est essentiellement un pager de toute façon donc c'est très bien. Difftool fonctionnera indépendamment de ces paramètres.

L'alias show est nécessaire car git show ne prend en charge que les outils de comparaison externes via l'argument.

Le '#' à la fin de la commande diff external est important. La commande diff de Git ajoute un $ @ (toutes les variables diff disponibles) à la commande diff, mais nous ne voulons que les deux noms de fichiers. Nous appelons donc ces deux explicitement avec $ 2 et $ 5, puis cachons le $ @ derrière un commentaire qui, autrement, confondrait sdiff. Il en résulte une erreur qui ressemble à:

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

Commandes Git qui produisent maintenant des différences côte à côte:

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

Utilisation Cdiff:

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

Vous avez maintenant des différences côte à côte via git diff et difftool. Et vous avez le code source cdiff python pour la personnalisation de l'utilisateur avancé si vous en avez besoin.

Eric
la source
2

Voici une approche. Si vous passez moins, la largeur xterm est définie sur 80, ce qui n'est pas si chaud. Mais si vous exécutez la commande avec, par exemple COLS = 210, vous pouvez utiliser votre xterm étendu.

gitdiff()
{
    local width=${COLS:-$(tput cols)}
    GIT_EXTERNAL_DIFF="diff -yW$width \$2 \$5; echo >/dev/null" git diff "$@"
}
Thomas Mellman
la source
1
Drôle. J'ai signé par nom avec un pseudonyme mais cela a été ignoré ... Merci de m'avoir sorti, Stack Overflow. :(
Thomas Mellman
2

Ouvrez Intellij IDEA , sélectionnez un ou plusieurs commits dans la fenêtre de l'outil "Contrôle de version", parcourez les fichiers modifiés et double-cliquez dessus pour inspecter les modifications côte à côte pour chaque fichier.

Avec le lanceur de ligne de commande fourni, vous pouvez amener IDEA n'importe où avec un simple idea some/path

vue de contrôle de version vue diff

Holger Brandl
la source
1

Il y a beaucoup de bonnes réponses sur ce fil. Ma solution à ce problème était d'écrire un script.

Nommez ce 'git-scriptname' (et rendez-le exécutable et placez-le dans votre PATH, comme n'importe quel script), et vous pouvez l'invoquer comme une commande git normale en exécutant

$ git scriptname

La fonctionnalité réelle n'est que la dernière ligne. Voici la source:

#!/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
la source
1

Cela peut être une solution quelque peu limitée, mais fait le travail en utilisant la diffcommande du système sans outils externes:

diff -y  <(git show from-rev:the/file/path) <(git show to-rev:the/file/path)
  • filtrer uniquement les lignes de changement d'utilisation --suppress-common-lines(si votre diffsupporte l'option).
  • pas de couleurs dans ce cas, juste les diffmarqueurs habituels
  • peut modifier la largeur de la colonne --width=term-width; dans Bash peut obtenir la largeur comme $COLUMNSou tput cols.

Cela peut également être enveloppé dans un script d'aide git pour plus de commodité, par exemple, une utilisation comme celle-ci:

git diffy the/file/path --from rev1 --to rev2
nomadbyte
la source