开源自荐:CodeYear:把本机 Git 历史变成年度代码手账(本地优先 · 零上传 · 已上 PyPI)

年底想写年度总结,发现 GitHub Wrapped 只算公开仓库还要 OAuth;而大部分提交都在公司内网 GitLab 和本地项目里。市面上的 git 统计脚本,要么把 package-lock.json 算成"最常改文件",要么把硬盘里的 backup 副本重复计数,数字看着吓人但全是水分。

所以我写了一个:CodeYear,本地优先的年度代码报告生成器,MIT 开源,刚发布 v0.2.14 并上了 PyPI。

先看效果

一次扫描,五连输出:中英双语 HTML 报告、2400×3200 海报、5330px 完整长图、640×1254 透明底 GitHub 主页卡片、JSON 原始数据。

报告是纸面档案风格:书脊式目录、超大年份封面、按真实数据生成的年度称号(比如"Works late at night")、7×24 提交时钟、编码会话、季度语言栈、仓库墓园、同比去年面板,中英双语页内一键切换,浏览器直接打印成 PDF。

GitHub 主页卡片是 640×1254 透明底 SVG,浅色/深色随主题自适应,内置 4 套主题(paper / mono / forest / ocean)和 8 条大白话观察。仓库里附带了 GitHub Action 模板,卡片每天自动更新。

快速上手

已发布 PyPI,三行命令:

bash 复制代码
pip install codeyear
codeyear scan ~/code --open

不想安装的话,uvx 一行免安装运行:

bash 复制代码
uvx codeyear scan ~/code --open

Windows 用户:Releases 提供免装 Python 的单文件 exe,双击即用,软件内自带检查更新和一键升级。

常用参数:

bash 复制代码
# 同比去年 + 最近 365 天(滚动年度)+ 排除练习仓库
codeyear scan ~/code --compare --rolling --exclude "temp,*-demo" --open

# 公开 GitHub 账号模式(可选联网,仅读公开数据)
codeyear github <用户名> --year 2026

为什么它的数字更"诚实"

这是和其他 git 统计工具最大的差异点,也是这个项目花精力最多的地方。

1. 只统计本人提交。 自动读取 git config user.name / email 识别身份,旧邮箱用 --alias 合并,仓库里的 .mailmap 自动生效。默认剔除 merge commit(--no-merges),其他人提交的贡献不会被算进你的"行数"。

2. 副本血统去重。 硬盘里同一项目的 work/、backup/、fork 副本,按根提交(root commit)和 remote 血统自动合并------只保留提交最全的一份,commit hash 全局去重。备份文件夹再多也不会虚报。

3. 剔除锁文件与构建产物。 package-lock.json、Cargo.lock、dist/、模型二进制全部排除,"最常改文件"榜保证是真实手写代码。

4. 时区口径可指定。 时间取 author date 并按指定时区换算(--tz Asia/Shanghai 或 UTC+8),"深夜提交占比"这类作息统计才不会整体偏移 8 小时。API 查询窗口在年初年末各多留一天,跨时区边界提交不丢。

几个实现要点

给同样想写这类工具的同学,几个踩过的坑:

  • git log 解析 :用 %x1e(记录分隔符)和 %x1f(字段分隔符)作为定界符输出 --numstat,比逐行正则解析可靠得多,文件名里的中文和空格都不会炸;
  • 副本合并:对仓库列表跑并查集(union-find),root commit 和 remote 归一化后作为并查集的 key,同一血统自动聚成一组,取提交数最多的副本为代表;
  • 对比去年零额外开销 :--compare 时一次 git log 扫 [year-1, year] 两年数据,内存里按提交时间拆成两份分别聚合,扫描耗时不变;
  • 公开模式断点续传 :codeyear github 拉 commit 详情时每条实时写入本地 SHA 缓存(~/.cache/codeyear),中断重跑不浪费已拉取的请求;
  • 英文报告不误伤用户数据 :翻译只作用于界面文案节点,仓库名、README 简介和 commit message 用 data-raw 标记保护,用户的"1.5万"不会被转成"15k";
  • Windows 自更新 :exe 运行中不能覆盖自身,但可以改名------os.replace 把运行中的 exe 原地改名为 .old 再把新版本顶上原位,无需批处理脚本,不触发杀软误报。

链接

如果觉得有用,欢迎点个 Star;对统计口径有疑问(时区、副本识别这类边角情况)欢迎提 issue,这也是我现在最想收集的反馈。

相关推荐
用户83514140494943 分钟前
我把 claude-mem 跑了一遍:值得学的地方和踩到的坑
github·claude
QuZhengRong1 小时前
【Luck‑Report】 AI 智能报表助手 + RAG 知识库 + 报表引擎 V2.0.9 更新
github·agent·报表·开源项目·数据可视化
一条Go4 小时前
能力套餐:菜单、权限、开通范围怎么拆成三层而不打架
后端·github·saas
WeWorker4 小时前
浏览器 Agent 的两种宿命:像素派和工具派
github
GitHub实测笔记4 小时前
hyperfine 本机实测:2.96MB 上 bat 开高亮中位数 2.39s、cat 3.0ms(约 870 倍);v2 默认不走 shell
github
徐小夕6 小时前
万字长文!DeepSeek Super-agent × 企业知识库架构深度拆解与落地实践
前端·vue.js·github
奶油话梅糖6 小时前
打开项目 0.9 秒、内存只有 IDEA 的 1/12:OpenIDEA 用 Rust 把 IntelliJ IDEA 重造了一遍
java·rust·github·intellij-idea
miofly8 小时前
GitHub 日榜趋势速报 | 2026-11-06
开源·github
穆梓兰煊21 小时前
Vue生态下AI生成UI:千万级向量场景落地实践
github