生成物不入 git
入档:2026-07-23 触发:LastStand 教程的 11.4MB PDF 备份被提交进仓库,随后按”不要增加仓库不必要的体积”撤回 验证状态:✅ 当场验证——reset + 移出 + gc 后
.git从 140M 回到 129M,历史零残留 性质:Git 资产管理纪律,配套 个人项目免PR直推主分支_v1 的提交侧规则
一句话律
能由源文件重建的生成物(PDF / exe / pck / zip / 渲染导出)一律不入 git。 进了历史就永久占体积——删掉文件也降不回来;放仓库外的产物目录,或作为 Release 附件分发。
踩坑现场
给教程产出 PDF 备份(11.4MB,20 页含嵌入图)后,我提示过”二进制大文件建议不入库”,跳蛛先生回”一并提交”,于是连同两份 md 一起 commit 了。下一句他就纠正:“不要增加仓库不必要的体积。”
撤回处理(关键前提:那个 commit 还没 push):
git reset --soft HEAD~1 # 撤 commit,改动回暂存区
git restore --staged docs/xxx.pdf # 只把 PDF 取消暂存
mv docs/xxx.pdf ../last-stand-build/ # 移到仓库外的产物目录
# .gitignore 补一条 *.pdf 防复发,重新 commit 其余文件
git reflog expire --expire=now --all && git gc --prune=now # 回收悬空 blob
结果:.git 从 140M 回到 129M,git log --all -- '*.pdf' 为空,历史零残留。
为什么这条值钱
git 存的是全量历史,不是当前状态。 一个二进制文件一旦进过某次 commit,它的 blob 就永久留在对象库里——后续 rm 掉文件、甚至删掉整个目录,仓库体积都降不回去,因为历史还要能 checkout 回那个版本。
同一个坑 LastStand 踩过两次:v0.7 那次”仓库瘦身清掉 57MB 废弃资产”,清的其实只是工作区,那些素材源料仍躺在 git 历史里。真正要清得改写历史(filter-repo / BFG),代价和风险都高一个量级。
而生成物本来就没有版本化价值:PDF 能由 md 重新导出,exe/pck 能重新构建,渲染成片能重新渲。版本化源文件就够了。
补救窗口(这条最实用)
| 时机 | 代价 |
|---|---|
| 已 commit、未 push | ⭐ 低:reset --soft + 移出 + gc --prune=now,本地就抹干净 |
| 已 push | 高:要改写远端历史(force push),协作者需重新同步,公开仓库还可能已被 fork/缓存 |
所以”提交了大文件但还没推”是最后一个低成本纠正点——发现得及时就当场处理,别想着”先推上去以后再说”。
操作规则
- 默认不入库的类型:
*.pdf*.exe*.pck*.zip构建包、渲染导出、数据集、模型权重。在.gitignore里落规则,别靠人记。 - 放哪:仓库外的产物目录(LastStand 用
E:\last-stand-build\,与构建 zip 同处),或作为 GitHub Release 附件分发——后者还顺带解决了”用户在哪下载”。 - 用户要求提交大二进制时:先说明”进历史后体积降不回来”再执行;执行后、push 前主动提醒还有补救窗口。
- 例外要过一问:“这个文件能从仓库里的源文件重建吗?“能 → 不入库;不能(如无源的第三方素材、必须随仓库分发的小体积资产)→ 可入库,但仍要看体积。
边界
小体积(几百 KB 以内)且无源可重建的二进制(图标、字体、少量截图)该入就入——本条针对的是可重建 + 大体积的生成物。文档配图属于”无源可重建”,正常入库;但由文档生成的 PDF 属于生成物,不入。
关联文档
- 个人项目免PR直推主分支_v1 —— 同族 git 纪律:那条管”提交流程别过度仪式化”,本条管”提交内容别塞生成物”
- ⭐ 构建产物的脏改动不是事故_复发是归因错了的信号_v1 —— 同族下一环:本条管「可重建的生成物别进版本库」,那篇管「生成物已经正确 gitignore 了,但编辑器仍把它摆进提交位」——kb-content 每次 build 都被脚本就地重写,稳定显示几百个未提交改动,两次被误判为事故;解法不在数据层(反复 checkout 徒劳)而在展示层(
git.ignoredRepositories) - 伪开源三查律_v1 —— 同为仓库治理视角
- 交付前实测证伪律_v1 —— 同源姿态:动作执行前先想清后果,别把代价留给以后
- 04_方法论与洞察索引