beldmit: (Программизм)
Dmitry Belyavskiy ([personal profile] beldmit) wrote2024-12-25 04:30 pm

Как нам обустроить патчи

Сгребу-ка я сюда все свои не очень оформленные мысли, а заодно и ссылки.

Вводная. У меня есть два основных пакета, с которыми я на работе ковыряюсь, OpenSSH и OpenSSL. И там и там 60+ патчей, которые при каждом ребейзе приносят адскую боль. OpenSSL я знаю хорошо и поэтому с этой болью я почти смирился, OpenSSH я знаю средне.

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

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

Ещё очевидно, что патчи к одной подсистеме лучше прикладывать подряд, потому что контекст (в голове). И опять же склеить там, где возможно.

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

Номера затронутых строк и строк контекста так просто из patch/diff не получить. Во всяком случае, я не нашёл. Ну теоретически эту часть я могу хоть на Perl написать, не rocket science. Найти сцепленные патчи так можно, и дальше уже решать, что с этим делать.

Следующий интересный вопрос - а что ещё с этим можно сделать, чтобы улучшить поддерживаемость набора патчей in the long run.

На уровне разработки я нашёл совершенно чудный инструмент git absorb, который разбирает свежие изменения на fixup-ы и новые содержательные. Не знаю, как он потянет 60+ коммитов, конечно.

Вот тут пишут про замену diff для GitHub, но в основном для web-интерфейса.

Difftastic - продвинутый diff, не по строкам, а по логическим блокам

Mergiraf - продвинутый merge.

В дискуссию приглашается, например, [personal profile] spamsink
livelight: (Default)

[personal profile] livelight 2024-12-26 10:48 am (UTC)(link)
Не очень понимаю, что у вас за процесс. Если мейнтейнер апстрима начнёт ребейзить ключевые ветки, то в них одни коммиты превратятся в другие, и в тыкву превратится примерно всё у примерно всех в даунстримах. Почему ребейзы, а не нормальные мержи?
livelight: (Default)

[personal profile] livelight 2024-12-26 11:07 am (UTC)(link)
Но зачем ребейз?
Каждый патч знает, от какого коммита он отрос, и при мерже номера строк автоматически сдвигаются, куда надо. Блейм после мержа обычно тоже вразумительный, кроме мест с конфликтами. Даунстрим, патч от которого принят, знает свой коммит и не удивляется, увидев его клон после ребейза. В общем, сплошные плюсы.
Единственный минус стандартного гитового мержа - что после него бывает сложно понять, что было в той же ветке до мержа, а что приехало с мержом, так что бисекция может показывать лажу, ну так эту проблему ребейз тоже не решает.
Edited 2024-12-26 11:08 (UTC)
livelight: (Default)

[personal profile] livelight 2024-12-26 11:38 am (UTC)(link)
Я правильно понимаю, что "изменения в апстриме" - это как раз и есть ребейзы? Мержи - это append-only изменения, после них старые патчи обычно прикладываются (если только не возникли текстуально конфликтующие изменения одних и тех же строк).
yurikhan: (Default)

[personal profile] yurikhan 2024-12-26 01:04 pm (UTC)(link)

Процесс пакетирования программы или библиотеки для Debian («дебианизация») состоит в том, что Мейнтейнер берёт релизный слепок исходников Апстрима и обеспечивает, чтобы этот слепок собирался в контексте целевой версии системы и удовлетворял представлениям Debian’а о прекрасном. (Использует системные версии библиотек, а не таскает свои; не содержит несвободных или нарушающих прайваси компонентов; не имеет функциональности самообновления в обход apt’а и пр.) Иногда для этого приходится менять исходники, таким образом получаются патчи.

Веселье здесь в том, что процесс не требует от Апстрима использования Git’а. И даже вообще какой-нибудь системы контроля версий. От Апстрима требуется предоставлять тарболы тех версий, которые он считает стабильными, остальное забота Мейнтейнера.

Более того, когда конечный пользователь говорит в шелле apt-get source {somepackage}, то ему приезжает исходный тарбол Апстрима + патчи от Мейнтейнера, это часть контракта. Так что Мейнтейнеру нельзя локально смёржить свои патчи и время от времени подмёрживать Апстрим и собирать бинарные пакеты. Нужно уметь выдать наружу версию серии патчей, соответствующую каждому релизу.

Вот процесс получения серии патчей для нового релиза, когда есть тарболы старого и нового релизов, и называется обобщённо ребейзом, и это не обязан быть буквально git rebase, иногда это последовательность quilt push — чиним реджекты — quilt refresh — следующий quilt push — пока не наложатся все патчи.

livelight: (Default)

[personal profile] livelight 2024-12-27 10:53 am (UTC)(link)
То есть, патчи для готового релиза (включая, возможно, бинарники), а не для сорцов? Тогда это вообще пипец задачка - множественные патчи для такого держать.
yurikhan: (Default)

[personal profile] yurikhan 2024-12-27 11:17 am (UTC)(link)

Не, патчи для сорцов. Но (1) сорцы не обязаны лежать в гиту, (2) конечный пользователь должен мочь собрать бинарники из сорцов с патчами самостоятельно, и (3) конечный пользователь должен мочь читать патчи по отдельности.

С оценкой нелёгкой доли мейнтейнеров согласен, хоть бы бинарники патчить и не приходилось.