Автоматическое слияние в git без конфликтов (используя пословный diff вместо построчного)

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

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

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

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

В этом ответе предлагается использовать очистить и размазать< /em> фильтры для сохранения каждого слова в отдельной строке моментального снимка. Однако мне это кажется слишком хакерским.

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


person Adam Libuša    schedule 21.11.2018    source источник


Ответы (1)


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

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

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

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

Внутри измененного xdiff выглядит так, как будто Git присваивает каждой строке «запись», так что сравниваемые символы сравниваются между записями. Если вместо этого вы назначите каждое слово, разделенное пробелами, записи, вы в основном получите то, что хотите, игнорируя небольшой вопрос (позже) работа с любым фактическим пробелом, разделяющим фактические записи. . То есть в 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 строк может содержать 30 000 символов. Так что это, очевидно, будет медленнее, но, по крайней мере, обычно линейно медленнее. Алгоритмы гистограммы и терпения являются модификациями Майерса, которые должны вести себя одинаково во времени, я думаю, но я не изучал их должным образом.)

person torek    schedule 21.11.2018