Skip to content

Commit 1feac7a

Browse files
author
Test
committed
feat: production-ready git-stats-cli with performance optimizations
- Linguist language detection via go-enry - Fast path without churn by default; parallel churn with --churn - Support bare/shallow repos, JSON/MD/HTML reports - CI and GoReleaser release pipeline
1 parent db49355 commit 1feac7a

24 files changed

Lines changed: 1155 additions & 259 deletions

‎.goreleaser.yaml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ builds:
2222
- arm64
2323
ldflags:
2424
- -s -w
25+
- -X github.com/loSpaccaBit/git-stats-cli/internal/version.Version={{.Version}}
2526

2627
archives:
2728
- id: default

‎README.md‎

Lines changed: 72 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,22 @@
22

33
[![CI](https://github.com/loSpaccaBit/git-stats-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/loSpaccaBit/git-stats-cli/actions/workflows/ci.yml)
44
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
5-
[![Go Report Card](https://goreportcard.com/badge/github.com/loSpaccaBit/git-stats-cli)](https://goreportcard.com/report/github.com/loSpaccaBit/git-stats-cli)
65

7-
A command-line tool to analyze Git repositories and generate insightful reports — without requiring the `git` binary installed.
6+
Production-grade CLI to analyze Git repositories locally using **go-git** and **go-enry** (GitHub Linguist rules).
87

9-
Built with **Go**, **Cobra**, and **go-git**.
8+
No `git` binary required.
109

1110
## Features
1211

13-
- Analyze local repositories with `git-stats analyze`
14-
- Terminal output with colored tables (disable with `--no-color`)
15-
- Export reports as JSON, Markdown, or HTML
16-
- Cross-platform binaries via GoReleaser
17-
- Docker support
12+
- **Complete commit scan** — analyzes every commit object available locally (all branches/tags present in the object database)
13+
- **Linguist-compatible languages** — byte share, file counts, and percentages at `HEAD`
14+
- **Authors** — unique contributor count + configurable top-N ranking
15+
- **Activity windows** — 30 / 90 / 365 days
16+
- **Monthly trends** — configurable number of recent months
17+
- **Code churn** — lines added/deleted and files changed (disable with `--no-churn`)
18+
- **Repository metadata** — default branch, branch/tag counts, bare & shallow detection
19+
- **Reports** — JSON, Markdown, HTML
20+
- **Cross-platform releases** — GoReleaser builds for Linux, macOS, Windows (amd64 + arm64)
1821

1922
## Installation
2023

@@ -33,32 +36,53 @@ docker run --rm -v "$(pwd):/repo" git-stats-cli analyze /repo
3336

3437
### GitHub Releases
3538

36-
Download the latest binary for your OS from [Releases](https://github.com/loSpaccaBit/git-stats-cli/releases).
39+
Download binaries from [Releases](https://github.com/loSpaccaBit/git-stats-cli/releases).
3740

3841
## Usage
3942

40-
### Analyze a repository
41-
4243
```bash
44+
# Terminal report (fast — churn off by default)
4345
git-stats analyze .
4446
git-stats analyze /path/to/repo
47+
48+
# Enable churn stats on large repos (slower, uses parallel workers)
49+
git-stats --churn analyze /path/to/repo
50+
git-stats --churn --workers 8 analyze /path/to/repo
51+
52+
# Show timing
53+
git-stats -v analyze /path/to/repo
54+
55+
# Disable colors
4556
git-stats --no-color analyze .
57+
58+
# Show top 20 authors, last 6 months
59+
git-stats --top 20 --months 6 analyze .
60+
61+
# Export reports
62+
git-stats report -f json -o report.json .
63+
git-stats report -f md -o report.md .
64+
git-stats report -f html -o report.html .
65+
66+
# Version
67+
git-stats --version
4668
```
4769

48-
Output includes:
70+
## Output
4971

50-
- Total commits
51-
- Top authors by commit count
52-
- Languages detected from file extensions
53-
- Activity in the last 30 and 90 days
72+
### Terminal (`analyze`)
5473

55-
### Generate a report
74+
- Repository path, commits, authors
75+
- Branch/tag metadata, shallow/bare flags
76+
- Activity (30/90/365 days)
77+
- Code churn (lines added/deleted, files changed)
78+
- Top authors table
79+
- Languages at HEAD with bytes and percentage (Linguist)
80+
- Monthly commit trend
81+
- Warnings (e.g. shallow clone, empty repository)
5682

57-
```bash
58-
git-stats report --format=json --output=report.json .
59-
git-stats report --format=md --output=report.md .
60-
git-stats report --format=html --output=report.html .
61-
```
83+
### Reports (`report`)
84+
85+
Same data in machine-readable JSON or human-readable Markdown/HTML.
6286

6387
## Tech Stack
6488

@@ -67,8 +91,8 @@ git-stats report --format=html --output=report.html .
6791
| Language | Go 1.22+ |
6892
| CLI | Cobra |
6993
| Git parsing | go-git |
94+
| Language detection | go-enry (Linguist) |
7095
| Terminal output | fatih/color, tablewriter |
71-
| Reports | encoding/json, text/html templates |
7296
| Testing | testing + testify |
7397
| CI/CD | GitHub Actions + GoReleaser |
7498

@@ -78,51 +102,53 @@ git-stats report --format=html --output=report.html .
78102
git-stats-cli/
79103
├── cmd/git-stats/ # CLI entrypoint
80104
├── internal/
81-
│ ├── analyzer/ # Repository analysis logic
82-
│ ├── formatter/ # JSON, Markdown, HTML, terminal output
83-
│ ├── git/ # go-git wrapper
84-
│ └── report/ # Report generation
105+
│ ├── analyzer/ # Analysis engine
106+
│ ├── formatter/ # Terminal + export renderers
107+
│ ├── git/ # go-git wrapper + language detection
108+
│ ├── report/ # Report orchestration
109+
│ └── version/ # Build version injection
85110
├── pkg/stats/ # Shared data models
86111
└── .github/workflows/ # CI and release pipelines
87112
```
88113

89114
## Development
90115

91-
### Prerequisites
92-
93-
- Go 1.22+
94-
- Git (for development only; runtime uses go-git)
95-
96-
### Setup
97-
98116
```bash
99117
git clone https://github.com/loSpaccaBit/git-stats-cli.git
100118
cd git-stats-cli
101-
go mod download
119+
go test ./...
120+
go build -o git-stats ./cmd/git-stats
102121
```
103122

104-
### Run tests
123+
## Releasing
105124

106125
```bash
107-
go test ./...
126+
git tag v0.1.0
127+
git push origin v0.1.0
108128
```
109129

110-
### Build locally
130+
GoReleaser publishes multi-platform binaries and attaches checksums automatically.
111131

112-
```bash
113-
go build -o git-stats ./cmd/git-stats
114-
./git-stats analyze .
115-
```
132+
## Performance
116133

117-
## Releasing
134+
| Mode | When to use |
135+
|------|-------------|
136+
| Default (no `--churn`) | Day-to-day use, large repos, reports json/md/html |
137+
| `--churn` | When you need lines added/deleted; parallelized via `--workers` |
138+
| `-v` / `--verbose` | Prints analysis duration to stderr |
118139

119-
Tag a version to trigger GoReleaser:
140+
Benchmark on a local repo:
120141

121142
```bash
122-
git tag v0.1.0
123-
git push origin v0.1.0
143+
GIT_STATS_BENCH_REPO=/path/to/repo go test ./internal/analyzer -bench=. -benchmem
124144
```
125145

146+
## Limitations
147+
148+
- Analysis is **local only** — only objects present in the repository are counted.
149+
- **Shallow clones** analyze available history; a warning is shown when `.git/shallow` is detected.
150+
- Language stats reflect the **HEAD tree**, not historical composition.
151+
126152
## License
127153

128154
MIT — see [LICENSE](LICENSE).

‎go.mod‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.25.1
44

55
require (
66
github.com/fatih/color v1.19.0
7+
github.com/go-enry/go-enry/v2 v2.9.6
78
github.com/go-git/go-git/v5 v5.19.1
89
github.com/olekukonko/tablewriter v0.0.5
910
github.com/spf13/cobra v1.10.2
@@ -19,6 +20,7 @@ require (
1920
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
2021
github.com/davecgh/go-spew v1.1.1 // indirect
2122
github.com/emirpasic/gods v1.18.1 // indirect
23+
github.com/go-enry/go-oniguruma v1.2.1 // indirect
2224
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
2325
github.com/go-git/go-billy/v5 v5.9.0 // indirect
2426
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect

‎go.sum‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w=
2727
github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE=
2828
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
2929
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
30+
github.com/go-enry/go-enry/v2 v2.9.6 h1:np63eOtMV56zfYDHnFVgpEVOk8fr2kmylcMnAZUDbSs=
31+
github.com/go-enry/go-enry/v2 v2.9.6/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8=
32+
github.com/go-enry/go-oniguruma v1.2.1 h1:k8aAMuJfMrqm/56SG2lV9Cfti6tC4x8673aHCcBk+eo=
33+
github.com/go-enry/go-oniguruma v1.2.1/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4=
3034
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
3135
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
3236
github.com/go-git/go-billy/v5 v5.9.0 h1:jItGXszUDRtR/AlferWPTMN4j38BQ88XnXKbilmmBPA=
@@ -84,8 +88,13 @@ github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiT
8488
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
8589
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
8690
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
91+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
92+
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
8793
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
8894
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
95+
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
96+
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
97+
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
8998
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
9099
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
91100
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
@@ -122,6 +131,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV
122131
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
123132
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
124133
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
134+
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
125135
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
136+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
126137
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
127138
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)