← Все проекты

Кейс · CLI-утилита

GitPulse: аналитика git-репозиториев

CLI на Go для анализа git-репозиториев без внешних зависимостей (нужен только git): stats с цветами и спарклайнами в терминале, report — самодостаточный HTML-отчёт с тепловой картой активности, churn и горячими файлами, вкладом авторов, bus factor по каталогам, ростом кода по языкам и периодами тишины (светлая и тёмная темы), diff-hotspots между ревизиями и локальный serve на 127.0.0.1. История читается потоком через git log -z --numstat -M. Пет-проект.

  • Go
  • stdlib only
  • CLI
  • git
  • html/template
  • SVG
  • ANSI
  • os/exec
  • GitHub Actions
  • Docker

01 · Как выглядит

Скриншоты

Скриншот проекта «GitPulse: аналитика git-репозиториев» на экране 1280 пикселей
Десктоп, 1280 px
Скриншот проекта «GitPulse: аналитика git-репозиториев» на экране телефона, 390 пикселей
Телефон, 390 px

02 · О проекте

Что это и зачем

GitPulse — консольная утилита на Go для анализа git-репозиториев: по истории коммитов она показывает, где кипит работа, какие файлы правят чаще всего, кто и сколько вложил и в каких каталогах знание держится на одном человеке. Пет-проект.

Только стандартная библиотека Go, внешний бинарник один — git. Историю читает потоком через git log -z --numstat -M (через os/exec): собственный разбор packfile не делался, потому что нужны .mailmap, shallow-клоны и обнаружение переименований, а они надёжно решены в самом git. Результат один и тот же для терминала, HTML и JSON.

Ограничения

Нужен установленный git. Время считается по UTC автора, часовой пояс автора не учитывается; слияния не анализируются, так что работа, видимая только в слиянии, пропадает.

Рост языков — оценка «добавлено минус удалено» по расширениям, а не снимок дерева. Bus factor и риск — эвристики по числу строк в коммитах, а не по реальному знанию кода; рефакторинги и массовые правки их искажают.

Память растёт с числом файлов и авторов; на очень больших репозиториях нужны -max-commits и -since. В -json есть почты авторов, в HTML их нет, но имена в отчёте есть, поэтому публиковать его стоит после проверки.

На macOS в CI тесты не идут (раннер не выдали), darwin собирается кросс-компиляцией; тесты с -race проходят только в CI; Dockerfile не проверялся.

Что внутри

  • Команда stats: сводка, активность по неделям со спарклайнами, churn, горячие файлы с риском, авторы, bus factor, размеры коммитов, языки и паузы в терминале с цветами и ANSI (NO_COLOR и -color auto|always|never учитываются)
  • Команда report: самодостаточный HTML-отчёт одним файлом без внешних запросов: тепловая карта активности, churn, вклад авторов, bus factor по каталогам, рост кода по языкам, периоды тишины, светлая и тёмная темы, SVG-графики
  • Команда diff-hotspots <rev1>..<rev2>: горячие файлы и вклад авторов внутри диапазона ревизий
  • Команда serve: отчёт в браузере на 127.0.0.1 (только loopback-адрес), проверка заголовка Host против DNS-rebinding, CSP, кеш результата, /api/stats и /healthz
  • Потоковый разбор git log -z --numstat -M: в памяти живёт один коммит, пути с табами и кириллицей не ломаются, переименования прослеживаются (история старого пути засчитывается новому), .mailmap учитывается через %aN/%aE
  • Флаги -json, -since, -until, -max-commits, -top, -depth, -include-generated, -quiet и -color; lock-файлы, vendor/, node_modules/ и min-файлы по умолчанию пропускаются; коды возврата 0/1/2/3/130
  • Тесты строят синтетические репозитории через git и сверяют метрики с заранее посчитанными числами; golden-тест структуры HTML и проверка, что отчёт самодостаточен и экранирован
  • Кросс-сборка под windows, linux и darwin скриптом scripts/build.sh, CI в GitHub Actions и Dockerfile; на синтетической истории из 100 000 коммитов анализ занимает около 5 секунд

03 · Как запустить

Запуск одной командой

git clone <репозиторий по запросу> gitpulse
cd gitpulse
go run ./cmd/gitpulse stats .                   # таблицы в терминале (нужен git в PATH)
go run ./cmd/gitpulse report -o report.html .  # HTML-отчёт одним файлом

04 · Код

Репозиторий приватный

Исходники лежат в приватном репозитории. Открою доступ по запросу: напишите, и пришлю приглашение.

Запросить код