Выделите измененные строки и измененные байты в каждой измененной строке


94

В проекте с открытым исходным кодом Trac есть отличный инструмент для выделения различий - он выделяет измененные строки и измененные байты в каждой измененной строке! См. Примеры здесь или здесь .

Есть ли способ использовать одну и ту же цветовую подсветку (например, измененные строки и измененные байты ) в терминале bash gitили vim для вывода diff (файл патча)?


Что вы хотите выделить? Вам нужен инструмент сравнения, который выделяет изменения байтов? (Это было бы очень полезно). Вы говорите vim, насколько я помню, vim уже выполняет множество манипуляций с цветом, когда вы используете шаблоны языков программирования (и другие). Как бы вы это изменили? Существует довольно много методов изменения цвета в окне терминала, которое определено VT100 (и есть десятки других определений, которые также поддерживают escape-последовательности цветов). Пожалуйста, подробнее. Или прочтите en.wikipedia.org/wiki/VT100 и связанные ссылки. Может, это поможет.
Shellter

Я знаю, что вас интересуют только инструменты с открытым исходным кодом и только терминал. Но в качестве ориентира вы можете посмотреть на diffzilla slickedit. из немногих инструментов сравнения, которые я использовал, он всегда, кажется, лучше всего отражает различия символов (хотя у него определенно были проблемы, когда различия были сложными (сочетание форматирования и изменений кода, что всегда является плохой идеей)
nhed

Похоже на дублирование stackoverflow.com/questions/3231759/…
Адам Монсен

Примечание: GitHub теперь предлагает такой инструмент сравнения в своем веб-интерфейсе: stackoverflow.com/a/25723584/6309
VonC

Я опубликовал «еще один» чистый git, решение на основе diff-highlight с обучающими материалами, чтобы легко: 1) найти соответствующий файл diff-highlight, 2) сделать его исполняемым 3) установить необходимые параметры в .gitconfig. Пожалуйста, посмотрите. Инструкции предназначены для Ubuntu 18.04, но должны широко работать в системах Linux.
Zorglub29,

Ответы:


60

Сценарий diff-highlightPerl contrib выдает результат, настолько похожий на снимки экрана Trac, что вполне вероятно, что Trac его использует:

введите описание изображения здесь

Установить с помощью:

wget https://raw.githubusercontent.com/git/git/fd99e2bda0ca6a361ef03c04d6d7fdc7a9c40b78/contrib/diff-highlight/diff-highlight && chmod +x diff-highlight

Переместите файл diff-highlightв ~/bin/каталог (или где-нибудь $PATHеще), а затем добавьте в свой ~/.gitconfig:

[pager]
        diff = diff-highlight | less
        log = diff-highlight | less
        show = diff-highlight | less

Установка с одной копией вставки, предложенная @cirosantilli:

cd ~/bin
curl -O https://raw.githubusercontent.com/git/git/fd99e2bda0ca6a361ef03c04d6d7fdc7a9c40b78/contrib/diff-highlight/diff-highlight
chmod +x diff-highlight
git config --global pager.log 'diff-highlight | less'
git config --global pager.show 'diff-highlight | less'
git config --global pager.diff 'diff-highlight | less'
git config --global interactive.diffFilter diff-highlight

Этот. Это отлично. Спасибо. Хотя в некоторых местах он кажется немного консервативным, в нем отсутствуют некоторые строки, которые, очевидно, имеют большую часть общего текста. У вас есть для этого баг-трекер?
naught101

21
А, теперь это часть ядра git: github.com/git/git/tree/master/contrib/diff-highlight
naught101

2
Теперь он преобразован в модуль, и я думаю, что проще всего загрузить версию, которая была непосредственно перед этим изменением по адресу raw.githubusercontent.com/git/git/…
Крис Мидгли,

4
Эта часть не только ядра git, она распространяется вместе с git и, вероятно, уже в вашей системе. Я добавил подробности о том, как включить его, в своем ответе ниже. ↓
Кори Кляйн

2
Это пропускает различия, которые вы видите через git add -p. Также добавьте:git config --global interactive.diffFilter diff-highlight
josch

41

При использовании git diffили git logи, возможно, других, используйте опцию --word-diff=color(есть также другие режимы для word diffs BTW)


2
--word-diff=colorдействительно лучше (особенно с git config color.diff.old "red reverse"и git config color.diff.new "green reverse"), но это не то, что я хочу :(
Николай Францев

4
Итак, единственное, чего вам не хватает, - это маркировка цветом / каким-то образом измененные строки и байты одновременно?
anydot

7
Я хочу выделить измененные строки и измененные байты в каждой измененной строке, как в Trac. Не просто изменились байты, это уже не то.
Николай Францев

Вы также можете использовать это с помощью git add --patch: stackoverflow.com/questions/10873882/…
naught101

Преимущество diff-highlightзаключается в том, что он хорошо работает как для слов, так и для строк.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功 05

21

diff-so-fancy- diffосветитель, предназначенный для глаз человека.

Он удаляет начальные +/, -которые раздражают при вырезании / вставке, и очищает разделы между файлами.

Цветное git(слева) против diff-so-fancy(справа - обратите внимание на выделение на уровне персонажа):

необычный вывод

Если вы хотите, чтобы diff-so-fancyвывод (правая сторона) не ограничивался файлами в gitрепозитории, добавьте следующую функцию в свой, .bashrcчтобы использовать ее для любых файлов:

dsf() { git diff --no-index --color "$@" | diff-so-fancy; }

Например:

dsf original changed-file

Подсветка уровня символов и стандартный diffформат

Если вам не нравится нестандартное форматирование diff-so-fancy, но вы все же хотите gitвыделить на уровне символов , используйте diff-highlightwhich, чтобы получить gitвывод в действительно diffкрасивом стандартном формате:

снимок экрана с подсветкой

Чтобы использовать его по умолчанию из git, добавьте в свой .gitconfig:

[color "diff-highlight"]
  oldNormal = red bold
  oldHighlight = red bold 52
  newNormal = green bold
  newHighlight = green bold 22

[pager]
  diff = diff-highlight | less -FRXsu --tabs=4

В этом [pager]разделе говорится gitо конвейере уже окрашенного вывода, diff-highlightкоторый раскрашивается на уровне символа, а затем выводит вывод с меньшим количеством страниц (если требуется), а не просто с использованием значения по умолчанию less.


Это очень интересно, не могли бы вы немного рассказать об этих gitconfigвариантах?
caesarsol

Обновлено, также добавлена ​​функция dsf().
Том Хейл

15

Желаемое поведение теперь доступно в самом git (как было указано в комментарии naught101). Чтобы включить его, вам нужно настроить свой пейджер на

perl /usr/share/doc/git/contrib/diff-highlight/diff-highlight | less

где /usr/share/doc/git/contrib/diff-highlight/diff-highlightнаходится скрипт подсветки в Ubuntu 13.10 (я понятия не имею, почему он в docпапке). Если его нет в вашей системе, попробуйте использовать, locate diff-highlightчтобы найти его. Обратите внимание, что сценарий выделения не является исполняемым (по крайней мере, на моем компьютере), следовательно, требуется perl.

Чтобы всегда использовать маркер для различных команд, подобных различию, просто добавьте в свой ~/.gitconfigфайл следующее:

[pager]
    log = perl /usr/share/doc/git/contrib/diff-highlight/diff-highlight | less
    show = perl /usr/share/doc/git/contrib/diff-highlight/diff-highlight | less
    diff = perl /usr/share/doc/git/contrib/diff-highlight/diff-highlight | less

Я добавил это как новый ответ, комментарий naught101 похоронен, и потому что настройка не так тривиальна, как должна быть, и, по крайней мере, в той версии Ubuntu, в которой у меня есть инструкции в README , не работают.


Я только что заметил, что это не позволяет выделять различия внутри git add -p(интерактивный режим). Я не знаю, как это можно исправить, просто добавление добавления в список приводит к зависанию.
dshepherd

5
Теперь это должно работать в git 2.9.0:git config interactive.diffFilter diff-highlight
Thomas

^ Это! К сожалению, diff-highlightэто не было на моем пути, поэтому мне пришлось сначала найти его. Подробности в моем ответе ниже.
Кори Кляйн

11

Утилита для сравнения на основе байтов распространяется с официальным Git начиная с версии 1.7.8 1 . Вам просто нужно найти, где он установлен на вашем компьютере, и включить его.

Найдите, где установлен Git

  • MacOS с Git, установленным через Homebrew : это/usr/local/opt/git
  • Windows с Git для Windows : запустите, cd / && pwd -Wчтобы найти установочный каталог.
  • Linux: Ботан. Если вы еще не знаете, где установлен Git, тогда ll $(which git)или locate gitдолжно помочь.

Ссылка diff-highlightна ваш каталог bin, чтобы ваш PATH мог его найти

GIT_HOME='/usr/local/opt/git/'  # Use the value from the first step.
ln -s "${GIT_HOME}/share/git-core/contrib/diff-highlight/diff-highlight" \
      '/usr/local/bin/diff-highlight'

Включите его в своей конфигурации Git

git config --global interactive.diffFilter diff-highlight # Use on interactive prompts
git config --global pager.diff "diff-highlight | less"    # Use on git diff
git config --global pager.log  "diff-highlight | less"    # Use on git log
git config --global pager.show "diff-highlight | less"    # Use on git show

1 Это версия v1.7.8 , но с тех пор было внесено много изменений .


1
Было бы хорошо указать, в какой версии он начал распространяться с помощью git. Также я предполагаю, что дистрибутивы поместят его в PATH по умолчанию, поэтому шаг символической ссылки не понадобится? И which gitтребует, чтобы он был в PATH в первую очередь, поэтому он не будет работать, если это не так :-)
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

2
Это было бы хорошо! Не стесняйтесь добавлять эту информацию. И хотя Git связывает diff-highlight, на самом деле он не устанавливает его, поэтому шаг символьной ссылки действительно необходим (по крайней мере, в macOS). Если вы обнаружите, что это не обязательно для вашей платформы, снова не стесняйтесь обновить ответ. В то же время, как which gitправило , делает работу, потому что Git делает установки gitбинарного где - то на пути.
Кори Кляйн

Обратите внимание, что в debian unstable мне нужно было «скомпилировать» этот файл, потому что у меня только что был .perl. Компиляция тривиальна: просто запустите sudo makeв diff-highlightкаталоге.
tobiasBora

10

Я использую --color-wordsвариант, и он мне подходит:

$ git diff --color-words | less -RS

5
Нет, это только показывает разницу в словах. То, что OP (и я) хотят, - это обычное построчное различие с выделенными различиями слов (так, скажем, разные строки - это цветной текст, а различия слов в этих строках - это обычный цветной текст с цветным выделением или что нибудь). См. Ссылки на примеры в вопросе.
naught101

1
pastebin.com/1JrhYHRt На самом деле я использую vimdiff как difftool и vimdiff со схемой цветов molokai, чтобы получить приятное выделение, как вы описываете в своем вопросе. 1- git config --global diff.tool vimdiff 2- в vim ": colo molokai" * Molokai @ github.com/tomasr/molokai * Возможна автоматическая цветовая схема с ~ / .vimrc: if & diff set background = dark colorscheme molokai endif
amized

4

как говорит @dshepherd :

Желаемое поведение теперь доступно в самом git.

Но diff-highlightнаходится в DOC и недоступен из оболочки.
Чтобы установить diff-highlightв свой ~/binкаталог, выполните следующие действия (это сохранит ваш ввод):

$ locate diff-highlight
$ cd /usr/share/doc/git/contrib/diff-highlight  #or path you locate
$ sudo make
$ mv diff-highlight ~/bin

Затем настройте свой .gitconfigкак официальный документ:

[pager]
    log  = diff-highlight | less
    show = diff-highlight | less
    diff = diff-highlight | less

UPD
Также вы можете попробовать следующее gitбез установки:

git diff --color-words=.

Более сложный:

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

1

В Emacs есть функция ediff-patch-buffer, которая должна удовлетворить ваши потребности.

Откройте файл без исправлений в emacs типа ESC-x, ediff-patch-buffer.

Следуйте инструкциям, и вы должны увидеть выделенное сравнение исправленной и исходной версий вашего файла.

В соответствии с вашим комментарием следующее даст вам решение bash, требующее только dwdiff:

#!/bin/bash
paste -d'\n' <(dwdiff -2 -L -c <(cat $2) <(patch $2 -i $1 -o -)) <(dwdiff -1 -L -c <(cat $2) <(patch $2 -i $1 -o -))| uniq

извините, я не хочу использовать emacs, только bash, git или vim
Николай Францев

Это понятно. Единственное, что я могу придумать, это использовать colordiff со стандартным выводом из патча: colordiff -u <(patch original_file -i patch_file -o -) <(cat original_file) но это только выделит измененные строки, а не кусочки ...
Финбар Краго

Я немного подумал над вашей проблемой и добавил второе решение, для которого требуется только dwdiff.
Finbar Crago

1
пожалуйста, прочтите внимательно мой вопрос, я не хочу сравнивать файлы
Николай Францев

1
извините за путаницу, так что вы сразу после способа выделить измененные байты в измененных строках файла diff? если так, попробуйтеdwdiff -c --diff-input diff_file
Finbar Crago

1

Диффи

GitLab использует Diffy https://github.com/samg/diffy (Ruby) для достижения вывода, аналогичного GitHub и diff-highlight:

введите описание изображения здесь

Diffy сам делает различие, используя тот же алгоритм, что и Git, и поддерживает различные типы вывода, включая вывод HTML, который использует GitLab:

gem install diffy
echo '
  require "diffy"    
  puts Diffy::Diff.new("a b c\n", "a B c\n").to_s(:html)
' | ruby

Выход:

<div class="diff">
  <ul>
    <li class="del"><del>a <strong>b</strong> c</del></li>
    <li class="ins"><ins>a <strong>B</strong> c</ins></li>
  </ul>
</div>

Обратите внимание, как strongбыли добавлены измененные байты.


0

Да, Vim делает это, включая выделение текста, измененного внутри строки.
Смотрите :h diffи:h 08.7 для получения дополнительной информации о том, как сравнивать файлы.

Vim использует довольно простой алгоритм выделения. Он ищет в строке первый измененный символ, а затем последний измененный символ и просто выделяет все символы между ними.
Это означает, что у вас не может быть нескольких основных моментов в строке - многие дизайнерские решения в Vim отдают приоритет эффективности.


к сожалению, он не выделяет измененные байты при выводе diff (set filetype = diff)
Николай Францев

1
Думаю, теперь я понял ваш вопрос - вы хотите синтаксически выделить текстовый вывод команды diff, чтобы он выделял любые изменения, сделанные внутри строки. При редактировании этого текста в Vim выделяются различия строк, но не изменения внутри строки.
PDug

Не могли бы вы использовать команду Vim: patchfile, чтобы загрузить исходный файл и затем сравнить его с исправленной версией?
PDug

к сожалению, нет, я хочу использовать рекурсивный вывод diff для нескольких файлов
Николай Францев

0

vimdiff file1 file2 отобразит посимвольную разницу между двумя файлами.

vimdiff - это инструмент сравнения, включенный в vim. (Vim должен был быть скомпилирован с опцией + diff, чтобы убедиться, что вы можете проверить :version)

Вы также можете запустить его из vim. См. :help diffДополнительную информацию и команды.


Я не хочу сравнивать файлы, я хочу выделить файл diff (patch).
Николай Францев

@Nikolay Frantsev Если вас не волнует производительность, вы можете установить мой плагин format.vim и сделать vimdiff file.old file.new -c 'FormatCommand diffformat' -c 'w! file.diff.html' -c 'qa!'.
ZyX

Он выполнит сравнение в пакетном режиме ( screen -D -mдобавление или добавление &>/dev/null(вариант / dev / null иногда вызывает странные ошибки), если вы не хотите видеть мигание терминала) и выйдет из vim после завершения форматирования, но это чистый vimscript и даже с моей оптимизацией это очень медленно для больших файлов.
ZyX

0

Примечание . Это дубликат того, что можно найти здесь: Как улучшить выделение различий в git? . Публикую свой ответ и здесь, так как он может быть полезен некоторым людям, которые напрямую находят эту тему :)

Как было сказано в некоторых предыдущих ответах, это возможно только с помощью git. Я публикую это, так как инструкции могут быть немного проще в зависимости от вашей системы, но это похоже на несколько других ответов.

Одно решение, которое полностью полагается на git и его вклад. Для этого не требуются дополнительные файлы, кроме того, что поставляется с git . Все объяснения относятся к Ubuntu (протестировано на 18.04LTS), должно работать аналогично в других системах Linux:

  • Найдите фрагмент кода diff-highlight contrib git:
find -L /usr -name diff-highlight -type f

в моей системе единственный правильный ответ:

/usr/share/doc/git/contrib/diff-highlight/diff-highlight
  • Сделайте соответствующий скрипт Perl исполняемым. В моем случае мне нужно было сделать:
sudo chmod +x /usr/share/doc/git/contrib/diff-highlight/diff-highlight
  • Обновите свой, ~/.gitconfigчтобы получить желаемый результат, добавив (обратите внимание, что это ТАБЛИЦЫ, а не 4 пробела):
[color "diff-highlight"]
    oldNormal = red
    oldHighlight = red 52
    newNormal = green
    newHighlight = green 22
  • Наслаждайтесь результатом (примечание: это только для окраски различий + подсветки, у меня, конечно же, есть другие вещи для подсказки :)).

diff-highlight

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.