Уйдёт лидер — до 97% файлов без автора: считаем truck factor по git

Всем привет, меня зовут Сергей Прощаев, я Tech Lead и руководитель направления Java | Kotlin разработки в FinTech & E‑commerce и преподаю на курсах разработки и архитектуры в ОТУС.
В этой статье расскажу, почему руководитель команды обычно узнаёт о концентрации знаний в день заявления об уходе, как посчитать её заранее по истории git и что в этом расчёте меняют коммиты, сделанные вместе с агентом.
Знакомая картина. Сильный разработчик кладёт на стол заявление, впереди две недели отработки. Руководитель открывает файл владельцев кода: модулей у человека три, у каждого записано ещё по два ответственных, всё выглядит спокойно.
Через месяц в одном из модулей падает интеграция со сторонним API, и выясняется, что два «ответственных» видели этот код только в списке изменённых файлов на ревью. Команда неделю разбирается в проблеме по логам и комментариям в коде.
Обычное объяснение звучит так: «не успели передать дела». Я с ним не согласен. Две недели здесь ни при чём: знания собирались в одной голове годами, а измерить это можно было в любой день, просто никто не смотрел.
Что я посчитал
Чтобы не спорить на ощущениях, я взял метод из работы Авелино и соавторов, представленной на конференции ICPC в 2016 году. Они предложили считать truck factor, то есть bus factor, автоматически по истории git.
Для каждого файла считается степень авторства разработчика (DOA): создал ли он файл, сколько раз менял и сколько правок внесли другие. Величина нормируется по максимуму для файла, и автором считается тот, у кого нормированный DOA выше 0,75, а абсолютный не ниже 3,293.
Авторов у файла может быть несколько. Затем по одному исключают автора с наибольшим числом файлов, пока оставшиеся авторы покрывают хотя бы половину файлов. Число исключённых разработчиков и есть оценка truck factor по этой модели.
Ядро расчёта занимает несколько строк:
import math
def doa(is_first_author: bool, own_changes: int, other_changes: int) -> float:
# Avelino et al., ICPC 2016: первое авторство весит больше всего,
# свои правки добавляют, чужие правки медленно отнимают
return (3.293 + 1.098 * int(is_first_author) + 0.164 * own_changes
- 0.321 * math.log1p(other_changes))В исходной работе 65% из 133 популярных проектов GitHub имели truck factor не больше двух. Я применил эту методику к шести открытым проектам на JVM и Python по зафиксированным коммитам от 29 сентября до 23 октября 2026 года. Это не полное воспроизведение: файлы кода я отбирал по расширению и без каталогов вроде vendor и build, а не через Linguist, как авторы.
Кроме того, я добавил две величины, которых в исходной работе нет. «Ничьё сейчас» — доля файлов, у которых по расчёту не осталось ни одного автора, коммитившего за последний год. «Ничьё без лидера» — та же доля, если из активных уйдёт один человек с наибольшим числом файлов.
Авторство считается по всей истории, а «активные» — это авторы с коммитами за 365 дней до зафиксированного коммита, DOA по одним свежим правкам я не пересчитывал. Обе метрики оценивают авторство по истории правок, а не знание кода. Их ограничения разберу в конце.
Проект | Файлов кода | Truck factor по всей истории | Truck factor среди активных | Ничьё сейчас | Ничьё без лидера |
|---|---|---|---|---|---|
fastapi | 1220 | 1 | 1 | 3,6% | 78,6% |
javalin | 372 | 1 | 1 | 16,4% | 97,0% |
kotlinx.coroutines | 1105 | 2 | 1 | 29,7% | 73,2% |
ktor | 2631 | 4 | 1 | 26,4% | 62,6% |
okhttp | 690 | 1 | 1 | 1,6% | 62,5% |
spring‑petclinic | 50 | 4 | 1 | 46,0% | 74,0% |
Открытый проект не равен команде в компании, об этом ниже. Но механика ошибок одна и та же, и шесть из них я разберу по порядку.
Перед схемой коротко о том, как файл становится ничьим. На схеме ниже путь от истории правок до вывода.

Главная мысль схемы: история git помнит авторов, но не знает, кто из них ещё в команде и кто на самом деле читал код, который принял от агента. Обе проверки руководителю приходится делать самому.
Ошибка 1. Считать устойчивость команды по всей истории
Симптом. Отчёт показывает у модуля четырёх авторов, и руководитель спокоен.
Неверное объяснение. «Раз авторов несколько, уход одного переживём».
Настоящая причина. Git помнит всех. В ktor и spring‑petclinic truck factor по всей истории равен четырём, а среди тех, кто коммитил за последний год, — единице. Остальные авторы больше не коммитят, но расчёт продолжает на них опираться.
Последствие. Риск недооценён ровно в тот момент, когда его можно было снять дёшево.
Исправление. Считать truck factor только по активным людям и смотреть на долю ничьих файлов. Я проверил, не держится ли вывод на выбранном окне в 12 месяцев: при окне в 6 и 24 месяца доля ничьих файлов в пяти проектах из шести меняется на 0,3–3,7 процентного пункта. Сильно сдвигается только маленький spring‑petclinic: 56% при окне в полгода и 30% при двух годах.
Когда возникает. В проектах, где команда успела смениться хотя бы наполовину.
Ошибка 2. Верить файлу владельцев кода
Симптом. У каждого модуля в файле владельцев записаны два‑три человека, ревью без них не проходит.
Неверное объяснение. «Владельцы назначены, значит, знания распределены».
Настоящая причина. Файл владельцев решает, кого звать на ревью, а обязательность одобрения задают правила защиты ветки. Ни то ни другое не говорит, кто знает код. Сам файл заполняют один раз при создании модуля и почти не обновляют. Совпадает ли владелец по файлу с автором по истории, проверяется за минуту: достаточно положить рядом два списка.
Последствие. Руководитель планирует уход человека по документу, который уже не отражает реальность.
Исправление. Раз в квартал сверять файл владельцев с картой авторства. Если расчёт не приписывает владельцу ни одного файла в модуле, это повод проверить, знает ли он модуль на деле: дать ему небольшую задачу там или разобрать с ним последний инцидент.
Когда возникает. Когда файл владельцев завели при запуске модуля, а состав с тех пор менялся.
Ошибка 3. Ревью одним и тем же человеком
Симптом. Любой PR в модуль одобряет один и тот же старший разработчик, потому что «он лучше всех знает этот код».
Неверное объяснение. «Ревью и есть передача знаний: все видят изменения».
Настоящая причина. Ревьюер не становится автором. В расчёте степени авторства одобрение вообще не участвует, и это честно: прочитать чужой дифф и уметь чинить модуль ночью — разные навыки. Ревью одним человеком к тому же закрепляет его роль единственного знатока.
Последствие. Модуль держится на одном человеке, хотя через него проходят все.
Исправление. Ротация в паре: второй ревьюер выбирается из тех, у кого в модуле нет файлов, первые ревью проходит вместе с автором и разбирает не только дифф, но и ограничения модуля, а следом получает там свою задачу. Я бы предложил начинать с модулей, где «Ничьё без лидера» выше половины, а не со всей кодовой базы сразу.
Когда возникает. В командах, где ревью назначается вручную и по привычке достаётся самому опытному.
Ошибка 4. Считать документацию страховкой
Симптом. После тревожного разговора команда пишет страницу в вики с описанием модуля, и тема закрыта.
Неверное объяснение. «Всё записано, новый человек прочитает».
Настоящая причина. Документация переносит описание, но не умение. Пока человек сам не поменял код и не довёл изменение до продакшена, он не знает, где в модуле острые углы. Поэтому в расчёте степень авторства растёт только от собственных правок.
Последствие. В день инцидента страница есть, а того, кто по ней что‑то делал, нет.
Исправление. Страница остаётся, но к ней добавляются задачи. Каждый квартал по одной небольшой задаче в чужом модуле на человека, с ревью от текущего автора. Мой вариант — брать для этого технический долг: он всё равно нужен, а риск ошибки невысокий.
Когда возникает. После разговора о рисках, когда хочется закрыть тему быстро и без перестройки планов.
Ошибка 5. Передавать дела за две недели отработки
Симптом. Заявление подано, уходящий проводит три созвона по своим модулям, запись лежит в облаке.
Неверное объяснение. «Главное — успеть выгрузить знания из головы».
Настоящая причина. Двух недель не хватает на то, что копилось годами. Таблица выше показывает масштаб: если завтра уйдёт самый крупный из активных авторов, без автора останется от 62,5 до 97% файлов проекта.
Последствие. Передача дел превращается в лекцию, а лекция быстро забывается.
Исправление. Готовиться к уходу до заявления. Карта ничьих файлов «если уйдёт лидер» считается заранее, и по ней видно, кому и какие задачи давать уже в этом квартале. Когда заявление всё‑таки придёт, две недели уйдут на остаток, а не на всё сразу.
Когда возникает. Всегда, когда о концентрации знаний вспоминают только в момент ухода.
Ошибка 6. Записывать код агента на автора коммита
Симптом. За год в модуль вошли десятки коммитов, сделанных вместе с агентом. Автором коммита везде числится человек, а на вопрос «почему здесь так» он отвечает «так предложил агент».
Неверное объяснение. «Человек принял изменение, значит, он его понимает».
Настоящая причина. Расчёт берёт из git поле Author, и правка с агентом засчитывается человеку, который в нём стоит. В ktor за последний год 43 коммита с агентом затронули 198 файлов, и в 128 из них расчёт считает автором этого человека. Агента расчёт распознаёт по двум признакам: по трейлеру, служебной строке вида
Co-authored-by:в конце сообщения коммита, или по имени и адресу самого автора коммита. Это эвристика: агент без таких следов останется незамеченным, а служебную учётку правило может принять за агента. Код, принятый из чата без следов, неотличим от написанного руками.Последствие. Карта авторства показывает человека там, где он, возможно, только принял дифф. Насколько это сдвигает цифры, я проверил пересчётом: в нём ни один коммит с распознанным агентом за всю историю, а не только за год, не засчитывается человеку ни как создание файла, ни как правка, но из истории не удаляется и остаётся чужой правкой файла. Состав активных я оставил прежним. Сценарий нарочно жёсткий: даже правку, которую человек переписал сам, он не считает человеческой. Это проверка чувствительности, а не оценка доли кода, написанного агентом. Truck factor не изменился ни в одном проекте, ни по всей истории, ни среди активных. А вот ничьих файлов в ktor стало 29,7% вместо 26,4%, и без лидера 65,5% вместо 62,6%, в javalin 16,7% вместо 16,4%. Агент уже прячет часть ничьих файлов: в ktor больше трёх процентных пунктов, и это только те случаи, которые удалось распознать по метаданным git.
Исправление. Договориться в команде подписывать коммиты с агентом трейлером и считать такие правки отдельно. Для файлов, которые за год затронули коммиты с агентом, второй ревьюер обязателен, а автор изменения на ревью объясняет решение своими словами.
Когда возникает. В командах, где агентом пользуются давно, а правила ревью остались прежними.
История: проект с одним мейнтейнером
Самая известная история про проект, который держался на одном человеке, случилась с XZ Utils, библиотекой сжатия, которая стоит почти в каждом дистрибутиве Linux. В июне 2022 года в рассылке проекта, в ветке про XZ for Java, один из участников написал, что прогресса не будет, пока не появится новый мейнтейнер, и отдельно упрекнул XZ for C в редких коммитах.
Мейнтейнер Лассе Коллин ответил, что его возможности сильно ограничены из‑за долгих проблем со здоровьем, что это неоплачиваемый проект и что он уже немного работал с Jia Tan, у которого в будущем может быть роль больше.
Роль действительно выросла. В 2024 году в архивах релизов 5.6.0 и 5.6.1, собранных и подписанных Jia Tan, нашли бэкдор, уязвимость получила номер CVE-2024-3094. Truck factor проекта я здесь не считал, это не пример цифры.
Для руководителя это история не про личные качества мейнтейнера, а про сочетание трёх вещей: ресурсов на сопровождение мало, полномочия сосредоточены у одного‑двух людей, а независимая проверка критичных изменений и релизных архивов не поймала подмену до релиза.
Механика та же и в команде, где все добросовестны: когда всё держится на одном, преемника выбирают не по плану, а по обстоятельствам, а проверка изменений нужна при любой репутации.
Что делать: план на квартал
Ниже на схеме исправления из шести ошибок собраны в один цикл. Он повторяется раз в квартал.

Что важно на схеме: исправления запускаются не по поводу ухода человека, а по графику, и каждое следующее начинается с цифры, а не с ощущения.
Сводная таблица
Ошибка | Признак | Что проверить |
|---|---|---|
Устойчивость по всей истории | Авторов много, но часть давно не коммитит | Truck factor только по активным |
Вера файлу владельцев | Владелец без своих файлов в модуле | Сверка с картой авторства |
Ревью одним человеком | Все PR модуля одобряет один | Доля ревью у второго ревьюера |
Документация как страховка | Вики есть, задач в модуле у других нет | Число людей с правками за квартал |
Передача дел за две недели | Созвоны вместо задач | Карта «если уйдёт лидер» заранее |
Код агента на авторе коммита | Автор не может объяснить решение | Файлы, затронутые коммитами с агентом |
Чек‑лист
1. Посчитать truck factor и долю ничьих файлов по активным авторам.
2. Посчитать ту же долю на случай ухода самого крупного автора.
3. Сверить файл владельцев с картой авторства.
4. Назначить второго ревьюера в модули, где без лидера ничьей станет больше половины файлов.
5. Дать каждому по задаче в чужом модуле на квартал.
6. Ввести трейлер для коммитов с агентом и считать их отдельно.
7. Повторить замер через квартал и сравнить.
Где это не сработает
Авторство по git — приближение. Человек мог разобраться в модуле на дежурствах и ни разу не менять код, и расчёт его не увидит. «Активный» значит коммитил в репозиторий за год, а не работает в команде сегодня.
Считаются файлы, а не строки, и большой модуль весит столько же, сколько маленький. Псевдонимы склеиваются по адресу и по имени с отличием в одну букву, и на похожих именах склейка может ошибиться.
В открытых проектах много разовых участников, а в команде компании ушедший часто сидит в соседнем отделе и отвечает в чате. Поэтому цифры из таблицы не стоит переносить на свою команду напрямую: их нужно посчитать на своей истории.
Вывод
Эта группа ошибок проверяет навык руководителя видеть риск в цифрах до того, как он стал инцидентом. Truck factor не меняется от совещаний и страниц в вики: он меняется, когда другие люди правят код в чужих модулях.
А с агентами появилась новая слепая зона: git хранит автора коммита, но не знает, кто на деле написал код и понял ли его автор, поэтому понимание надо проверять отдельно.
Ссылка на мой репозиторий с экспериментом: https://github.com/sproshchaev/bus‑factor‑from‑git
Начать стоит с expected.txt: там все четыре таблицы, на которые опирается статья, включая проверку при окне активности 6 и 24 месяца и пересчёт без правок с агентом. Как считается авторство и truck factor, видно в bus_factor.py, выгрузки истории шести проектов лежат в data/, а пересчёт со сверкой запускается командой ./run.sh.
Источники:

Если критичные знания сосредоточены у нескольких разработчиков, а распределение ответственности существует только на бумаге, важно не просто зафиксировать риски, но и изменить подход к управлению командой.
Разобраться в управлении знаниями и командой помогут открытые уроки:
5 ноября, 20:00. «Knowledge‑centered service и подходы к структурированию баз знаний». Записаться
9 ноября, 20:00. «Качество без микроменеджмента: что должен контролировать CTO». Записаться
Больше актуальных материалов по разработке, управлению и ИТ-архитектуре — в дайджесте ноября.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.