web-dev-qa-db-fra.com

Comment puis-je afficher la sortie 'git diff' avec mon outil de diff / visualiseur préféré?

Lorsque je tape git diff, je souhaite afficher la sortie avec l'outil de différenciation visuel de mon choix (SourceGear "diffmerge" sous Windows). Comment configurer git pour faire cela?

723
user3891

Depuis Git1.6.3, vous pouvez utiliser le script de git difftool : voir ma réponse ci-dessous .


Peut-être ceci article vous aidera. Voici les meilleures parties:

Il existe deux manières différentes de spécifier un outil de différenciation externe.

La première est la méthode que vous avez utilisée en définissant la variable GIT_EXTERNAL_DIFF. Cependant, la variable est supposée pointer vers le chemin complet de l'exécutable. De plus, l'exécutable spécifié par GIT_EXTERNAL_DIFF sera appelé avec un ensemble fixe de 7 arguments:

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

Comme la plupart des outils de diffs requièrent un ordre différent (et seulement certains) des arguments, vous devrez probablement spécifier un script d'encapsuleur, qui à son tour appelle le véritable outil de diff.

La deuxième méthode, que je préfère, consiste à configurer l'outil de diff externe via "git config" . Voici ce que j'ai fait:

1) Créez un script de wrapper "git-diff-wrapper.sh" qui contient quelque chose comme

-->8-(snip)--
#!/bin/sh

# diff is called by git with 7 parameters:
# path old-file old-hex old-mode new-file new-hex new-mode

"<path_to_diff_executable>" "$2" "$5" | cat
--8<-(snap)--

Comme vous pouvez le constater, seuls les deuxième ("ancien-fichier") et le cinquième ("nouveau-fichier") arguments seront passés à l'outil diff.

2) Type

$ git config --global diff.external <path_to_wrapper_script>

à l'invite de commande, en remplaçant par le chemin d'accès à "git-diff-wrapper.sh", votre ~/.gitconfig contient donc

-->8-(snip)--
[diff]
    external = <path_to_wrapper_script>
--8<-(snap)--

Veillez à utiliser la syntaxe correcte pour spécifier les chemins du script wrapper et de l’outil diff, c’est-à-dire utiliser des barres obliques au lieu de barres obliques inverses. Dans mon cas, j'ai

[diff]
    external = \"c:/Documents and Settings/sschuber/git-diff-wrapper.sh\"

dans .gitconfig et

"d:/Program Files/Beyond Compare 3/BCompare.exe" "$2" "$5" | cat

dans le script wrapper. Attention au "chat"!

(Je suppose que le '| cat' n'est nécessaire que pour certains programmes qui peuvent ne pas renvoyer un statut de retour correct ou cohérent. Vous pouvez essayer sans le chat de fin si votre outil diff a un statut de retour explicite)

( Diomidis Spinellis ajoute dans les commentaires :

La commande cat est requise, car diff(1) , se ferme par défaut avec un code d'erreur si les fichiers diffèrent.
Git s'attend à ce que le programme de diff externe se termine avec un code d'erreur uniquement si une erreur réelle s'est produite, par ex. s'il manque de mémoire.
En canalisant la sortie de git à cat, le code d'erreur différent de zéro est masqué.
Plus efficacement, le programme pourrait simplement exécuter exit avec un argument de 0.)


Ceci (l'article cité ci-dessus) est la théorie des outils externes définis via le fichier de configuration (et non par la variable d'environnement).
En pratique (toujours pour la définition du fichier de configuration d'un outil externe), vous pouvez vous référer à:

376
VonC

Pour compléter mon précédent "diff.external" config answer ci-dessus:

Comme mentionné par Jakub , Git 1.6.3 a introduit git difftool , initialement proposé en septembre 2008:

USAGE = '[--tool=tool] [--commit=ref] [--start=ref --end=ref] [--no-Prompt] [file to merge]'
(Voir --extcmd dans la dernière partie de cette réponse)

$LOCAL contient le contenu du fichier de la révision de départ et $REMOTE contient le contenu du fichier de la révision finale.
$BASE contient le contenu du fichier dans le monde

Il est fondamentalement git-mergetool modifié pour fonctionner sur l'index/arbre de travail git.

Le cas d'utilisation habituel de ce script est lorsque vous avez des modifications planifiées ou non mises en scène et que vous souhaitez voir les modifications dans un visualiseur de différences côte à côte (par exemple, xxdiffname__, tkdiffname__, etc.).

git difftool [<filename>*]

Un autre cas d'utilisation est celui où vous souhaitez voir la même information mais comparez des commits arbitraires (c'est la partie où l'analyse syntaxique pourrait être meilleure)

git difftool --start=HEAD^ --end=HEAD [-- <filename>*]

Le dernier cas d’utilisation correspond au moment où vous souhaitez comparer votre arbre de travail actuel à autre chose que HEAD (par exemple une balise).

git difftool --commit=v1.0.0 [-- <filename>*]

Note: depuis Git 2.5, git config diff.tool winmerge suffit!
Voir " git mergetool winmerge "

Et depuis Git 1.7.11 , vous avez l'option --dir-diff, afin de générer des outils de diff externes capables de comparer deux hiérarchies de répertoires à la fois après avoir rempli deux répertoires temporaires, au lieu d'exécuter une instance du outil externe une fois par paire de fichiers.


Avant Git 2.5:

Cas pratique pour configurer difftoolavec votre outil de différenciation personnalisé:

C:\myGitRepo>git config --global diff.tool winmerge
C:\myGitRepo>git config --global difftool.winmerge.cmd "winmerge.sh \"$LOCAL\" \"$REMOTE\""
C:\myGitRepo>git config --global difftool.Prompt false

Avec winmerge.sh stocké dans une partie du répertoire de votre PATH:

#!/bin/sh
echo Launching WinMergeU.exe: $1 $2
"C:/Program Files/WinMerge/WinMergeU.exe" -u -e "$1" "$2" -dl "Local" -dr "Remote"

Si vous avez un autre outil (kdiff3, P4Diff, ...), créez un autre script Shell et la directive difftool.myDiffTool.cmd config appropriée.
Ensuite, vous pouvez facilement changer d’outil avec le diff.tool config.

Vous avez également ceci entrée de blog par Dave pour ajouter d'autres détails.
(Ou cette question pour les options winmergeuname__)

L’intérêt de ce paramètre est le winmerge.shscript : vous pouvez le personnaliser pour prendre en compte des cas particuliers.

Voir par exemple David Marble 's réponse ci-dessous pour un exemple traitant de:

  • nouveaux fichiers d'origine ou de destination
  • fichiers supprimés dans leur origine ou leur destination

Comme Kem Mason mentionne sa réponse , vous pouvez également éviter tout emballage en utilisant l'option --extcmd:

--extcmd=<command>

Spécifiez une commande personnalisée pour afficher les différences. git-difftool ignore les valeurs par défaut configurées et s'exécute $command $LOCAL $REMOTE lorsque cette option est spécifiée.

Par exemple, voici comment gitkNAME__ PEUT EXÉCUTER/UTILISER N’IMPORTE QUEL OUTIL diffNAME_ .

204
VonC

Dans l’esprit de répondre à des questions quelque peu différentes de celles posées. Essayez cette solution:

$ meld my_project_using_git

Meld comprend git et fournit une navigation autour des modifications récentes.

108
Charles Merriam

Depuis la version 1.6.3 de Git, il y a "git difftool" que vous pouvez configurer pour utiliser votre outil de diff graphique préféré. kdiff3, kompare, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, diffuse et opendiff sont actuellement pris en charge ; si l'outil que vous souhaitez utiliser ne figure pas dans cette liste, vous pouvez toujours utiliser l'option de configuration 'difftool.<tool>.cmd'.

"git difftool" accepte les mêmes options que "git diff".

40
Jakub Narębski

Avec le nouveau git difftool , il suffit d’ajouter ceci à votre fichier . Gitconfig :

[diff]
    tool = any-name
[difftool "any-name"]
    cmd = "\"C:/path/to/my/ext/diff.exe\" \"$LOCAL\" \"$REMOTE\""

Vérifiez également diffall , un script simple que j'ai écrit pour étendre la comportement par défaut gênant (IMO) par défaut d’ouverture en série.

36
Seba Illingworth

J'ai un ajout à cela. J'aime utiliser régulièrement une application de diff qui n'est pas prise en charge par l'un des outils par défaut (kaléidoscope, par exemple), via

git difftool -t

J'aime également que la valeur par défaut diffsoit simplement la ligne de commande habituelle. La définition de la variable GIT_EXTERNAL_DIFF n'est donc pas une option.

Vous pouvez utiliser une application diffarbitraire comme application unique avec cette commande:

git difftool --extcmd=/usr/bin/ksdiff

Il passe simplement les 2 fichiers à la commande que vous spécifiez, vous n'avez donc probablement pas besoin d'un wrapper non plus.

23
Kem Mason

En vous appuyant sur la réponse de VonC pour traiter les suppressions et les ajouts de fichiers, utilisez les commandes et les scripts suivants:

> git config --global diff.tool winmerge
> git config --global difftool.winmerge.cmd "winmerge.sh \"$LOCAL\" \"$REMOTE\" \"$BASE\""
> git config --global difftool.Prompt false

Ce qui revient à placer ceci dans votre .gitconfig global:

[diff]
    tool = winmerge
[difftool "winmerge"]
    cmd = winmerge.bat "$LOCAL" "$REMOTE" "$BASE"
[difftool]
    Prompt = false

Ensuite, mettez ce qui suit dans winmerge.shqui doit être sur votre chemin:

#!/bin/sh
NULL="/dev/null"
if [ "$2" = "$NULL" ] ; then
    echo "removed: $3"
Elif [ "$1" = "$NULL" ] ; then
    echo "added: $3"
else
    echo "changed: $3"
    "C:/Program Files (x86)/WinMerge/WinMergeU.exe" -e -ub -dl "Base" -dr "Mine" "$1" "$2"
fi
17
David Marble

Solution pour Windows/msys git

Après avoir lu les réponses, j'ai découvert un moyen plus simple qui consiste à changer un seul fichier.

  1. Créez un fichier de commandes pour appeler votre programme diff, avec les arguments 2 et 5. Ce fichier doit se trouver quelque part dans votre chemin. (Si vous ne savez pas où cela se trouve, mettez-le dans c:\windows). Appelez-le, par exemple, "gitdiff.bat". Le mien est:

    @echo off
    REM This is gitdiff.bat
    "C:\Program Files\WinMerge\WinMergeU.exe" %2 %5
    
  2. Définissez la variable d'environnement pour qu'elle pointe vers votre fichier de commandes. Par exemple: GIT_EXTERNAL_DIFF=gitdiff.bat. Ou via powershell en tapant git config --global diff.external gitdiff.bat.

    Il est important de ne pas utiliser de guillemets ni de spécifier des informations de chemin, sinon cela ne fonctionnera pas. C'est pourquoi gitdiff.bat doit être sur votre chemin.

Désormais, lorsque vous tapez "git diff", votre visualiseur de différences externe est appelé.

11
Steve Hanov

Si vous le faites via cygwin, vous devrez peut-être utiliser cygpath:

$ git config difftool.bc3.cmd "git-diff-bcomp-wrapper.sh \$LOCAL \$REMOTE"
$ cat git-diff-bcomp-wrapper.sh
#!/bin/sh
"c:/Program Files (x86)/Beyond Compare 3/BComp.exe" `cygpath -w $1` `cygpath -w $2`
9
idbrii

Après avoir examiné d'autres outils de diff externes, j'ai constaté que la vue diff dans IntelliJ IDEA (et Android Studio) était la meilleure pour moi.

Étape 1 - Configuration d'IntelliJ IDEA à exécuter à partir de la ligne de commande

Si vous souhaitez utiliser IntelliJ IDEA comme outil de différenciation, vous devez d'abord configurer IntelliJ IDEA à exécuter à partir de la ligne de commande en suivant les instructions ici :

Sous MacOS ou UNIX:

  1. Assurez-vous que IntelliJ IDEA est en cours d'exécution.
  2. Dans le menu principal, choisissez Tools | Create Command-line Launcher. La boîte de dialogue Créer un script de lancement s'ouvre avec le chemin d'accès suggéré et le nom du script de lancement. Vous pouvez accepter les valeurs par défaut ou spécifier votre propre chemin. Notez-le, vous en aurez besoin plus tard. En dehors d'IntelliJ IDEA, ajoutez le chemin d'accès et le nom du script de lancement à votre chemin.

Sous Windows:

  1. Spécifiez l'emplacement de l'exécutable IntelliJ IDEA dans la variable d'environnement du système Path. Dans ce cas, vous pourrez appeler l'exécutable IntelliJ IDEA et d'autres commandes IntelliJ IDEA à partir de n'importe quel répertoire.

Étape 2 - configurez git pour utiliser IntelliJ IDEA en tant que difftool

En suivant les instructions sur cet article de blog :

Bash

export INTELLIJ_HOME /Applications/IntelliJ\ IDEA\ CE.app/Contents/MacOS
PATH=$IDEA_HOME $PATH

Poisson

set INTELLIJ_HOME /Applications/IntelliJ\ IDEA\ CE.app/Contents/MacOS
set PATH $INTELLIJ_HOME $PATH

Ajoutez maintenant les éléments suivants à votre configuration git:

[merge]
   tool = intellij
[mergetool "intellij"]
   cmd = idea merge $(cd $(dirname "$LOCAL") && pwd)/$(basename "$LOCAL") $(cd $(dirname "$REMOTE") && pwd)/$(basename "$REMOTE") $(cd $(dirname "$BASE") && pwd)/$(basename "$BASE") $(cd $(dirname "$MERGED") && pwd)/$(basename "$MERGED")
   trustExitCode = true
[diff]
   tool = intellij
[difftool "intellij"]
   cmd = idea diff $(cd $(dirname "$LOCAL") && pwd)/$(basename "$LOCAL") $(cd $(dirname "$REMOTE") && pwd)/$(basename "$REMOTE")

Vous pouvez l'essayer avec git difftool ou git difftool HEAD~1

8
David Rawson

Un bref résumé des bonnes réponses ci-dessus:

git difftool --tool-help
git config --global diff.tool <chosen tool>
git config --global --add difftool.Prompt false

Puis utilisez-le en tapant (en spécifiant éventuellement le nom du fichier):

git difftool
7
user2443147

cela fonctionne pour moi sur Windows 7. Pas besoin de scripts sh intermédiaires

contenu de .gitconfig:

    [diff]
      tool = kdiff3

    [difftool]
       Prompt = false

    [difftool "kdiff3"]
      path = C:/Program Files (x86)/KDiff3/kdiff3.exe
      cmd = "$LOCAL" "$REMOTE"
7
Sharas

Voici un fichier de commandes qui fonctionne pour Windows - suppose que DiffMerge est installé à l'emplacement par défaut, gère x64, gère le remplacement de la barre oblique inversée si nécessaire et est capable de s'installer lui-même. Devrait être facile de remplacer DiffMerge par votre programme de diff préféré.

À installer:

gitvdiff --install 

gitvdiff.bat:

@echo off

REM ---- Install? ----
REM To install, run gitvdiff --install

if %1==--install goto install



REM ---- Find DiffMerge ----

if DEFINED ProgramFiles^(x86^) (
    Set DIFF="%ProgramFiles(x86)%\SourceGear\DiffMerge\DiffMerge.exe"
) else (
    Set DIFF="%ProgramFiles%\SourceGear\DiffMerge\DiffMerge.exe"
)



REM ---- Switch forward slashes to back slashes ----

set oldW=%2
set oldW=%oldW:/=\%
set newW=%5
set newW=%newW:/=\%


REM ---- Launch DiffMerge ----

%DIFF% /title1="Old Version" %oldW% /title2="New Version" %newW%

goto :EOF



REM ---- Install ----
:install
set selfL=%~dpnx0
set selfL=%selfL:\=/%
@echo on
git config --global diff.external %selfL%
@echo off


:EOF
6
Brad Robinson

Si vous utilisez un Mac et que vous avez le code X, FileMerge est installé. La commande de terminal est opendiff, vous pouvez donc simplement faire git difftool -t opendiff

6
LuxuryMode

Introduction

Pour référence, j'aimerais inclure ma variation sur la réponse de VonC. N'oubliez pas que j'utilise la version MSys de Git (1.6.0.2 pour le moment) avec PATH modifié et que j'exécute Git lui-même à partir de Powershell (ou cmd.exe), et non de Bash Shell.

J'ai introduit une nouvelle commande, gitdiff. L'exécution de cette commande redirige temporairement git diff vers un programme de différenciation visuelle de votre choix (contrairement à la solution de VonC qui le fait de manière permanente). Cela me permet d’avoir à la fois la fonctionnalité par défaut de Git diff (git diff) ainsi que la fonctionnalité de diff visuelle (gitdiff). Les deux commandes utilisent les mêmes paramètres. Par exemple, vous pouvez saisir, par exemple, les différences visuelles dans un fichier donné.

gitdiff path/file.txt

Installer

Notez que $GitInstall est utilisé comme espace réservé pour le répertoire où Git est installé.

  1. Créez un nouveau fichier, $GitInstall\cmd\gitdiff.cmd

    @echo off
    setlocal
    for /F "delims=" %%I in ("%~dp0..") do @set path=%%~fI\bin;%%~fI\mingw\bin;%PATH%
    if "%HOME%"=="" @set HOME=%USERPROFILE%
    set GIT_EXTERNAL_DIFF=git-diff-visual.cmd
    set GIT_PAGER=cat
    git diff %*
    endlocal
    
  2. Créez un nouveau fichier, $GitInstall\bin\git-diff-visual.cmd (en remplacement de l'espace réservé [visual_diff_exe] par le chemin complet du programme diff de votre choix)

    @echo off
    rem diff is called by git with 7 parameters:
    rem path old-file old-hex old-mode new-file new-hex new-mode
    echo Diffing "%5"
    "[visual_diff_exe]" "%2" "%5"
    exit 0
    
  3. Vous avez maintenant terminé. L'exécution de gitdiff à partir d'un référentiel Git devrait maintenant appeler votre programme diff visuel pour chaque fichier modifié.

6
Milan Gardian

Pour une version Linux de la façon de configurer un outil de diff sur les versions de git antérieures à 1.6.3 (1.6.3 a ajouté difftool à git) this est un excellent didacticiel concis,

en bref:

Etape 1: ajoutez ceci à votre .gitconfig

[diff]
  external = git_diff_wrapper
[pager]
  diff =

Étape 2: créez un fichier nommé git_diff_wrapper, placez-le quelque part dans votre $ PATH

#!/bin/sh

vimdiff "$2" "$5"
5
Fire Crow

Installer la fusion

 # apt-get install meld

Puis choisissez comme difftool

 $ git config --global diff.tool meld

Si vous voulez l'exécuter sur le type de console:

 $ git difftool

Si vous souhaitez utiliser le type de mode graphique:

 $ git mergetool

Et le résultat serait:

 'git mergetool' will now attempt to use one of the following tools:
 meld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse
 diffmerge ecmerge p4merge araxis bc3 codecompare emerge vimdiff
 Merging:
 www/css/style.css
 www/js/controllers.js

 Normal merge conflict for 'www/css/style.css':
   {local}: modified file
   {remote}: modified file
 Hit return to start merge resolution tool (meld):

Il suffit donc d’appuyer sur Entrée pour utiliser meld (valeur par défaut). Cela ouvrirait le mode graphique, effectuerait une sauvegarde magique et appellerait cette opération pour résoudre la fusion. C'est tout

5
G. I. Joe

Sur Mac OS X,

git difftool -t diffuse 

fait le travail pour moi dans le dossier git. Pour installer diffuse, on peut utiliser le port -

Sudo port install diffuse
4
Shreyas

vous pouvez utiliser git difftool.

par exemple, si vous avez meld , vous pouvez modifier les branches masteret develde:

git config --global diff.external meld
git difftool master..devel
3
suhailvs

Ce qui suit peut être dégagé des autres réponses ici, mais pour moi c'est difficile, (trop d'informations), alors voici la réponse 'il suffit de taper dans' pour tkdiff:

git difftool --tool=tkdiff <path to the file to be diffed>

Vous pouvez remplacer le nom de l'exécutable de votre outil de diffing préféré par tkdiff. Tant que (par exemple, tkdiff), (ou votre outil de diffing préféré) est dans votre CHEMIN, il sera lancé.

2
dolphus333

J'ai essayé les trucs sophistiqués ici (avec tkdiff) et rien n'a fonctionné pour moi. J'ai donc écrit le script suivant, tkgitdiff. Il fait ce que j'ai besoin de faire.

$ cat tkgitdiff
#!/bin/sh

#
# tkdiff for git.
# Gives you the diff between HEAD and the current state of your file.
#

newfile=$1
git diff HEAD -- $newfile > /tmp/patch.dat
cp $newfile /tmp
savedPWD=$PWD
cd /tmp
patch -R $newfile < patch.dat
cd $savedPWD
tkdiff /tmp/$newfile $newfile
2
Theodore Sternberg

J'utilise ce bit dans ~/.gitconfig depuis longtemps:

[diff]
    external = ~/Dropbox/source/bash/git-meld

Avec git-meld:

#!/bin/bash
if [ "$DISPLAY" = "" ];
then
    diff $2 $5
else
    meld $2 $5
fi

Mais maintenant, j'en ai eu marre de toujours utiliser meld dans un environnement graphique, et il n'est pas anodin d'invoquer le diff normal avec cette configuration.

[alias]
    v =  "!sh -c 'if [ $# -eq 0 ] ; then git difftool -y -t meld ; else git difftool -y $@ ; fi' -"

Avec cette configuration, des choses comme celle-ci fonctionnent:

git v
git v --staged
git v -t kompare
git v --staged -t tkdiff

Et je garde toujours le bon vieux git diff.

1
abo-abo

Si vous avez déjà un outil de diff associé à des types de fichiers (par exemple, parce que vous avez installé TortoiseSVN qui est livré avec un visualiseur de diff), vous pouvez simplement diriger la sortie normale de git diff vers un fichier "temp", puis simplement ouvrir ce fichier directement rien savoir sur le spectateur:

git diff > "~/temp.diff" && start "~/temp.diff"

Le définir comme un alias global fonctionne encore mieux: git what

[alias]
    what = "!f() { git diff > "~/temp.diff" && start "~/temp.diff"; }; f"
0
drzaus

Vous voudrez peut-être essayer xd http://github.com/jiqingtang/xd , qui est une interface graphique pour les différences GIT/SVN. Ce n'est pas un outil de diff en soi. Vous exécutez xd lorsque vous souhaitez exécuter git diff ou svn diff et il vous montrera une liste de fichiers, une fenêtre d'aperçu et vous pourrez lancer n'importe quel outil de différenciation, y compris tkdiff, xxdiff, gvimdiff, emacs (ediff), xemacs (ediff) , fondre, diffuser, kompare et kdiff3. Vous pouvez également exécuter n'importe quel outil personnalisé.

Malheureusement, l'outil ne supporte pas Windows.

Divulgation : Je suis l'auteur de cet outil.

0
Jiqing Tang

J'utilise kompare sur Ubuntu:

Sudo apt-get install kompare

Pour comparer deux branches:

git difftool -t kompare <my_branch> master
0
Bilal and Olga

Si vous n'êtes pas un utilisateur de la ligne de commande, si vous installez Tortoise git, vous pouvez cliquer avec le bouton droit de la souris sur un fichier pour obtenir un sous-menu tortoisegit avec l'option "Diff later".

Lorsque vous sélectionnez cette option sur le premier fichier, vous pouvez alors cliquer avec le bouton droit de la souris sur le deuxième fichier, accéder au sous-menu tortoisegit et sélectionner "Diff with == yourfilehere ==". Le résultat sera alors donné à l’interface tortoisegitmerge.

0
user3270579