使用 .gitattributes 修复 GitHub 仓库语言识别问题
最近在使用 Trellis 辅助开发项目时,我发现了一个挺有意思的问题:明明项目的主要业务代码不是 Python,但 GitHub 仓库列表里却显示这个仓库的主要语言是 Python。
一开始我还以为是 GitHub 识别错了,后来才发现,问题其实出在 GitHub 的语言统计规则上。
一、问题现象
在 GitHub 仓库列表里,仓库名称下面会显示当前仓库的主要语言,比如:
但是这些项目的核心业务代码可能是 Android、Kotlin、Java、前端代码,Python 只是 Trellis 生成的工具代码、脚本代码或者辅助代码。
这就导致一个问题:
Python 代码体积比业务代码还多,GitHub 就把整个仓库识别成了 Python 项目。
二、为什么 GitHub 会显示成 Python?
GitHub 并不是根据项目名称、README 或者框架来判断语言的,而是使用一个叫 Linguist 的工具来统计仓库中的代码语言。
它大致会根据仓库里被 Git 跟踪的文件内容、文件后缀、文件大小来计算语言占比。
简单理解就是:
所以,当 Trellis 生成了大量 Python 文件,而这些文件又被提交到了 Git 仓库里,GitHub 就会认为:
这个仓库里 Python 代码最多,所以主语言是 Python。
这并不是 GitHub 出错,而是它不知道哪些代码是真正的业务代码,哪些只是工具代码或生成代码。
三、.gitattributes 是什么?
.gitattributes 是 Git 仓库里的一个配置文件,通常放在项目根目录。
它的作用是给不同文件设置处理规则。
可以这样理解:
比如 .gitignore 关注的是:
这个文件要不要进 Git 仓库?
而 .gitattributes 关注的是:
这个文件进了 Git 仓库以后,应该怎么被识别、比较、统计、处理?
四、.gitattributes 能解决什么问题?
.gitattributes 的用途很多,常见的有:
在这次的问题里,我们主要使用的是 GitHub Linguist 相关规则。
比如:
trellis/** linguist-generated
.trellis/** linguist-generated
意思是:
trellis和.trellis目录下的文件属于生成代码,不要参与 GitHub 仓库语言统计。
五、常用的 Linguist 规则
GitHub Linguist 支持通过 .gitattributes 修改语言统计行为。
常见规则如下:
例如:
generated/** linguist-generated
vendor/** linguist-vendored
docs/** linguist-documentation
*.kt linguist-language=Kotlin
它们分别表示:
六、如何修复 Trellis 导致的 Python 语言占比问题?
如果项目中 Trellis 生成的 Python 代码比较多,可以在仓库根目录创建或修改 .gitattributes 文件。
推荐写法是按目录排除:
# Trellis generated files
trellis/** linguist-generated
.trellis/** linguist-generated
# Generated files
generated/** linguist-generated
# Tooling scripts, if they are not business code
scripts/trellis/** linguist-generated
这种方式比较稳妥。
因为它只排除 Trellis 相关目录,不会影响其他真正的 Python 业务代码。
七、不建议直接排除所有 Python 文件
有些人可能会这样写:
*.py linguist-generated
这确实可以让 GitHub 不再统计 Python 文件。
但是这个写法有风险。
如果以后项目里真的有 Python 业务代码,比如后端接口、数据处理服务、自动化业务逻辑,那么这些 Python 文件也会被排除掉。
所以更推荐:
除非你非常确定:
这个仓库里的 Python 文件全部都是工具代码或生成代码,不属于业务代码。
否则不要一刀切排除所有 .py 文件。
八、Android 项目可以怎么写?
如果是 Android 项目,业务代码主要是 Kotlin 或 Java,可以这样写:
# Trellis generated files
trellis/** linguist-generated
.trellis/** linguist-generated
# Generated files
generated/** linguist-generated
# Keep Android business code language detection clear
*.kt linguist-language=Kotlin
*.java linguist-language=Java
这样做的目的不是强行“骗 GitHub”,而是告诉 GitHub:
Trellis 相关 Python 文件不是这个项目的主体业务代码,真正的业务代码应该按 Kotlin / Java 统计。
九、修改后怎么提交?
修改 .gitattributes 后,正常提交即可:
git add .gitattributes
git commit -m "Fix GitHub language detection"
git push
推送到 GitHub 后,语言统计不会一定立刻刷新,可能需要等一会儿。
如果规则写得没问题,GitHub 仓库语言显示就会逐渐恢复到更符合实际项目的状态。
十、这件事的本质
这次问题的本质不是 GitHub 识别能力差,而是 GitHub 不知道项目里的哪些代码是“核心业务代码”。
从 GitHub 的角度看,它只知道:
所以它自然会显示 Python。
而 .gitattributes 的作用就是补充上下文:
哪些代码是生成的,哪些代码是第三方的,哪些代码才是真正应该参与语言统计的。
总结
当使用 Trellis、代码生成器、脚手架、SDK 或其他自动化工具时,仓库里可能会出现大量非业务代码。
这些代码如果被 GitHub Linguist 统计进去,就可能导致仓库语言显示不准确。
解决方式是在仓库根目录添加 .gitattributes,把 Trellis 或生成代码标记为 linguist-generated。
核心配置如下:
trellis/** linguist-generated
.trellis/** linguist-generated
generated/** linguist-generated
简单来说:
.gitignore决定哪些文件不进仓库,.gitattributes决定进了仓库的文件应该怎么被 GitHub 对待。
对于这次问题,.gitattributes 就是最合适的解决方案。
使用 .gitattributes 修复 GitHub 仓库语言识别问题
https://lautung.com/archives/AOhZDYnn
评论