Как я могу визуализировать посимвольные различия в едином файле сравнения?

122

Скажем, у меня есть патч, созданный с помощью git format-patch. По сути, файл представляет собой унифицированный файл сравнения с некоторыми метаданными. Если я открываю файл в Vim, я вижу, какие строки были изменены, но я не вижу, какие символы в измененных строках отличаются. Кто-нибудь знает способ (в Vim или другом бесплатном программном обеспечении, работающем в Ubuntu) визуализировать посимвольные различия?

Пример счетчика, в котором визуализируется посимвольное различие, - это при выполнении vimdiff a b.

обновить Пт, 12 ноября, 22:36:23 UTC 2010

diffpatch полезен для сценария, когда вы работаете с одним файлом.

обновить Чт, 16 июня, 17:56:10 UTC 2016

Посмотрите diff-highlight в git 2.9 . Этот сценарий делает именно то , что я изначально искал.

Адам Монсен
источник
Это может быть лучше на superuser.com
Дейнит
13
Может быть. Я выбрал stackoverflow.com, поскольку в FAQ упоминается, что это место для вопросов о «программных инструментах, обычно используемых программистами»
Адам Монсен,
7
Я не уверен, что это прямо отвечает на ваш вопрос, но git diff --color-wordsэто очень полезно, чтобы просто увидеть, какие слова были изменены в строках, а не обычный унифицированный вывод diff. Однако он основан на словах, а не на символах, поэтому, если в контенте, который вы различаете, не так много пробелов, результат может быть менее четким. (Отредактировано: Ой, я вижу, что я неправильно понял то, о чем вы просите - тем не менее, может быть, этот комментарий будет кому-то полезен.)
Марк Лонгэр

Ответы:

13

Учитывая ваши ссылки на Vim в вопросе, я не уверен, что это тот ответ, который вам нужен :) но Emacs может это сделать. Откройте файл , содержащий диф, убедитесь , что вы находитесь в diff-mode(если файл с именем foo.diffили foo.patchэто происходит автоматически, в противном случае типа M-x diff-mode RET), перейдите к ломтю вы заинтересованы в и ударили C-c C-bпо refine-hunk. Или пролистайте файл по одному фрагменту за раз M-n; это произведет уточнение автоматически.

legoscia
источник
1
Работает для меня! Хех, я использовал Vim 10 лет, но только что установил emacs. :)
Адам Монсен
Но emacs не поддерживает чтение из стандартного ввода, я не могу, например,git log master.. -p | emacs -
Hi-Angel
1
@ Hi-Angel Вы можете открыть Emacs и ввести M-!команду, чтобы запустить команду и записать вывод в буфер.
legoscia
172

В git вы можете выполнить слияние без фиксации. Сначала слейте свой патч, а затем выполните:

git diff --word-diff-regex=.

Обратите внимание на точку после знака равенства.

yingted
источник
139
Лучше: git diff --color-words=..
ntc2 06
4
@ ntc2 Вы должны сделать свой комментарий ответом.
Тайлер Кольер
1
Наблюдатели, пожалуйста, обратите внимание, мой исходный вариант использования предполагает, что у вас есть только файл патча , нет репозитория git или даже базовые / модифицированные версии. Вот почему я принял ответ @ legoscia ... он точно описывает то, что было запрошено.
Адам Монсен
2
@ ntc2 git diff --color-words=.и git diff --color-words .работает иначе. Лучше git diff --color-words ..
abhisekp
2
@abhisekp: спасибо за картинку. Думаю, разобрался: git diff --color-words .действительно то же самое git diff --color-words -- .! Т.е. .интерпретируется как путь. Вы можете проверить с помощью 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 04
145

Вот некоторые версии с менее шумным , чем выходом git diff --word-diff-regex=<re>и требует меньше , чем печатать, но эквивалентны, git diff --color-words --word-diff-regex=<re>.

Простой (выделяет изменения пространства):

git diff --color-words

Простой (выделяет отдельные изменения символов; не выделяет изменения пробелов):

git diff --color-words=.

Более сложный (выделяет изменения пространства):

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

В основном:

git diff --color-words=<re>

где <re>- регулярное выражение, определяющее «слова» с целью идентификации изменений.

Они менее шумны, так как окрашивают измененные «слова», тогда как при использовании только --word-diff-regex=<re>совпадающие «слова» окружаются цветными -/+маркерами.

NTC2
источник
9
Мне самому нравится --color-words, без =.детали.
Тайлер Кольер
1
git diff --color-words='\w'будет лучше работать с диакритическими знаками (git v1.7.10.4)
1
Ваша более сложная версия отлично работает. Я добавил, --word-diff=plainчтобы дополнительно иметь [-и -]окружающие удаления {+и +}окружающие добавления. Как предупреждает руководство, однако, фактические вхождения этих разделителей в источнике не спасся каким - либо образом
Tobias Kienzler
2
К сожалению, ваша более сложная версия, похоже, не выделяет, например, изменения отступов, я открыл вопрос по этому
поводу
Отличный ответ! Однако есть ли способ изменить фон этих изменений на зеленый / красный?
WoLfPwNeR
45
git diff --color-words="[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+"

Вышеупомянутое регулярное выражение ( от Томаса Раста ) неплохо справляется с разделением фрагментов diff на уровне знаков препинания / знаков (хотя и не так шумно, как --word-diff-regex=.).

Я разместил снимок экрана с полученным результатом здесь .


Обновить:

В этой статье есть несколько отличных предложений. В частности, в contrib/дереве репозитория git есть diff-highlightскрипт на Perl, который показывает мелкие детали.

Быстрый старт в использовании:

$ 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
Джастин М. Киз
источник
5
Вы можете сократить его до--color-words=[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'
Eddified
Мне пришлось добавить 'туда значение в начале. в противном случае я получил ошибку. Кроме того, я просто использую, --color-wordsя получаю то же поведение, что и при использовании этого регулярного выражения.
gcb
3
@gcb Текстовое содержание имеет значение. Если ваши изменения разделены пробелом, разницы нет. Но если изменить , если изменить что - то подобное , foo.barчтобы foo.quxвы увидите разницу.
Джастин М. Киз,
5
Simpler: git diff --color-words='[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'.
ntc2 06
1
Я установил git с Homebrew и уже имел этот скрипт в /usr/local/share/git-core/contrib/diff-highlight/diff-highlight. Это позволяет предположить , что мерзавец доморощенного в это установить весь вно в /usr/local/share/git-core/contrib/. Итак, наконец, у меня сработало следующееgit diff --color=always | /usr/local/share/git-core/contrib/diff-highlight/diff-highlight
Ашутош Джиндал
6

Если вы ничего не имеете против установки NodeJS, есть пакет под названием "diff-so-fancy" ( https://github.com/so-fancy/diff-so-fancy ), который очень легко установить и отлично работает:

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

Изменить: только что узнал, что на самом деле это оболочка для официального diff-highlight ... По крайней мере, его проще установить для таких перлофобов, как я, и страница GitHub хорошо документирована :)

Walnutz
источник
2

Мне неизвестен инструмент для разницы в символах, но есть инструмент для разницы в словах: wdiff.

см. примеры Лучшие 4 инструмента для различения файлов в UNIX / Linux - Diff, Colordiff, Wdiff, Vimdiff .

thegeek
источник
wdiff интересно, спасибо! Чтобы прояснить свой исходный вопрос, я ищу что-то, что обеспечивает улучшенную подсветку синтаксиса для одного файла, который находится в унифицированном формате diff.
Adam Monsen
Немного оффтоп (о дословных различиях, без улучшения уже существующего вывода различий), но я нашел следующие комбинации, которые лучше всего подходят для дословной визуализации: * wdiff old_file new_file | cdiff * vimdiff , затем внутри vim :windo wincmd K, чтобы переключиться на вертикальную компоновку окна (один под другим) сбоку один. Такой макет лучше подходит для файлов с длинными строками.
Александр Адамовский
2
Кстати, проверить некоторые другие инструменты стоят, не упомянутых в связанной статье: wdiff2, mdiffи в онлайн - инструмент от Google .
Александр Адамовский
1

После небольшого исследования я заметил, что этот вопрос в последнее время дважды поднимался в основном списке рассылки Vim. Плагин NrrwRgn был упомянут как раз (сделать две узкие области и дифф их). Использование NrrwRgn, описанное Кристианом Брабандтом, больше похоже на обходной путь, чем решение, но, возможно, этого достаточно.

Я попробовал NrrwRgn, и он вместе с: diffthis действительно был полезен для иллюстрации посимвольных различий в частях одного файла. Но для этого потребовалось много нажатий клавиш. Мой Vimscript довольно ржавый, но, скорее всего, это скрипт. Возможно, NrrwRgn можно улучшить, чтобы обеспечить желаемую функциональность.

Мысли?

Адам Монсен
источник