Автоматическое объединение в git без конфликтов (использование пословных различий вместо построчных) - PullRequest
0 голосов
/ 22 ноября 2018

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

git-diff может показать мне разницу между двумя коммитами не только для каждой строки, но также для каждого слова или символа.Например:

$ git diff --word-diff-regex=. HEAD HEAD~

Если git-diff может идентифицировать слова (в отличие от целых строк), которые изменились, я был убежден, что могу заставить git-merge обнаруживать конфликты по словам за словом (илипосимвольная) основа.Я был неправ.Из того, что я понял ( source ), в глубине души инструмент git-diff работает со строками, а функциональность различий между словами или символами уже работает с этими строковыми результатами, возвращаемыми git.

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

Какой подход вы бы выбрали?

1 Ответ

0 голосов
/ 22 ноября 2018

Чтобы заставить Git работать так, как вам нужно, вам нужно изменить код слияния.В теории это не так уж сложно.На практике я не уверен, насколько трудно это окажется.

В этот другой ответ , я упоминаю xdelta.Точнее, Git использует модифицированные версии xdelta и libxdiff . Исходный код Git помещает большую часть этого кода в подкаталог. На один уровень вы найдете еще несколько битов кода, которые работают с библиотекой, таких как xdiff-interface.c .

Если вы изменили их так, чтобы код xdiff обрабатывал «слова» (разделенные, предположительно, любым пробелом), а не «строки» как отдельные символы для алгоритмов Майерса, терпения и гистограммы, иизменив код вызова аналогично, вы должны иметь возможность заставить Git выполнять слияние на основе слов вместо строк.(Теперь Git добавляет «якорную» вещь, с которой вам, возможно, придется что-то делать; я не смотрел на то, как это работает.) Вы должны были бы выбрать, как вставить любые маркеры конфликта, предположительно, вокруг этих пробелов.-разделенные слова.

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

Внутренне визмененный xdiff, похоже, что Git назначает каждую строку «записи», так что сравниваемые символы являются записью за записью.Если вместо этого вы присваиваете каждой записи, разделенной пробелами word , запись, вы в основном получите то, что вам нужно, игнорируя незначительную часть (позже) работы с любым реальным пробелом, разделяющим фактические записи.То есть в xdl_hash_record все, что вам нужно сделать, это остановиться на любом пробеле вместо новой строки, а затем отбросить дополнительный пробел между этой и следующей строками при поиске«Следующая» запись, чтобы построить записи сами.Код , вызывающий , этот измененный diff, возможно, придется изменить, поскольку он может предполагать, что «номер записи» подразумевает «номер строки» (это мне не совсем понятно).

(Этоможет также сработать лучше, если вы включите начальный или конечный пробел в каждую запись и просто будете иметь функцию сравнения xdl_recmatch - в том же файле - скажем, что символы совпадают, если они совпадают, исключая их пробел. Обратите внимание, что xdl_hash_record долженхэш символа минус также пробел: механизм сравнения требует, чтобы хэши совпадали, если символы совпадали, и для производительности хочет, чтобы хэши отличались, если символы различаются. Тест, по сути, таков: символы S1и S2 с хэшами H1 и H2 совпадают, если H1 == H2 и recmatch (S1, S2) говорят, что они совпадают . Тест H1 == H2 устраняет множество вызовов подпрограмм для медленного "сравнения", когда символы явноотличаются, но для символов, чьи хэши совпадают, требуется вызов, чтобы убедиться, что они действительно одинаковы.)

Основной алгоритм Майерсаэльф имеет временную сложность O (ND), где N - количество символов, а D - количество различий, т. е. длины возможного сценария редактирования, между двумя наборами ввода.Когда символы являются строками, файл из 1000 строк содержит 1000 символов;когда вместо символов используются слова, файл из 1000 строк может содержать 30000 символов.Так что это, очевидно, будет медленнее, но, по крайней мере, обычно линейно медленнее.Алгоритмы гистограммы и терпения - это модификации Майерса, которые, по-моему, должны вести себя аналогично, по времени, но я их не изучил должным образом.)

...