有效写法是配置 .gitattributes 文件而非 composer.json 的 archive,因后者仅用于手动 composer archive 且不参与 packagist/github 自动发布;.gitattributes 中写入 .git export-ignore 即可排除 .git 目录。

composer.json 的 archive 配置怎么写才有效?
archive 不是全局配置,只在你用 composer archive 手动打包时起作用,而绝大多数发布场景(比如 Packagist 自动抓取、GitHub Release)根本不会读它。所以别指望靠它防 .git —— 它压根不参与日常发布流程。
真正起作用的是 .gitattributes 文件,Composer 在生成 ZIP 包(例如用户运行 composer install --prefer-dist)时,会尊重 Git 的导出规则。你要做的只是告诉 Git:哪些文件不该进归档。
-
.gitattributes必须放在项目根目录,且必须提交到仓库里 - 写法很简单:
.git export-ignore(一行即可) - 这条规则会跳过整个
.git目录,也顺带排除.gitignore、.gitmodules等
为什么 exclude-from-classmap 和 autoload.exclude 不能防 .git?
这些配置只影响自动加载器的行为,和包分发完全无关。exclude-from-classmap 是让 Composer 在生成 classmap 时跳过某些路径;autoload.exclude(v2.5+)是让 PSR-4/PSR-0 加载器忽略某些文件。它们既不删文件,也不改 ZIP 内容,对 .git 目录毫无约束力。
常见误操作:把 .git 加进 autoload.exclude,结果发现发布的 ZIP 里还是有它 —— 因为 autoload 配置根本不参与归档逻辑。
Packagist / GitHub 自动发布时,谁在决定包内容?
Packagist 拉取的是 Git tag 对应的 commit 的**干净快照**,等价于 git archive --format=zip HEAD。它依赖 Git 自身的导出机制,也就是 .gitattributes 和 .gitignore 的组合行为。
-
.gitignore 只控制工作区文件是否被 Git 跟踪,不影响归档
-
.gitattributes 中的 export-ignore 才是归档时的“闸门”
- 如果没写
.gitattributes,Git 默认会把所有 tracked 文件都打进 ZIP,包括 .git 目录下的东西(只要它被意外 track 过)
.gitignore 只控制工作区文件是否被 Git 跟踪,不影响归档.gitattributes 中的 export-ignore 才是归档时的“闸门”.gitattributes,Git 默认会把所有 tracked 文件都打进 ZIP,包括 .git 目录下的东西(只要它被意外 track 过)所以最稳妥的做法就是:删掉所有可能 track 过 .git 相关文件的痕迹,然后加一行 .git export-ignore 到 .gitattributes。
验证是否生效的最快方式
别等发布后才发现问题。本地就能测:
- 确保已提交
.gitattributes
- 运行:
git archive --format=zip --output=test.zip HEAD
- 解压
test.zip,检查里面有没有 .git/ 目录
- 如果有,说明
.gitattributes 没生效(可能是路径不对、没提交、或用了 Windows 换行符导致解析失败)
.gitattributes
git archive --format=zip --output=test.zip HEAD
test.zip,检查里面有没有 .git/ 目录.gitattributes 没生效(可能是路径不对、没提交、或用了 Windows 换行符导致解析失败)Git 归档不报错也不提示,它默默按规则执行——所以漏掉 .gitattributes 或写错格式,就会原样打包进去,连 warning 都没有。










