Spec-Zone.ru › Git

gitdiffcore

Имя

gitdiffcore - Настройка вывода diff

Синтаксис

git diff *

Описание

Команды diff, git diff-index, git diff-files, и git diff-tree, могут быть настроены для обработки найденных различий нестандартным образом перед отображением diff вывода. Данная обработка называется "преобразованием diffcore". Эта краткая заметка описывает, что это такое и как использовать эти преобразования, чтобы получить diff вывод, более понятный, чем обычный.

Цепочка операций

Семейство команд git diff-* работает, сначала сравнивая два набора файлов:

  • git diff-index сравнивает содержимое объекта "дерево" и рабочую директорию (если флаг --cached не используется) или объект "дерево" и файл индекса (если флаг --cached используется);

  • git diff-files сравнивает содержимое файла индекса и рабочей директории;

  • git diff-tree сравнивает содержимое двух объектов "дерево";

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

Спецификации путей используются для ограничения области действия diff. Они удаляют пары файлов, не попадающие в указанные наборы имён путей. Например, если входной набор пар файлов включал:

:100644 100644 bcd1234... 0123456... M junkfile

но вызов команды был git diff-files myfile, тогда запись junkfile будет удалена из списка, так как рассматривается только "myfile".

Результат сравнения передаётся в механизм diffcore, в формате, аналогичном тому, который выводится, когда опция -p не используется. Например:

in-place edit  :100644 100644 bcd1234... 0123456... M file0
create         :000000 100644 0000000... 1234567... A file4
delete         :100644 000000 1234567... 0000000... D file5
unmerged       :000000 000000 0000000... 0000000... U file6

Механизм diffcore получает список таких результатов сравнения (каждый из которых называется "filepair", хотя на данном этапе каждый из них описывает один файл), и преобразует этот список в другой список. В настоящее время существует 5 таких преобразований:

  • diffcore-break

  • diffcore-rename

  • diffcore-merge-broken

  • diffcore-pickaxe

  • diffcore-order

  • diffcore-rotate

Они применяются последовательно. Набор пар файлов, git diff-* команд, используется в качестве входных данных для diffcore-break, а вывод diffcore-break используется в качестве входных данных для следующего преобразования. Конечный результат затем передаётся процедуре вывода и генерирует либо формат diff-raw (см. разделы "Формат вывода" в руководстве по git diff-* командам), либо формат diff-patch.

Diffcore-break: для разделения полных переписываний

Второе преобразование в цепочке — diffcore-break, и оно управляется опцией -B для git diff-* команд. Оно используется для обнаружения пары файлов, представляющих "полное переписывание", и разделения такой пары на две пары, представляющие удаление и создание. Например, если входной набор содержал эту пару файлов:

:100644 100644 bcd1234... 0123456... M file0

и если он обнаружит, что файл "file0" полностью переписан, он изменит его на:

:100644 000000 bcd1234... 0000000... D file0
:000000 100644 0000000... 0123456... A file0

Для разделения пары файлов diffcore-break анализирует степень изменений между содержимым файлов до и после модификации (т. е. содержимое, имеющее "bcd1234…​" и "0123456…​" в качестве идентификатора содержимого SHA-1, в приведённом примере). Общее количество удалённого исходного содержимого и добавленного нового материала суммируются, и если оно превышает "балл разделения", пара файлов разделяется на две. По умолчанию балл разделения равен 50% от размера меньшего из исходного и результирующего файлов (т. е., если редактирование уменьшает файл, используется размер результата; если редактирование увеличивает файл, используется размер исходного файла), и его можно настроить, указав число после опции -B (например, -B75, чтобы использовать 75%).

Diffcore-rename: для обнаружения переименований и копий

Это преобразование используется для обнаружения переименований и копий, и контролируется опцией -M (для обнаружения переименований) и опцией -C (для обнаружения копий также) для команд git diff-*. Если входной набор содержал эти пары файлов:

:100644 000000 0123456... 0000000... D fileX
:000000 100644 0000000... 0123456... A file0

и содержимое удалённого файла fileX достаточно похоже на содержимое созданного файла file0, тогда обнаружение переименований объединяет эти пары файлов и создаёт:

:100644 100644 0123456... 0123456... R100 fileX file0

Если используется опция -C, исходное содержимое изменённых файлов и удалённых файлов (а также неизменённых файлов, если используется опция --find-copies-harder) рассматриваются как кандидаты исходных файлов в операциях переименования/копирования. Если входной набор был подобен этим парам файлов, описывающих изменённый файл fileY и новый созданный файл file0:

:100644 100644 0123456... 1234567... M fileY
:000000 100644 0000000... bcd3456... A file0

исходное содержимое fileY и результирующее содержимое file0 сравниваются, и если они достаточно похожи, они меняются на:

:100644 100644 0123456... 1234567... M fileY
:100644 100644 0123456... bcd3456... C100 fileY file0

В обоих случаях обнаружения переименования и копирования используется тот же алгоритм "степени изменений", используемый в diffcore-break, чтобы определить, являются ли два файла "достаточно похожими", и его можно настроить, чтобы использовать коэффициент сходства, отличный от значения по умолчанию 50%, указав число после опции -M или -C (например, -M8, чтобы использовать 8/10 = 80%).

Обратите внимание, что при включённом обнаружении переименований, но выключенных обнаружении копий и разделении, обнаружение переименований добавляет предварительный шаг, который сначала проверяет, перемещаются ли файлы между директориями, сохраняя при этом то же имя файла. Если добавлен файл в директорию, содержимое которого достаточно похоже на файл с тем же именем, удалённый из другой директории, он будет помечен как переименованный и исключён из последующего квадратичного шага (шага, который попарно сравнивает все несовпавшие файлы, чтобы найти "лучшее" соответствие, определяемое наивысшим сходством содержимого). Например, если удалённый docs/ext.txt и добавленный docs/config/ext.txt достаточно похожи, они будут помечены как переименованный, и исключат возможность добавления docs/ext.md, который может быть ещё более похожим на удалённый docs/ext.txt, как место назначения переименования на более поздней стадии. По этой причине предварительный шаг «сопоставление файлов с одинаковым именем» использует немного более высокий порог для маркировки пары файлов как переименованной и прекращения рассмотрения других кандидатов для лучших совпадений. Максимум, один сравнения выполняется на файл в этом предварительном проходе; поэтому если после точного обнаружения переименования остаётся несколько файлов ext.txt в иерархии директорий, этот предварительный шаг может быть пропущен для этих файлов.

Примечание. При использовании опции -C с --find-copies-harder опцией, git diff-* команды передают неизменённые пары файлов в механизм diffcore наряду с изменёнными. Это позволяет детектору копий рассматривать неизменённые файлы как кандидаты источника копирования за счет увеличения времени выполнения. Без --find-copies-harder, git diff-* команды могут обнаруживать копии только в том случае, если файл, который был скопирован, оказался изменённым в том же наборе изменений.

Diffcore-merge-broken: для объединения разбитых полных переписываний

Это преобразование используется для объединения пар файлов, разбитых diffcore-break, и не преобразованных в переименование/копирование diffcore-rename, обратно в одну модификацию. Оно всегда запускается при использовании diffcore-break.

Для объединения разбитых пар файлов оно использует другое вычисление "степени изменений", отличное от используемых diffcore-break и diffcore-rename. Оно считает только удаление из оригинала и не считает вставки. Если вы удалили только 10 строк из 100-строчного документа, даже если вы добавили 910 новых строк, чтобы получить новый 1000-строчный документ, вы не сделали полное переписывание. diffcore-break разбивает такой случай, чтобы помочь diffcore-rename рассматривать такие пары файлов как кандидата для обнаружения переименования/копирования, но если таким образом разбитые пары файлов не были сопоставлены с другими парами файлов для создания переименования/копирования, то это преобразование объединяет их обратно в исходную "модификацию".

Параметр "степени изменений" можно настроить от значения по умолчанию 80% (то есть, если удалено более 80% исходного материала, разбитые пары объединяются обратно в одну модификацию) путём указания второго числа в опции -B, например:

  • -B50/60 (указать 50% "балл разделения" для diffcore-break, использовать 60% для diffcore-merge-broken).

  • -B/60 (то же самое, что и выше, так как diffcore-break по умолчанию имеет 50%).

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

Diffcore-pickaxe: для обнаружения добавления/удаления указанной строки

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

"-S<блок-текста>" обнаруживает пары файлов, у которых преобразованное и результативное изображения имеют разное количество вхождений указанного блока текста. По определению, он не будет обнаруживать перемещения внутри файла. Кроме того, когда изменения устанавливают файл целиком без влияния на интересную строку, diffcore-rename срабатывает как обычно, и -S опускает пару файлов (так как количество вхождений этой строки не изменилось в этой паре файлов, обнаруженных rename). При использовании с --pickaxe-regex, интерпретируйте <блок-текста> как расширенное регулярное выражение POSIX для соответствия, а не как литеральную строку.

"-G<регулярное выражение>" (мнемоника: grep) обнаруживает пары файлов, у которых текстовый diff содержит добавленную или удалённую строку, соответствующую заданному регулярному выражению. Это означает, что он будет обнаруживать перемещения внутри файла (или то, что обнаружение переименований считает тем же файлом), что является шумом. Реализация выполняет diff дважды и grep, и это может быть довольно дорого. Для ускорения будут игнорироваться двоичные файлы без фильтров textconv.

Когда -S или -G используются без --pickaxe-all, в выводе сохраняются только пары файлов, соответствующие их соответствующим критериям. Когда используется --pickaxe-all, если хотя бы одна пара файлов соответствует своим критериям в наборе изменений, весь набор изменений сохраняется. Это поведение разработано для упрощения просмотра изменений в контексте всего набора изменений.

Diffcore-order: для сортировки вывода на основе имён файлов

Это используется для переупорядочивания пар файлов в соответствии с предпочтениями пользователя (или проекта) и контролируется опцией -O команд git diff-*.

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

В качестве примера, типичный файл порядка для ядра Git, вероятно, будет выглядеть так:

README
Makefile
Documentation
*.h
*.c
t

Diffcore-rotate: для изменения пути начала вывода

Это преобразование принимает один путь к файлу и вращает набор пар файлов так, чтобы пара файлов для данного пути оказалась первой, необязательно удаляя пути, которые идут перед ним. Это используется для реализации опций --skip-to и --rotate-to. Ошибка возникает, когда указанный путь к файлу не находится в наборе пар файлов, но при использовании с командами семейства «git log» нет смысла выдавать ошибку, поскольку неразумно ожидать, что данный путь будет изменён каждым и каждым коммитом, показанным командой «git log». По этой причине при использовании с «git log» пара файлов, которая сортируется так же, как или первая, которая сортируется после данного пути, является местом, где начинается вывод.

Использование этого преобразования в сочетании с diffcore-order приведёт к непредсказуемым результатам, так как входные данные этого преобразования, вероятно, не отсортированы, когда diffcore-order активен.

См. также

git-diff[1], git-diff-files[1], git-diff-index[1], git-diff-tree[1], git-format-patch[1], git-log[1], gitglossary[7], Руководство пользователя Git

gitdiffcore

© 2005–2026 Linus Torvalds and others
Licensed under the GNU General Public License version 2.
https://git-scm.com/docs/gitdiffcore

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API