Все статьи

Почему количество коммитов обманывает и что считать вместо него

Число коммитов — самая доступная инженерная метрика и самая легко подделываемая. Разбираем, что она измеряет на самом деле, где ломается и какую оценку мы используем вместо неё.

Команда DevGhost · Опубликовано

Любой инженерный дашборд начинается одинаково: коммиты на разработчика в неделю. Это единственное число, которое любой git-хостинг отдаёт бесплатно. И это же число чаще всего уводит команду не туда.

Речь не о том, чтобы не измерять ничего. Речь о том, чтобы измерять то, что действительно важно, — сколько инженерных усилий вложено в кодовую базу, — а не то, что просто удобно посчитать.

Что на самом деле измеряет счётчик коммитов

Коммит — это точка сохранения. Нигде в git не написано, что коммит обязан соответствовать единице работы, фиче или часу размышлений. Счётчик коммитов измеряет как часто разработчик решает записать что-то в историю, а это привычка, а не результат.

Двое разработчиков могут выкатить одну и ту же фичу с совершенно разным числом коммитов:

  • один коммитит после каждого зелёного теста и заканчивает неделю с 60 коммитами;
  • второй перед открытием pull request сводит ветку rebase-ом в три аккуратных коммита.

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

Как только метрика становится целью, люди начинают оптимизировать метрику. В случае коммитов оптимизация тривиальна и незаметна: коммить чаще. Продукт при этом не улучшается никак.

Где это ломается на практике

Squash-мерж уничтожает сигнал полностью

Если команда сливает pull request через squash, вся ветка схлопывается в один коммит, приписанный тому, кто нажал кнопку. Двухнедельная фича и исправление опечатки теперь неразличимы — и то и другое один коммит. Любая команда на squash-процессе измеряет свою политику слияния, а не свою инженерию.

Строки кода ситуацию не спасают

Обычное «лекарство» — перейти на количество изменённых строк. Это хуже. Строки поощряют многословность, наказывают за удаление и оценивают сгенерированный lock-файл как месяц работы:

Изменение Строки Реальные усилия
Перегенерация pnpm-lock.yaml +4120 / −3987 секунды
Удаление мёртвой подсистемы −2400 дни на обход вызовов
Правка ошибки на единицу в планировщике +1 / −1 возможно, неделя

Третья строка — единственная, которая по-настоящему важна, и именно её обе метрики оценивают в ноль.

Сгенерированный и вендоренный код топит настоящую работу

Один npm install или закоммиченная миграция могут перевесить все написанные руками изменения за тот же период. Пока сгенерированный контент не распознан и не исключён, метрика измеряет в основном шум от тулинга.

Что считать вместо этого

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

DevGhost оценивает её по каждому изменению, опираясь на свойства самого изменения, а не на его размер:

усилия(изменение) = f(
  новизна,            # новая логика против механической правки
  структурная глубина, # насколько глубоко изменение уходит в систему
  объём контекста,     # сколько окружающего кода нужно понять
  сгенерировано?       # исключается, если контент машинный
)

Результат удерживают на земле два ограничения:

  1. Потолок на изменение. Одно изменение не может вобрать больше усилий, чем разработчик реально мог на него потратить, поэтому один крупный рефакторинг не искажает квартал.
  2. Потолок на день. Усилия распределяются по дням, в которые разработчик действительно мог работать, и никогда не сваливаются в одну дату только потому, что в этот день приземлился коммит.

Итог сопоставим между squash- и merge-процессами, между многословными и лаконичными коммитерами и между языками — потому что ни одна из этих вещей не меняет объём мышления, которого потребовало изменение.

Как читать эту оценку

Относитесь к ней как к порядку величины, а не как к табелю учёта времени. Она отвечает на вопросы, недоступные счётчику коммитов:

  • Какие части системы съели усилия, которых никто не планировал?
  • Какая доля прошлого квартала ушла в работу, которой больше нет в кодовой базе?
  • Где разрыв между тем, куда команда потратила время, и тем, что обещала дорожная карта?

Вот на эти вопросы имеет смысл иметь число. «Кто больше всех накоммитил за неделю» — не из их числа.

Что почитать дальше