Git 和 SVN 怎么选?8.7GB 仓库、LFS、浅克隆踩坑记录
先说结论,别急着背“分布式一定比集中式先进”。我 2019 年接一个 Unity 外包,仓库 3.2GB,美术每天丢 500MB 到 1.2GB 的 PSD 和 FBX 进来,团队 7 个人。当时用 SVN 1.10,svn update 经常 11 分钟,冲突不多,但每次美术锁文件都要在群里喊“别动 Scene”。后来换 Git,前 3 个月爽,第 4 个月 .git 涨到 6.4GB,CI 从 4 分 20 秒变成 19 分钟。那一刻我才明白:版本控制选型不是选命令,是选“团队愿意为哪种协作协议付代价”。
先看 4 个工具的硬差异,别只看分布式
| 维度 | Git | SVN | Mercurial | Perforce Helix Core |
|---|---|---|---|---|
| 模型 | 分布式,本地全历史 | 集中式,目录当分支 | 分布式,命令更统一 | 集中式,按需同步 |
| 大二进制 | 原生差,靠 LFS | 原生一般,能锁 | 有 largefiles 但生态小 | 强,代理和锁成熟 |
| 目录权限 | 弱,基本靠仓库/分支 | 强,authz 按路径 | 弱 | 强 |
| 分支成本 | 低,本地分支快 | 分支等于目录拷贝,合并有债 | 低 | stream 可 |
| CI 缓存 | 要处理 .git 和 LFS | 工作副本大 | 同 Git | 按需拿文件,代理省带宽 |
| 学习曲线 | 中高,rebase 吓人 | 低,美术也能懂 | 中 | 中,管理重 |
如果只盯“有没有离线提交”,Git 赢。但 30 人以上、单个 1GB 文件、需要文件锁,Perforce 或 SVN 的锁加按需同步更省事。Git LFS 不是把大文件塞进 Git,它只是把文件内容放远端,仓库里留 130 字节左右的 pointer。所以 git clone 看起来快了,git lfs pull 还是要把 11GB 拉回来。我们迁完后 .git 从 6.4GB 降到 220MB,但 LFS 对象 11.3GB,CI 每次冷缓存拉 3.1GB。免费套餐?存储和流量账单会教你做人。
我踩过的 3 个坑,和对应命令
坑 1:以为删文件就瘦仓库。git rm big.psd 只删最新提交,历史里还在。查大文件:git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | awk '/^blob/ {print $3, $4}' | sort -n -r | head -20。看仓库体积:git count-objects -vH。真正清理要用 git filter-repo --strip-blobs-bigger-than 10M,但会改历史,必须通知所有人重新 clone。别在周五下午干这事。
坑 2:LFS 迁移完没配 .gitattributes。结果新提交的大文件又进普通 Git。正确做法:git lfs migrate import --include='*.psd,*.zip,*.fbx,*.wav' --everything,然后确保 .gitattributes 里有 *.psd filter=lfs diff=lfs merge=lfs -text。少一个 -text,Windows 换行符可能把二进制搞坏。
坑 3:CI 全量 clone。GitLab CI 里写 GIT_DEPTH: 1 和 GIT_STRATEGY: fetch 还不够。Git 2.19+ 支持 partial clone:git clone --filter=blob:none --no-checkout --depth=1 <repo>。然后 git sparse-checkout init --cone,git sparse-checkout set Assets/Scripts Assets/Shaders Packages。我们 Jenkins 从 19 分钟降到 6 分 10 秒,但第一次配置花了 2 小时,因为旧版 Git 不支持 --filter。服务器 Git 至少 2.30+,能到 2.37+ 更稳。
日常提速:我会在每台机器上开的 6 个配置
git config --global core.preloadindex true
git config --global core.fsmonitor true
git config --global feature.manyFiles true
git config --global index.version 4
git config --global lfs.concurrenttransfers 8
git maintenance start
这些不是玄学。core.fsmonitor 在 Windows 上对 10 万文件仓库提升明显,feature.manyFiles 会开 index.version=4 和 core.untrackedCache。但别在 2015 年的老 Mac 上硬开,先跑 git status 对比。还有 git gc 别天天跑,git maintenance start 会按计划做 incremental repack。我们 8.7GB 仓库手动 git gc --aggressive 跑了 47 分钟,结果只省了 600MB,不划算。
选型决策:我会这样分
- 人数小于 10,文本大于 80%,仓库小于 500MB:Git + GitHub/GitLab 免费层,trunk-based,别搞 Git Flow。
- 人数 10 到 30,二进制 20% 到 50%,仓库 500MB 到 5GB:Git + LFS,自建 GitLab 或买 LFS 流量包,CI 必须用 partial clone + sparse-checkout。
- 单个文件超过 500MB 或二进制超过 20GB,美术/策划占 40% 以上:先评估 Perforce/Plastic,别硬上 Git LFS。LFS 的 lock 能用:
git lfs lock Assets/Scenes/Main.unity,但跨平台体验不如 Perforce。 - 权限必须细到目录:SVN 的
authz仍然简单粗暴。Git 做不到“只能改 Docs 不能改 Src”,只能靠 CODEOWNERS 和 CI 检查,防君子不防小人。 - 需要离线提交、频繁分支、PR 审查:Git 优势最大。但分支寿命超过 3 天、每周合并超过 2 次冲突,先改流程,不是换工具。
最后一句不太讨喜的话
我现在的观点是:Git 不是版本控制的终点,它只是把“合并成本”从服务器转移到了每个开发者的脑子里。SVN 也不是老古董,它在“大二进制加目录权限加低学习成本”里依然能打。真正该先定的是三件事:提交粒度能不能压到 1 天以内、二进制文件有没有锁、CI 能不能只拿需要的 5% 文件。这三件事没定,换 Git、SVN、Perforce 都只是把痛苦换个形状。我们那次迁移最后省了时间,但省得最多的是“让美术别提交 2GB PSD”这条规矩,不是某条 Git 命令。