Самый странный коммит в истории ядра Linux

Принято считать, что у git merge должно быть два родительских коммита. Например, вот свежий коммит ядра Linux версии 4.10-rc6 с идентификатором 2c5d955, образованный слиянием двух родителей:

Git также поддерживает слияния типа «осьминог», у которых есть больше двух родителей. Это непривычно для тех, кто работает над маленькими проектами: ну неужели вас не смутит слияние трёх или четырёх родителей? Однако такое случается. Иногда люди, сопровождающие ядро, объединяют десятки отдельных историй. 30 отдельных слияний проводить куда неудобнее, чем одно с 30 родителями, особенно если оно пройдёт без конфликтов.

И как часто используют этих осьминогов?

«Осьминоги» на самом деле встречаются куда чаще, чем вы могли бы подумать. Всего в истории ядра (на момент написания статьи) есть 649 306 коммитов. 46 930 (7,2%) из них — слияния. 1 549 слияний (3,3%) — осьминоги.

Приведём наглядный пример для сравнения: 20% коммитов Rails — слияния (12 401 из 63 111), и среди них нет осьминогов. Rails больше похож на среднестатистический проект: скорее всего, большинство пользователей git даже не подозревали о возможности множественного слияния.

Теперь возникает закономерный вопрос: насколько большими могут быть эти осьминоги? Символы > здесь обозначают продолжения строк — вся команда занимает 4 строки. Да, она не особо читаема, но нам больше интересен результат:

66 родителей! Да уж, немало. А что произошло?

Этот коммит сломал не один инструмент для отображения истории, и даже привлёк внимание самого Линуса Торвальдса:

Я только что извлёк звуковые обновления Takashi и получил мёрж-коммит 2cde51fbd0f3. У него 66 родителей.

[…]

Что ж, он извлёкся, он работает, но, бесспорно, нужно чувствовать разницу между «слияния-осьминоги — это здорово» и «Боже, это не осьминог, это Ктулху какой-то».

Изучив код, можно понять, что этот странный коммит был слиянием различных изменений кода ASoC (ALSA System on Chip). ALSA — это звуковая подсистема; SoC — это термин, означающий вычислительное устройство на одном чипе. Т.е. ASoC — это софт для поддержки звука на встроенных системах.

И как часто возникают такие слияния?

Никогда! На втором месте по количеству родителей находится слияние fa623d1, у которого есть «всего лишь» 30 родителей. Однако разрыв между 30 и 66 родителями не будет столь удивительным, если провести небольшое исследование.

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

Parents per commit in linux kernel log log

Если вкратце, тяжёлое одностороннее распределение случайной величины означает, что она принимает большие значения с гораздо меньшей вероятностью, чем маленькие, при этом максимальное значение не ограничено. Ядро содержит 45 381 слияние с двумя родителями и одно — с 66 родителями. Можно предположить, что когда-то мы увидим слияние с ещё большим количеством родителей.

Количество строк кода в функции или модуле также имеет тяжёлое одностороннее распределение (большинство из них маленькие, но некоторые будут огромными — подумайте о классе User в веб-приложении). То же справедливо и в отношении частоты изменения модулей (почти все будут изменяться очень редко, но некоторые — постоянно; User снова подойдёт в качестве примера). При разработке такие распределения возникают всюду и выглядят как прямые на графиках с логарифмической шкалой наподобие того, что изображён выше.

Для тех, кого заинтересовал этот случай, в ядре Linux есть и другие занимательные коммиты.

Иван Бирюков, страж правописания