Comment visualiser les différences par caractère dans un fichier diff unifié?

122

Disons que je reçois un patch créé avec git format-patch. Le fichier est essentiellement un diff unifié avec quelques métadonnées. Si j'ouvre le fichier dans Vim, je peux voir quelles lignes ont été modifiées, mais je ne peux pas voir quels caractères dans les lignes modifiées diffèrent. Quelqu'un connaît-il un moyen (dans Vim, ou dans un autre logiciel gratuit qui fonctionne sur Ubuntu) de visualiser les différences par caractère?

Un exemple de compteur où la différence par caractère est visualisée est lors de l'exécution vimdiff a b.

mise à jour Ven 12 novembre 22:36:23 UTC 2010

diffpatch est utile pour le scénario où vous travaillez avec un seul fichier.

mise à jour jeu.16 juin 17:56:10 UTC 2016

Découvrez diff-highlight dans git 2.9 . Ce script fait exactement ce que je cherchais à l'origine.

Adam Monsen
la source
Cela pourrait être mieux sur superuser.com
Daenyth
13
Peut-être. J'ai choisi stackoverflow.com car la FAQ mentionne que c'est l'endroit pour les questions sur les "outils logiciels couramment utilisés par les programmeurs"
Adam Monsen
7
Je ne suis pas sûr que cela réponde directement à votre question, mais git diff --color-wordsc'est très utile pour simplement voir quels mots ont changé dans les lignes, plutôt que la sortie diff unifiée habituelle. Il est basé sur des mots plutôt que sur des caractères, donc s'il n'y a pas beaucoup d'espaces dans le contenu que vous différez, la sortie peut être moins soignée. (Modifié: Oups, je vois que j'ai mal compris ce que vous demandez - néanmoins peut-être que ce commentaire serait utile à quelqu'un.)
Mark Longair

Réponses:

13

Compte tenu de vos références à Vim dans la question, je ne sais pas si c'est la réponse que vous voulez :) mais Emacs peut le faire. Ouvrez le fichier contenant le diff, assurez-vous que vous êtes dans diff-mode(si le fichier est nommé foo.diffou que foo.patchcela se produit automatiquement; sinon tapez M-x diff-mode RET), accédez au morceau qui vous intéresse et cliquez C-c C-bsur refine-hunk. Ou parcourez le fichier un morceau à la fois avec M-n; cela fera le raffinage automatiquement.

legoscia
la source
1
Travaille pour moi! Hé, j'utilise Vim depuis 10 ans, mais je viens d'installer emacs. :)
Adam Monsen
Mais emacs ne prend pas en charge la lecture depuis stdin, je ne peux pas faire par exemplegit log master.. -p | emacs -
Salut-Angel
1
@ Hi-Angel Vous pouvez ouvrir Emacs et taper M-!pour exécuter la commande et capturer la sortie dans un tampon.
legoscia
172

Dans git, vous pouvez fusionner sans valider. Fusionnez d'abord votre patch, puis faites:

git diff --word-diff-regex=.

Notez le point après le signe égal.

yingted
la source
139
Mieux: git diff --color-words=..
ntc2
4
@ ntc2 Vous devriez faire de votre commentaire une réponse.
Tyler Collier le
1
Veuillez noter que mon cas d'utilisation d'origine suppose que vous n'avez qu'un fichier de correctif , pas de dépôt git ou même des versions de base / modifiées. C'est pourquoi j'ai accepté la réponse de @ legoscia ... elle décrit exactement ce qui a été demandé.
Adam Monsen
2
@ ntc2 git diff --color-words=.et git diff --color-words .fonctionne différemment. Mieux vaut git diff --color-words ..
abhisekp
2
@abhisekp: merci pour la photo. Je pense que je l'ai compris: git diff --color-words .c'est vraiment le même que git diff --color-words -- .! Ie, le .est interprété comme un chemin. Vous pouvez vérifier avec 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

Voici quelques versions avec une sortie moins bruyante que git diff --word-diff-regex=<re> et qui nécessitent moins de frappe que, mais sont équivalentes à, git diff --color-words --word-diff-regex=<re>.

Simple (met en évidence les changements d'espace):

git diff --color-words

Simple (met en évidence les changements de caractères individuels; ne met pas en évidence les changements d'espace):

git diff --color-words=.

Plus complexe (met en évidence les changements d'espace):

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

En général:

git diff --color-words=<re>

<re>est une expression rationnelle définissant des «mots» dans le but d'identifier les changements.

Ceux-ci sont moins bruyants dans la mesure où ils colorent les "mots" modifiés, alors qu'ils n'utilisent que --word-diff-regex=<re>des "mots" assortis entourant les -/+marqueurs colorés .

ntc2
la source
9
J'aime moi-même --color-words, sans la =.partie.
Tyler Collier
1
git diff --color-words='\w'fonctionnerait mieux avec les signes diacritiques (git v1.7.10.4)
nr
1
Votre version plus complexe fonctionne très bien. J'ai ajouté --word-diff=plainpour avoir [-et -]entourer des suppressions {+et +}des ajouts entourant. Comme le manuel avertit, cependant, les occurrences réelles de ces délimiteurs dans la source ne sont en aucun cas échappées
Tobias Kienzler
2
Votre version plus complexe ne semble malheureusement pas mettre en évidence par exemple les changements d'indentation, j'ai ouvert une question à ce sujet
Tobias Kienzler
Cette réponse est géniale! Cependant, existe-t-il un moyen de changer l'arrière-plan de ces changements en vert / rouge?
WoLfPwNeR
45
git diff --color-words="[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+"

Le regex ci-dessus ( de Thomas Rast ) fait un travail décent de séparation des fragments de diff au niveau de la ponctuation / caractère (sans être aussi bruyant que --word-diff-regex=.).

J'ai posté une capture d'écran de la sortie résultante ici .


Mettre à jour:

Cet article contient de bonnes suggestions. Plus précisément, l' contrib/arborescence du repo git a un diff-highlightscript perl qui montre des surlignages fins.

Démarrage rapide pour l'utiliser:

$ 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
la source
5
Vous pouvez le raccourcir à--color-words=[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'
Édité
j'ai dû ajouter 'au début de la valeur là-bas. sinon j'ai une erreur. En outre, j'utilise simplement --color-wordsj'obtiens exactement le même comportement que l'utilisation de cette expression rationnelle.
gcb
3
@gcb Le contenu du texte est important. Si vos modifications sont séparées par des espaces, il n'y a aucune différence. Mais si vous changez si vous changez quelque chose comme foo.barà, foo.quxvous verrez la différence.
Justin M. Keyes
5
Simple: git diff --color-words='[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'.
ntc2
1
J'avais installé git avec Homebrew et j'avais déjà ce script sur /usr/local/share/git-core/contrib/diff-highlight/diff-highlight. Cela semble suggérer que git de Homebrew installe la totalité de la contribution dans /usr/local/share/git-core/contrib/. Donc finalement, ce qui suit a fonctionné pour moigit diff --color=always | /usr/local/share/git-core/contrib/diff-highlight/diff-highlight
Ashutosh Jindal
6

Si vous n'avez rien contre l'installation de NodeJS, il existe un package appelé "diff-so-fancy" ( https://github.com/so-fancy/diff-so-fancy ), qui est très facile à installer et fonctionne parfaitement:

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

Edit: Je viens de découvrir que c'est en fait un wrapper pour le diff-highlight officiel ... Au moins, c'est plus facile à installer pour les perlophobes comme moi et la page GitHub est bien documentée :)

Walnutz
la source
2

Je ne suis pas au courant de l'outil de différence par caractère, mais il existe un outil de différence par mot: wdiff.

voir les exemples Les 4 principaux outils de différence de fichiers sous UNIX / Linux - Diff, Colordiff, Wdiff, Vimdiff .

le geek
la source
wdiff est intéressant, merci! Pour clarifier ma question initiale, je recherche quelque chose qui fournit une coloration syntaxique améliorée pour un seul fichier qui se trouve être au format diff unifié.
Adam Monsen
Légèrement hors sujet (à propos des diffs mot à mot, n'améliorant pas une sortie diff préexistante), mais j'ai trouvé les combinaisons suivantes les meilleures pour les visualisations mot à mot: * wdiff old_file new_file | cdiff * vimdiff , puis à l'intérieur de vim :windo wincmd Kafin de passer à la disposition de la fenêtre verticale (l'un en dessous de l'autre) côte à côte. Cette disposition est bien meilleure pour les fichiers avec de longues lignes.
Aleksander Adamowski
2
BTW, d'autres outils la peine de vérifier, non mentionné dans l'article lié: wdiff2, mdiffet l' outil en ligne de Google .
Aleksander Adamowski
1

Après quelques recherches, je remarque que cette question a été soulevée deux fois récemment sur la liste de diffusion principale de Vim. Le plugin NrrwRgn a été mentionné les deux fois (créer deux régions étroites et les différencier). Utiliser NrrwRgn comme décrit par Christian Brabandt ressemble plus à une solution de contournement qu'à une solution, mais c'est peut-être suffisant.

J'ai essayé NrrwRgn et cela, avec: diffthis, était en effet utile pour illustrer les différences par caractère dans des parties d'un seul fichier. Mais il a fallu de nombreuses frappes. Mon Vimscript est assez rouillé, mais il pourrait probablement être scripté. Peut-être que NrrwRgn pourrait être amélioré pour fournir la fonctionnalité souhaitée.

Pensées?

Adam Monsen
la source