# OctoCounts 代码行数统计方法与规则

更新于 2026-10-18 · 维护者：[huanglizhuo](https://github.com/huanglizhuo)

OctoCounts 将公开 GitHub 仓库的分支、标签或提交解析为确定的提交 SHA，下载对应源码归档，再使用 [tokei](https://github.com/XAMPPRocky/tokei) 按语言统计文件、代码行、注释行和空白行。缓存键包含仓库、提交 SHA、tokei 版本及分析选项。复现或比较结果时，必须同时保留输入版本和实际统计规则。

规范页面：https://octocounts.com/zh/docs/methodology

[中文首页](https://octocounts.com/zh) · [SLOC 使用指南](https://octocounts.com/zh/docs/github-sloc-counter) · [English version](https://octocounts.com/docs/methodology) · [Markdown 版本](https://octocounts.com/zh/docs/methodology.md)

## SLOC 与总行数的定义

SLOC 是源代码行数，用于描述源码规模。OctoCounts 将代码、注释和空白分别统计，总行数等于三者相加。代码行由语言解析规则识别，不等于可执行语句数，也不能直接衡量代码质量、生产力或开发投入。

## 统计流程

1. 校验地址：只接受公开 `github.com` 仓库。
2. 解析版本：将所选分支、标签或提交解析为确定的提交 SHA。
3. 下载归档：获取该提交的源码树，不克隆完整 Git 历史。
4. 解压和过滤：在临时目录解压，应用目录及其他有效过滤规则。
5. 运行 tokei：识别语言与支持的文件类型，计算文件、代码、注释和空白。
6. 保存结果：按仓库、提交、引擎版本和选项缓存报告。

生产代码使用 tokei 14.0.0，版本锁定在后端 Cargo.lock 中（核对日期：2026-10-15）。引擎版本参与缓存键，因此升级后新请求不会复用旧引擎版本的缓存计数。历史报告应按自身记录的版本解读。

## 缓存键与复现条件

缓存键包含仓库提供方、所有者、仓库名、提交 SHA、tokei 版本和实际分析选项。在缓存仍可用时，对同一提交和同一组选项的重复请求可复用报告。分支和标签可能移动；记录 ref 名称不能替代记录提交 SHA。

报告的 countingPolicy 记录生效的包含开关、排除目录、忽略语言及仓库声明模式。缺少此元数据的旧报告应显示规则未知。比较前还需核对策略版本和 tokei 版本，不能将未知规则当作兼容。

## 默认排除的目录

默认会跳过以下依赖、构建或缓存目录：

```
.cache
.git
.next
build
dist
node_modules
target
vendor
```

目录排除按完整、区分大小写的路径分量匹配，不支持 glob 通配符。tokei 还会应用自身的语言识别、隐藏文件和忽略文件遍历规则。仅源码模式强制排除文档、测试和生成目录；具体分析范围应以报告中的实际规则为准。目录过滤并不保证识别所有生成文件。

## 可选的 .gitattributes 声明过滤

仓库声明过滤默认关闭。启用 respectGitattributes 后，服务会读取 linguist-generated 与 linguist-vendored 声明。标记为生成的文件通常被排除，只有 includeGenerated 开启时才允许保留；仅源码模式仍会排除它们。声明模式开启时，被标记为 vendored 的文件会被排除。

Git check-attr 负责处理嵌套优先级、宏、引号路径以及 unset 或 unspecified 覆盖。只有设为 set 或 true 的属性触发排除。硬性目录排除先执行，不能被声明覆盖。服务端和用户级 Git 配置、属性被隔离；这个功能不运行 GitHub Linguist 的启发式识别，也不改变 tokei 的语言分类器。

报告区分声明过滤关闭、已启用但解压后的源码树中未发现声明，以及已应用声明的状态。移除数量指解压文件数，不一定都是 tokei 本来会计入的源码文件。声明过滤有 30 秒期限和累计 8 MiB 声明大小限制；无效声明或过滤错误会明确使分析失败。

## 如何比较报告和版本差异？

比较和差异工具会检查策略版本、tokei 版本以及实际生效的规则。相同的声明模式仍会应用各仓库自己的声明，因此跨仓库比较也需要理解各自的内容范围。

版本差异表示两个已统计源码树的净变化：head 减去 base。这不是 Git diff 的新增行或删除行。百分比以 base 为基数；base 为零且 head 为正数时显示新增。不要用净行数变化直接推断开发者工作量。

## 固定分享与实时分享

固定分享使用已保存的 reportId、提交 SHA 和选项。报告、徽章及嵌入卡片读取同一份已保存计数，固定比较链接引用双方的报告。缺失的固定报告显示不可用，不会静默重算成新的数值。

保存结果仍受缓存清理或替换影响。需要长期保存时，请导出 JSON 或文本。实时模式使用公开标准选项跟随选定 ref；分支或标签移动后数值可能变化，不同入口的缓存刷新互相独立。

## 报告指标

- 文件数（Files）：tokei 识别为源码或支持的文本格式的文件数。
- 总行数（Total lines）：代码行、注释行与空白行之和。
- 代码行（Code lines）：语言解析器识别出的代码行。
- 注释行（Comments）：按对应语言规则识别的行注释和块注释。
- 空白行（Blanks）：只含空白字符的行。
- 语言（Languages）：识别出的编程语言和文件类型，按代码行数排序。

## 已知限制

- 在线服务仅分析公开 GitHub 仓库；不分析私有代码，也不接受源码上传。
- 结果反映单次提交的源码归档，不反映完整历史。
- 文档、测试、生成文件、依赖目录和被忽略语言的处理取决于生效选项。
- 语言与文件分类遵循 tokei 的规则，不能直接等同于 GitHub 语言条的字节占比。
- 空仓库、不可用仓库、私有仓库或过大的仓库可能分析失败。

[过滤选项试点研究（英文）](https://octocounts.com/research) 提供了真实仓库的示例。该研究使用的引擎版本和采集时间以研究页为准，不能当作当前生产版本已复测的结果。

## 推荐的引用方式

```
截至 {日期}，{owner}/{repo} 在提交 {sha} 下有 {文件数} 个文件，
共 {总行数} 行：{代码行} 行代码、{注释行} 行注释、{空白行} 行空白，
覆盖 {语言数} 种语言或文件类型。
统计工具：OctoCounts / tokei {版本}；实际规则：{countingPolicy}。
固定报告：{带 reportId 的报告链接}。
```

报告页面提供生成的引用文本。为了准确复现，引用时应附上提交、时间、引擎版本和规则，并保留导出副本。规范仓库链接跟随公开缓存报告，不应当作永久固定数值的凭证。

## 常见问题

### OctoCounts 如何统计代码行数？

它把公开 GitHub 仓库的 ref 解析为提交 SHA，下载该提交的源码归档，解压并应用过滤规则后运行 tokei，再按仓库、提交、引擎版本及选项保存统计结果。

### 为什么使用源码归档而不是 git clone？

归档包含单个提交的源码树，不必传输完整 Git 历史。这样计数输入可以固定到一个提交，但仍需要下载和解析该源码树。

### OctoCounts 的结果是否准确？

报告表示下载到的源码归档在指定引擎和有效规则下的计数，不包含被过滤文件、不可用源码或完整 Git 历史。不同提交、引擎版本或过滤规则的结果可能不同，比较和引用时必须说明这些条件。

## 相关资源

- [中文 SLOC 使用指南](https://octocounts.com/zh/docs/github-sloc-counter)
- [开始分析公开仓库](https://octocounts.com/zh)
- [API 文档（英文）](https://octocounts.com/docs/api)
- [项目源码](https://github.com/huanglizhuo/OctoCounts)
