Git大项目实践:Monorepo管理、LFS使用、稀疏检出、浅克隆
说实话,很多团队一开始用Git都挺开心的。代码量不大,仓库清爽,分支切换丝滑。但项目一膨胀,问题就来了——克隆慢得像下载电影,.git目录比源码还大,随便一个git status都要等好几秒。
我经历过一个项目,前端、后端、移动端、文档全塞在一个仓库里。第一次克隆花了40分钟,同事直接崩溃。后来我们不得不拆分仓库,但拆分后又带来了版本对齐的噩梦。嗯,这就是我们今天要聊的话题——大项目怎么用Git管好。
Monorepo:一个大仓库还是多个小仓库?
Monorepo,说白了就是把多个项目放在同一个Git仓库里。Google、微软、Uber都在用。我刚开始觉得这反人类,后来真香了。
Monorepo的好处很明显:
- 代码共享方便,不用发npm包
- 原子提交,一个改动跨多个模块
- 统一构建和CI流程
- 重构时跨项目改代码很轻松
但坑也不少:
- 仓库体积爆炸
- 克隆时间感人
- 权限控制困难
- Git操作变慢
我建议中小团队用Monorepo,但要做好配套。比如用pnpm workspaces或turborepo来管理依赖,用changesets来管理版本。Git本身只是载体,真正的管理工具在Git之上。
核心原则:Monorepo不是把代码堆在一起就完事了。你需要工具链来支撑。没有工具链的Monorepo,就是给自己挖坑。
Git LFS:大文件别往Git里塞
Git设计出来是管文本的。二进制文件?它真的不擅长。你想想看,一个100MB的PSD文件,每次改一点点,Git都会存一份完整副本。仓库不爆炸才怪。
Git LFS(Large File Storage)就是干这个的。它把大文件替换成指针文件,真正的文件内容存到远程服务器上。
安装和使用:
# 安装LFS
git lfs install
# 指定哪些文件用LFS管理
git lfs track "*.psd"
git lfs track "*.zip"
git lfs track "*.mp4"
# 提交.trackattributes文件
git add .gitattributes
git commit -m "配置LFS跟踪规则"
# 正常使用,LFS自动处理
git add design.psd
git commit -m "添加设计稿"
git push
我在项目中遇到过最坑的事:有人把node_modules提交到了LFS。嗯,你没看错。LFS是按流量收费的,node_modules动不动几百MB,一次push就烧掉几块钱。后来我们加了CI检查,禁止LFS跟踪node_modules目录。
避坑指南:我曾经因为忘记配置.gitignore,把编译产物也推到了LFS。结果团队成员每次拉取都要下载几百MB的二进制文件。记住:LFS只适合管理不常变但体积大的文件,比如设计稿、音视频、数据集。频繁变动的文件不要用LFS。
稀疏检出:我只想要一部分代码
Monorepo里可能有几十个模块,但你只负责其中一个。每次克隆整个仓库?太浪费了。稀疏检出(Sparse Checkout)就是解决这个问题的。
操作步骤:
# 方式一:克隆时直接稀疏
git clone --filter=blob:none --sparse https://github.com/example/monorepo.git
cd monorepo
# 设置要检出的目录
git sparse-checkout set packages/frontend packages/shared
# 方式二:已有仓库启用稀疏
git sparse-checkout init --cone
git sparse-checkout set packages/frontend
# 添加更多目录
git sparse-checkout add packages/docs
# 查看当前稀疏配置
git sparse-checkout list
我个人习惯用--cone模式。它只检出顶层文件和指定目录,性能最好。如果你需要更细粒度的控制,可以用非cone模式,但说实话,大部分场景cone模式就够了。
小技巧:稀疏检出配合--filter=blob:none使用效果更佳。前者控制工作目录,后者控制Git对象下载。两者结合,克隆一个大型Monorepo可以从40分钟降到2分钟。
浅克隆:只要最近的历史
有时候你根本不需要完整的历史。比如CI环境,只需要最新代码来跑测试。或者你只是想看看项目长什么样。这时候浅克隆(Shallow Clone)就派上用场了。
常用方式:
# 只克隆最近1次提交
git clone --depth 1 https://github.com/example/big-project.git
# 克隆最近5次提交
git clone --depth 5 https://github.com/example/big-project.git
# 克隆某个分支的最近提交
git clone --depth 1 --branch main https://github.com/example/big-project.git
# 浅克隆后拉取更多历史
git fetch --depth 50
我记得有一次线上问题排查,需要看某个文件的修改历史。结果发现CI环境用的是--depth 1克隆的,根本没法git blame。后来我们改了策略:开发环境用完整克隆,CI用浅克隆,但保留最近50次提交。
注意:浅克隆有一些限制。你不能从浅克隆仓库再推送(push)到远程,除非你git fetch --unshallow拉取完整历史。另外,git merge在某些情况下也会失败。所以浅克隆适合只读场景,不适合开发环境。
组合使用:大项目的最佳实践
这些技术不是孤立的。在实际项目中,我通常会组合使用:
# 终极组合:浅克隆 + 稀疏检出 + 无blob
git clone --depth 1 --filter=blob:none --sparse \
https://github.com/example/monorepo.git
cd monorepo
git sparse-checkout set packages/frontend
这个命令做了什么?
--depth 1:只拉取最新提交,不要历史--filter=blob:none:不下载文件内容,只下载目录结构--sparse:启用稀疏检出模式sparse-checkout set:只检出frontend目录
效果?一个原本5GB的仓库,克隆下来只有200MB。时间从30分钟降到1分钟。我团队里有个新人第一次用这个命令,直接惊呼"原来Git可以这么快"。
知识体系总览
下面这张图总结了本章的核心内容,方便你对照理解:
总结一下
大项目用Git,说白了就是三个字:减负。减少克隆的数据量,减少工作目录的文件数,减少历史记录的深度。
- Monorepo:适合多项目协作,但需要工具链支撑
- Git LFS:大文件的救星,但别滥用
- 稀疏检出:只拿你需要的代码
- 浅克隆:只要最新,不要历史
我见过太多团队被Git大项目折磨得死去活来。其实解决方案就在眼前,只是很多人不知道这些功能的存在。希望这篇文章能帮你少走一些弯路。
最后一句:如果你现在正被大仓库折磨,试试git clone --depth 1 --filter=blob:none --sparse。相信我,你会回来感谢我的。
公众号:蓝海资料掘金营,微信deep3321