方法论与洞察

生成物不入 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/缓存

所以”提交了大文件但还没推”是最后一个低成本纠正点——发现得及时就当场处理,别想着”先推上去以后再说”。

操作规则

  1. 默认不入库的类型*.pdf *.exe *.pck *.zip 构建包、渲染导出、数据集、模型权重。在 .gitignore 里落规则,别靠人记。
  2. 放哪:仓库外的产物目录(LastStand 用 E:\last-stand-build\,与构建 zip 同处),或作为 GitHub Release 附件分发——后者还顺带解决了”用户在哪下载”。
  3. 用户要求提交大二进制时:先说明”进历史后体积降不回来”再执行;执行后、push 前主动提醒还有补救窗口。
  4. 例外要过一问:“这个文件能从仓库里的源文件重建吗?“能 → 不入库;不能(如无源的第三方素材、必须随仓库分发的小体积资产)→ 可入库,但仍要看体积。

边界

小体积(几百 KB 以内)且无源可重建的二进制(图标、字体、少量截图)该入就入——本条针对的是可重建 + 大体积的生成物。文档配图属于”无源可重建”,正常入库;但由文档生成的 PDF 属于生成物,不入。

关联文档

类型/协作工具链主题/git