lex0c/gitcortex

GitHub: lex0c/gitcortex

一款专注于 Git 仓库本地指标提取与统计的 CLI 工具,帮助开发者在离线环境下洞察代码质量与协作风险。

Stars: 0 | Forks: 0

# gitcortex 提取提交元数据、文件变更、blob 大小和开发者信息到 JSONL。生成顶级贡献者、文件热点、巴士因子、耦合分析、变更风险、工作模式以及开发者协作网络等统计信息。 ## 性能 在开源仓库上进行基准测试。`extract` 读取裸克隆;`stats` 和 `report` 读取生成的 JSONL。在单台机器上使用预构建二进制文件进行测量(非受控实验室基准;仅作方向性参考,非绝对值)。 | 仓库 | 提交数 | 开发者数 | Extract | Stats (JSON) | Report (HTML) | JSONL 行数 | |------------|---------|------|---------|-------------|--------------|------------| | [Pi-hole](https://github.com/pi-hole/pi-hole) | 7,077 | 281 | 1.5s | 0.18s | 0.24s | 23K 行 / 6.5 MB | | [Praat](https://github.com/praat/praat) | 10,221 | 19 | 25s | 0.96s | 0.95s | 95K 行 / 30 MB | | [WordPress](https://github.com/WordPress/WordPress) | 52,466 | 131 | 47s | 2.9s | 2.8s | 298K 行 / 96 MB | | [Kubernetes](https://github.com/kubernetes/kubernetes) | 137,016 | 5,295 | 2m 4s | 11.7s | 14s | 943K 行 / 314 MB | | [Linux kernel](https://github.com/torvalds/linux) | 1,438,634 | 38,832 | 12m 57s | 1m 15s | 1m 53s | 6M 行 / 1.9 GB | `extract`、`stats` 和 `report` 的扩展性大致与数据规模线性相关。`report` 中的每开发者协作图谱在文件遍历过程中通过一次遍历预先计算(O(F × D_per_file²));在 Kubernetes 快照上这会增加约 2 秒,Linux 上约 40 秒。若之前的实现在每个开发者循环内嵌套了文件遍历(O(D × F × D_per_file)),则在 Kubernetes 上慢 6 倍,在 Linux 上慢 11 倍。如果只需要聚合数据,`stats --format json` 始终是最快的路径;当你真正需要 HTML 仪表板时再使用 `report`。 ## 供应商与生成的代码 **这是每个统计中最大的实际失真。** 行数统计将 5 万行的 `generated.pb.go` 与 5 万行的手写模块视为等同。`package-lock.json` 这类锁文件会随每次依赖更新而重新生成。供应商依赖在每次更新时都会增加变更计数。OpenAPI 规范、压缩的 JS、`bindata.go` 风格的嵌入文件——这些都很常见,都会增加变更计数和巴士因子,却不能反映真实的人类贡献。 在不加过滤的情况下运行 gitcortex 处理 Kubernetes,前十大历史热点将是 `vendor/golang.org/x/tools/…/manifest.go`、`api/openapi-spec/v3/…v1alpha3_openapi.json` 和 `staging/…/generated.pb.go` —— 从数据上看技术上正确,但从决策角度看实际上毫无用处。 通过在提取时使用 `--ignore` 通配模式来缓解。匹配的文件会完全从 JSONL 中丢弃,因此 **所有下游统计**(热点、变更风险、巴士因子、耦合、开发者网络、个人资料)都将只反映手工编写的代码: ``` # 典型入门套件 gitcortex extract --repo . \ --ignore "vendor/*" \ --ignore "node_modules/*" \ --ignore "dist/*" \ --ignore "build/*" \ --ignore "*.min.js" \ --ignore "*.min.css" \ --ignore "package-lock.json" \ --ignore "yarn.lock" \ --ignore "Cargo.lock" \ --ignore "go.sum" \ --ignore "poetry.lock" \ --ignore "*.pb.go" \ --ignore "*_generated.go" ``` 模式匹配 `git log --raw` 输出的文件路径(使用正斜杠,相对于仓库根目录)。目录模式如 `vendor/*` 会排除该前缀下的所有内容。文件名模式如 `*.pb.go` 在任意深度匹配。 从宽松的规则开始,运行 `gitcortex stats --stat hotspots --top 20` 和 `--stat churn-risk --top 20`,然后为输出中占主导地位的文件类型添加 `--ignore` 条目。重新提取,直到前十大列表代表真正值得理解的变更。 ## 隐私与可靠性 所有处理均在 **本地 100% 完成**。不依赖外部服务、不进行网络调用、**不使用 AI**、不发送遥测数据。gitcortex 仅读取 Git 元数据(提交、作者、日期、文件路径、行数)——它永远不会读取源代码内容。提交消息默认不包含,仅在使用 `--include-commit-messages` 时包含。数据保留在你的机器上,作为一个由你控制的 JSONL 文件。 ## 安装 ### 下载二进制文件(无需 Go) 适用于 Linux、macOS 和 Windows 的预构建二进制文件可在 [GitHub Releases](https://github.com/lex0c/gitcortex/releases/latest) 获取: ``` # Linux (x64) curl -L https://github.com/lex0c/gitcortex/releases/latest/download/gitcortex-linux-amd64 -o gitcortex chmod +x gitcortex sudo mv gitcortex /usr/local/bin/ # macOS (Apple Silicon) curl -L https://github.com/lex0c/gitcortex/releases/latest/download/gitcortex-darwin-arm64 -o gitcortex chmod +x gitcortex sudo mv gitcortex /usr/local/bin/ # macOS (Intel) curl -L https://github.com/lex0c/gitcortex/releases/latest/download/gitcortex-darwin-amd64 -o gitcortex chmod +x gitcortex sudo mv gitcortex /usr/local/bin/ ``` ### Go 安装 ``` go install github.com/lex0c/gitcortex/cmd/gitcortex@latest ``` ### 从源码构建 ``` git clone https://github.com/lex0c/gitcortex.git cd gitcortex make build ``` 其他目标:`make test`、`make vet`、`make check`(vet + test)、`make install`、`make clean`。 检查版本:`gitcortex --version` 要求 Git 2.31+ 和 Go 1.21+。CI 在每次推送/拉取请求时通过 GitHub Actions 自动运行。 ### 发布 ``` git tag v0.1.0 git push origin main --tags ``` 版本在构建时从 `git describe --tags` 注入。标记后执行 `make build && gitcortex --version` 将显示 `v0.1.0`。 ## 使用 ### 提取 ``` # 从当前目录提取 gitcortex extract # 从特定仓库和分支提取 gitcortex extract --repo /path/to/repo --branch main # 在输出中包含提交信息 gitcortex extract --repo /path/to/repo --include-commit-messages # 自定义输出路径 gitcortex extract --repo /path/to/repo --output data.jsonl # 通过 .mailmap 规范化作者标识 gitcortex extract --repo /path/to/repo --mailmap # 排除提取的文件 gitcortex extract --repo /path/to/repo --ignore package-lock.json --ignore "*.min.js" # 排除整个目录 gitcortex extract --repo /path/to/repo --ignore "dist/*" --ignore "vendor/*" ``` 默认分支从 `origin/HEAD` 自动检测,若不可用则回退到 `main`、`master` 或 `HEAD`。 `--mailmap` 标志使用 Git 内置的 `.mailmap` 支持来统一开发者身份。启用它可避免同一人以不同邮箱(例如 `alice@work.com` 和 `alice@personal.com`)被当作不同贡献者。 输出为 JSONL 文件,每行一条记录。四种记录类型: ``` {"type":"commit","sha":"abc...","tree":"def...","parents":["ghi..."],"author_name":"Alice","author_email":"alice@example.com","author_date":"2024-01-15T10:30:00Z","committer_name":"Alice","committer_email":"alice@example.com","committer_date":"2024-01-15T10:30:00Z","message":"","additions":42,"deletions":7,"files_changed":3} {"type":"commit_parent","sha":"abc...","parent_sha":"ghi..."} {"type":"commit_file","commit":"abc...","path_current":"src/main.go","path_previous":"src/main.go","status":"M","old_hash":"111...","new_hash":"222...","old_size":1024,"new_size":1087,"additions":10,"deletions":3} {"type":"dev","dev_id":"sha256hash...","name":"Alice","email":"alice@example.com"} ``` ### 恢复 提取过程可恢复。状态会保存在文件中(默认 `git_state`),在每个检查点保存: ``` # 首次运行(中断或已完成) gitcortex extract --repo /path/to/repo --output data.jsonl # 从中断处恢复 gitcortex extract --repo /path/to/repo --output data.jsonl ``` 检查点间隔由 `--batch-size` 控制(默认 1000 次提交)。 ### 统计 ``` # 全部统计(表格格式) gitcortex stats --input data.jsonl # 单个统计 gitcortex stats --input data.jsonl --stat contributors --top 20 # 多仓库:跨仓库聚合统计 gitcortex stats --input svc-auth.jsonl --input svc-payments.jsonl --input svc-gateway.jsonl # 导出为 CSV 或 JSON gitcortex stats --input data.jsonl --stat hotspots --format csv > hotspots.csv gitcortex stats --input data.jsonl --format json > report.json # 按周活动 gitcortex stats --input data.jsonl --stat activity --granularity week # 过滤到最近时段 gitcortex stats --since 7d # last 7 days gitcortex stats --since 3m --stat contributors # last 3 months gitcortex report --since 30d --output monthly.html ``` 可用统计项: | 统计项 | 描述 | |------|-------------| | `summary` | 总提交数、开发者数、文件数、增加/删除行数、合并次数、平均值、日期范围 | | `contributors` | 按提交数排名的开发者,含每位开发者的增加/删除行数 | | `hotspots` | 最常变更的文件及其变更次数与唯一开发者数 | | `activity` | 按天、周、月或年统计的提交与变更行数 | | `busfactor` | 变更占比超过 80% 的开发者数最少的文件 | | `coupling` | 经常一起变更的文件,揭示隐藏的架构依赖 | | `churn-risk` | 按近期变更频率排序的文件,并标记为 `cold` / `active` / `active-core` / `silo` / `legacy-hotspot` | | `working-patterns` | 按小时和星期几统计的提交热度图 | | `dev-network` | 基于共享文件所有权的开发者协作图 | | `profile` | 每个开发者的个人报告:范围、贡献类型、节奏、协作、顶级文件 | | `top-commits` | 按变更行数排序的最大提交(若提取时包含 `--include-commit-messages`,则包含提交信息) | | `pareto` | 文件、开发者(双视角:提交与变更)、目录的集中度(80% 阈值) | 输出格式:`table`(默认,人可读)、`csv`(每个 `--stat` 一个干净表格)、`json`(包含所有部分的统一对象)。 详见 [`docs/METRICS.md`](docs/METRICS.md) 了解每个指标的计算方式,包括时区处理(聚合桶使用 UTC、工作模式使用作者本地时间)以及重命名跟踪(基于 Git 检测到的重命名合并历史)。 ### 开发者个人资料 面向管理者的每位开发者报告,展示其范围、贡献类型、节奏、协作及顶级。 ``` # 所有开发者,按提交数排序 gitcortex stats --input data.jsonl --stat profile # 单个开发者 gitcortex stats --input data.jsonl --stat profile --email alice@company.com # JSON 导出 gitcortex stats --input data.jsonl --stat profile --format json ``` 每个个人资料包含: - **范围**:该开发者工作的主要目录(按唯一文件数,占比%) - **贡献**:增长(增加 >> 删除)、平衡,或重构(删除 >> 增加) - **节奏**:活跃日的提交次数 - **协作**:共享相同文件的最重要开发者 - **周末占比**:非工作时间工作的比例 - **顶级文件**:受变更影响最大的文件 ### 耦合分析 文件耦合检测在同一提交中共同变更的文件,揭示代码中不可见的架构依赖。基于 Adam Tornhill 的 ["Your Code as a Crime Scene"](https://pragprog.com/titles/atcrime/your-code-as-a-crime-scene/) 方法学。 ``` gitcortex stats --input data.jsonl --stat coupling --top 20 gitcortex stats --input data.jsonl --stat coupling --coupling-min-changes 10 --coupling-max-files 30 ``` ``` FILE A FILE B CO-CHANGES COUPLING CHANGES A CHANGES B ApplicationDbContext.cs ApplicationDbContextModelSnapshot.cs 54 61% 100 89 GuardianPortalControllerTests.cs GuardianPortalController.cs 40 91% 44 61 IWorkspaceRepository.cs WorkspaceRepository.cs 19 100% 19 29 ``` - **耦合百分比**:共同变更次数 / 两者中较小变更次数 —— 衡量两者关联的紧密程度 - **100% 耦合**:每当变更次数较少的文件时,另一文件也必然变更 ### 变更风险 按近期变更频率对文件进行排序并标记类别,以便区分健康的核心模块与遗留瓶颈,无需逐列比对。 ``` gitcortex stats --input data.jsonl --stat churn-risk --top 15 gitcortex stats --input data.jsonl --stat churn-risk --churn-half-life 60 # faster decay ``` Pi-hole 仓库的真实输出(每种标签一个示例): ``` PATH LABEL CHURN BF AGE TREND automated install/basic-install.sh active 115.3 15 4121d 0.00 .github/workflows/codeql-analysis.yml legacy-hotspot 66.2 2 1640d 0.26 advanced/bash-completion/pihole-ftl.bash silo 16.5 1 240d 1.00 test/_alpine_3_23.Dockerfile active-core 7.1 1 120d 1.00 advanced/Templates/gravity.db.schema cold 0.0 1 2616d 1.00 ``` | 标签 | 含义 | |-------|---------| | `cold` | 近期变更少 —— 可忽略 | | `active` | 共享所有权(巴士因子 ≥ 3)。健康。 | | `active-core` | 新代码(<180 天),单一作者。通常正常。 | | `silo` | 旧、集中、稳定/增长。知识瓶颈 —— 需规划转移。 | | `legacy-hotspot` | **紧急。** 旧、集中、下降。仍在被修改的废弃路径。 | 排序键为 `recent_churn`;标签回答“这些活动是否构成问题?”。复合字段 `risk_score`(`recent_churn / bus_factor`)仍用于 CI 网关向后兼容。 `--churn-half-life` 控制旧变更的衰减速度(默认 90 天,即每 90 天权重减半)。 ### 工作模式 按小时和星期几统计提交分布。揭示时区、过劳模式与部署习惯。 ``` gitcortex stats --input data.jsonl --stat working-patterns gitcortex stats --input data.jsonl --stat working-patterns --format csv > patterns.csv ``` ``` HOUR Mon Tue Wed Thu Fri Sat Sun 09:00 1 1 3 . . . . 10:00 7 4 2 2 1 6 1 11:00 10 13 3 1 2 14 7 ... 19:00 35 15 7 10 12 16 13 22:00 26 9 . 1 13 9 8 ``` ### 开发者网络 协作图谱,连接修改过相同文件的开发者。权重反映重叠比例。 ``` gitcortex stats --input data.jsonl --stat dev-network --top 20 gitcortex stats --input data.jsonl --stat dev-network --network-min-files 10 gitcortex stats --input data.jsonl --stat dev-network --format csv > network.csv ``` ``` DEV A DEV B SHARED FILES WEIGHT alice@company.com bob@company.com 142 34.5% carol@company.com alice@company.com 87 21.2% ``` ### 多仓库 跨多个仓库聚合统计。文件路径会自动加上文件名前缀以避免冲突。 ``` # 提取每个仓库 gitcortex extract --repo ./svc-auth --output auth.jsonl gitcortex extract --repo ./svc-payments --output payments.jsonl # 聚合统计 gitcortex stats --input auth.jsonl --input payments.jsonl gitcortex stats --input auth.jsonl --input payments.jsonl --stat coupling --top 20 ``` 路径显示为 `auth:src/main.go`,贡献者按邮箱跨仓库去重 —— 同一开发者在多个仓库的贡献只计一次。 ### 差异:比较时间段 比较两个时间段的统计,或筛选到单一时期。 ``` # 对比 Q1 与 Q2 gitcortex diff --input data.jsonl \ --from 2024-01-01 --to 2024-03-31 \ --vs-from 2024-04-01 --vs-to 2024-06-30 # 过滤到单月(运行该时段全部统计) gitcortex diff --input data.jsonl --from 2024-03-01 --to 2024-03-31 # JSON 导出 gitcortex diff --input data.jsonl \ --from 2024-01-01 --to 2024-06-30 \ --vs-from 2024-07-01 --vs-to 2024-12-31 \ --format json > comparison.json ``` ``` === Summary: 2024-01-01 to 2024-03-31 vs 2024-04-01 to 2024-06-30 === Commits 812 → 945 (+133) Additions 45420 → 62830 (+17410) Deletions 12300 → 18900 (+6600) Files touched 320 → 410 (+90) Merge commits 45 → 38 (-7) ``` ### HTML 报告 生成包含全部统计可视化图表的自包含 HTML 仪表板。纯 HTML+CSS,无外部依赖,可在任意浏览器打开。 ``` gitcortex report --input data.jsonl --output report.html gitcortex report --input data.jsonl --output report.html --top 30 # 每位开发者的个人报告(可与经理共享) gitcortex report --input data.jsonl --email alice@company.com --output alice.html ``` 包含:概览卡片、活动热力图(带表格切换)、顶级贡献者、文件热点、变更风险、巴士因子、文件耦合、工作模式热力图、顶级提交、开发者网络与开发者个人资料。典型体积:50-500KB,取决于贡献者数量。 ## CI:流水线质量门禁 运行自动化检查并在阈值超标时失败构建。 输出格式:`text`(默认)、`github-actions`(注解)、`gitlab`(Code Quality JSON)、`json`。 检测到违规时退出码为 1,清洁时退出码为 0。 ## 架构 ``` cmd/gitcortex/main.go CLI entry point (cobra) internal/ model/model.go JSONL output types git/ stream.go Single git log streaming parser catfile.go Long-running cat-file blob size resolver commands.go Utility functions (branch detection, SHA validation) parse.go Shared types (RawEntry, NumstatEntry) discard.go Malformed entry tracking extract/extract.go Extraction orchestration, state, JSONL writing stats/ reader.go Streaming JSONL aggregator (single-pass) stats.go Stat computations (9 stats) format.go Table/CSV/JSON output formatting ``` ### 提取流水线 两个长时间运行的 Git 进程处理整个提取过程,与仓库大小无关: ``` git log --raw --numstat -M --- single stream ---- parse ---- emit JSONL | git cat-file --batch-check -- long-running ---- resolve blob sizes ``` ### 统计流水线 单次遍历流式聚合。JSONL 文件仅读取一次,逐行处理,聚合到紧凑的映射中。原始记录永不存储 —— 仅保留预计算的聚合状态驻留内存。
标签:EVTX分析, Git, HTML报告, JSONL, 二进制分发, 仓库指标, 代码分析, 代码耦合, 凭证管理, 单机分析, 变更风险, 可扩展分析, 工作模式, 开发者协作网络, 开源项目分析, 性能基准, 总线因子, 提交数据提取, 数据提取, 文档结构分析, 日志审计, 本地分析, 热点文件, 统计报告, 统计计算