Как работают diff / patch и насколько они безопасны?

относительно того, как они работают, мне было интересно низкоуровневый рабочий материал:

  1. что вызовет конфликт слияния?
  2. контекст также используется инструментами для применения исправления?
  3. как они справляются с изменениями, которые фактически не изменяют поведение исходного кода? Например, замена мест определения функции.

Что касается безопасности, по правде говоря, огромный репозиторий ядра Linux является свидетельством их безопасности. Но Меня интересуют следующие моменты:

  1. существуют ли какие-либо оговорки/ограничения в отношении инструментов, о которых пользователь должен знать?
  2. были доказаны, что алгоритмы не генерируют неправильные результаты?
  3. Если нет, существуют ли реализации/документы, предлагающие интеграционное тестирование, которые, по крайней мере, доказывают их безошибочность эмпирически? Что-то вроде содержания этих бумаг!--18-->BrianKorver и JamesCoplien.
  4. опять же, репозитория Linux должно быть достаточно относительно предыдущего пункта, но мне было интересно что-то более общее. Исходный код, даже при изменении, не сильно изменится (особенно из-за реализованного алгоритма и синтаксических ограничений), но можно ли обобщить безопасность на общие текстовые файлы?

редактировать

Ok люди, я редактирую, так как вопрос расплывчатый и ответы не адресуются подробности.

git/diff / патч детали

унифицированный формат diff, который Git, похоже, использует по умолчанию, в основном выводит три вещи: изменение, контекст, окружающий изменение, и номера строк, относящиеся к контексту. Каждая из этих вещей может быть изменена или не изменена одновременно, поэтому Git в основном должен иметь дело с 8 возможными случаями.

например, если строки были добавлены или удалены до контекста, номера строк будут отличаться; но если контекст и изменения все еще одинаковы, то diff может использовать сам контекст для выравнивания текстов и применения патча (я не знаю, действительно ли это происходит). А что будет с другими делами? Я хотел бы знать подробности о том, как Git решает применять изменения автоматически и когда он решает выпустить ошибку и позволить пользователю разрешить конфликт.

надежность

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

все еще связано с этой темой, мы знаем, что git/diff рассматривают файлы как общие текстовые файлы и работают на линиях. Кроме того, алгоритм LCS, используемый diff, будет генерировать патч, пытающийся минимизировать количество изменений.

Итак, вот некоторые вещи, которые я также хотел бы знать:

  1. почему вместо этого используется LCS других строковых метрических алгоритмов?
  2. Если используется LCS, почему бы не использовать модифицированные версии Метрики, которые учитывают грамматические аспекты базового языка?
  3. Если используется такая метрика, которая учитывает грамматические аспекты, могут ли они обеспечить преимущества? Преимуществами в этом случае может быть что угодно, например, более чистый "журнал вины".

опять же, это могут быть огромные темы и научные статьи приветствуются.

3 ответов


что вызовет конфликт слияния?

давайте посмотрим на самый простой из git's слияние стратегий, рекурсивные, во-первых: при слиянии двух ветвей, скажем a и b, которые имеют общего предка c, git создает патч для перехода от commit c к совершению объявления глава a и пытается применить этот патч к дереву в голове b. Если исправление не удается, это конфликт слияния.

git по умолчанию использует рекурсивные стратегия, a 3-way merge. Общая идея та же: если алгоритм 3-way merge, описанный в ссылке, терпит неудачу, потому что два коммита из разных ветвей изменили одни и те же строки, это конфликт слияния.

контекст также используется инструментами для применения исправления?

да. Если патч не применяется к точному номеру строки, хранящемуся в файле diff, патч пытается найти правильную строку в паре строк, прилегающих к исходной, на основе контекста.

как они справляются с изменениями, которые фактически не изменяют поведение исходного кода? Например, замена мест определения функции.

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

существуют ли какие-либо оговорки/ограничения в отношении инструментов, о которых пользователь должен знать?

Что касается патча и diff: нет. Оба используют алгоритмы, которые существуют с начала 1970-х годов и довольно надежны. Пока они не жалуются, вы можете быть уверены, что они сделали то, что вы предназначенный.

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

были доказаны, что алгоритмы не генерируют неправильные результаты? Если нет, существуют ли реализации/документы, предлагающие интеграционное тестирование, которые, по крайней мере, доказывают их безошибочность эмпирически?

"неправильные результаты" - это довольно неопределенный термин в этом контексте; я бы сказал, что он не может быть доказан. Эмпирически доказано, что применение патча, генерируемого diff a b в файле a будет в любом случае производить с файлом b.

исходный код, даже при изменении, не сильно изменится (особенно из-за реализованного алгоритма и синтаксических ограничений), но можно ли обобщить безопасность на общие текстовые файлы?

опять же, diff / patch/git не различает исходный код и другие текстовые файлы. git также работает с общими текстовыми файлами, как и с исходным кодом.

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

коммиты в git-это снимки дерева с метаданными, а не различия с соседними версиями. Патча и diff не участвуют в ревизионный обход вообще. (Но на один уровень ниже поверхности, git затем организует капли в упаковать файлы, которые используют алгоритм Дельта-сжатия. Ошибки здесь было бы легко обнаружить, потому что Git внутренне использует суммы sha1 для идентификации файлов, и сумма изменится, если произошла ошибка.)

почему LCS используется вместо других строковых метрических алгоритмов?

git по умолчанию использует алгоритм Майерса. Оригинал статьи объясняет почему это так работает. (Это не только LCS.)


  1. что вызовет конфликт слияния?

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

  1. контекст также используется инструментами для применения исправления?

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

  1. как они справляются с изменениями, которые фактически не изменяют поведение исходного кода? Например, замена мест определения функции.

они не делают. Подумайте о попытке научить git, какая семантика применяется где. Если ты не кричишь мысленно ... ужас, ты этого не сделаешь: -)

вы можете предоставить свои собственные драйверы слияния. Это просто. Если у вас есть несколько общих особых случаев, которые вы хотите обрабатывать автоматически, просто сделайте это. Начните с простого сценария оболочки, который вызывает встроенный драйвер, а затем sedили awks или что угодно для конфликтов вы можете отрегулировать правильно автоматически.


я почти уверен, что Git полностью надежен, так как он имеет полную историю коммитов и может проходить история. Я хотел бы получить некоторые указания на академические исследования и ссылки на это, если они существуют.

внутренняя структура Git невероятно проста. Я не шучу. Вы можете проверить надежность модели путем осмотра. Держите структуру dag-of-trees и как merge работает в уме, попробуйте найти конкретную озабоченность или вопрос о ее надежности, я думаю, вы решите любой, как только они попытаются сформировать.

если вы вместо этого спрашиваете о надежность его реализованных операций, правильно ли он выполняет сжатие или передает правильные объекты для удовлетворения push или fetch или что-то еще, это пишется "есть ли у git ошибки?".


форматы diff/patch небезопасны. = ) Потому что они вообще ничего не знают о ваших источниках.

Вот описание формата, который я нарисовал в (OMG) 2008. unified diff format

  1. конфликты слияния запускаются, когда строки в исходном чанке отличаются или изменяются в фактическом исходном файле. Исходный фрагмент состоит из желтых линий, которые не начинаются с"+". Красный цвет очерчивает номера линий, где программа patch ожидает найти это исходный кусок перед латанием. Если эти строки уже были изменены где-то в истории, вы получаете конфликт слияния.

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

  3. утилита patch utility ничего не знает о вашем поведении кода - она просто вставляет и удаляет строки, дающие вам предупреждения, когда ожидаемые строки не найдены (также могут потерпеть неудачу или попытаться найти смещение) или когда они уже были изменены (конфликт слияния)

надеюсь, это объяснение работает для вашего второго блока вопросов.

Что касается того, что можно сделать, я однажды придумал расширяемый формат набора изменений, чтобы формат diff мог нести дополнительные данные для более интеллектуальных инструментов исправления. Я!--25-->отправил идею в список рассылки subversion в , но в то время там было много энтузиазма.

Я задокументировал идею в коде Google, но он был закрыт, поэтому теперь он похоронен (без истории) на GitHub здесь: https://github.com/techtonik/rainforce/blob/wiki/ExtensibleChangesetFormat.md

Он ничего не получалось из-за отсутствия реальных проектов, которые могли бы извлечь выгоду из этого. На самом деле я создал расширенную версию (или, лучше сказать, альтернативу) формата патча, который знает о файлы и каталоги. Он использовался для создания инкрементных обновлений для Wesnoth в 2008 годуhttp://forums.wesnoth.org/viewtopic.php?f=5&t=20132 но я был слишком жаден, чтобы выпустить его на открытый исходный код (или боялся, что я не смогу поддерживать инструмент должным образом, и он будет раздвоен какой-то коммерческой компанией, которая заработает много денег). Вот как выглядит расширенная / альтернативная версия формата path:

[PatchPlan version 0.1]------------------------------------
* Description   : 
* Old Version   :
* New Version   :
* URL       :
* Patch made by : 
* Comments  :
* Used tools    :
-----------------------------------------------------------
[C ] ... "dir1/dir2/filename.ext" MD5
         N:"dir3/dir4/newfile.ext" MD5
[C ] ... "dir1/dir3/filename.ext" MD5
         P:"dir1/dir3/patchfile.ext.patch" TYPE MD5
[D ] ... "dir1/dir2/filename.ext" MD5
[A ] ... "dir1/dir2/filename.ext"
         N:"dir3/dir4/newfile.ext" MD5
[AD] ... "dir1/dir2/newdirname"
-----------------------------------------------------------

[C ] ... - Status field

         C  - Changed
         D  - Deleted
         A  - Added
         DE - Deleted empty directory
         DD - Deleted directory
         AD - Added directory
         ... - place reserved for flags like overwrite,
               force deletion etc. flags are separated by
               spaces from other fields




"dir1/dir2/filename.ext" - relative path of patched file


MD5    - 32 letters, i.e. cb5bc9f48388568178f24e6294ea782b


N:"dir3/dir4/newfile.ext" MD5
       - path for replacement file relative to directory
         with new files, i.e. temp directory where they
         were extracted, for example

P:"dir3/dir4/patchfile.ext.patch" TYPE MD5
       - path for patch file that should be applied
         TYPE is one of the supported 
         - VPATCH (DIFF, BSDIFF are planned)
       - .patch extensions is not a requirement, but
         merely a convention
       - MD5 in this case is MD5 of the new patched file
         and not of the patch itself


[D ] ... - MD5 of the file to be deleted

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

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