加速 Git:必备性能优化技巧

通过减少克隆成本、合理使用 Git LFS、清理过时引用、忽略生成文件以及应用稀疏检出,来加速 Git。

加速 Git:必备性能优化技巧

Git 运行缓慢通常有具体原因:历史记录过多、未跟踪文件过多、大型二进制对象、昂贵的文件系统扫描或网络延迟。在责怪 Git 本身之前,请检查哪个操作缓慢以及它试图读取或下载什么。

Git 性能优化在将修复措施与症状匹配时效果最佳。缓慢的 CI 克隆与大型工作树中缓慢的 git status 需要不同的解决方案。

理解 Git 性能缓慢的原因

从常见原因开始:

  • 包含大量文件和引用的长历史记录。
  • 直接提交到 Git 的大型二进制文件。
  • 工作树中未忽略的构建输出、依赖文件夹或日志。
  • 大量过时的远程跟踪分支和标签。
  • 与远程仓库之间的慢速网络链接。
  • 缺少较新维护和稀疏检出改进的旧 Git 版本。

有目的地运行缓慢的命令。如果 git clone 缓慢,请检查历史记录大小和网络传输。如果 git status 缓慢,请检查工作树大小、忽略的文件和文件系统行为。如果 git fetch 缓慢,请检查远程引用、标签和更改的对象。

减少克隆和获取成本

对于 CI、部署作业和只读检查,您通常不需要完整的历史记录。

使用浅克隆:

git clone --depth <number> <repository_url>

例如,仅克隆最后 10 次提交:

git clone --depth 10 https://github.com/example/repo.git

对于仅构建当前提交的 CI 作业,--depth 1 通常就足够了。对于开发人员工作,完整克隆通常更不容易出错,因为诸如深层 git log、检出旧标签以及某些变基等命令需要更多历史记录。

如果您已有浅克隆并需要更多历史记录,请加深它:

git fetch --deepen=50 origin

或者将其转换为完整克隆:

git fetch --unshallow origin

对于部分数据需求,较新的 Git 版本还支持部分克隆过滤器,例如 --filter=blob:none,但仅在您的 Git 主机和工作流良好支持它们时使用:

git clone --filter=blob:none https://github.com/example/large-repo.git

将大型文件排除在常规 Git 历史记录之外

大型二进制文件是使 Git 变慢的最快方式之一。图像、视频、归档文件、设计文件和模型文件通常无法很好地压缩或差异比较。

对于真正属于仓库的大型资产,请使用 Git LFS:

git lfs install
git lfs track "*.psd"
git lfs track "assets/*.mp4"
git add .gitattributes
git commit -m "使用 Git LFS 跟踪大型资产"

Git LFS 会影响跟踪规则生效后的未来提交。如果有人已经将大型文件提交到常规 Git 历史记录中,仅从当前树中删除它们是不够的。您可能需要使用诸如 git lfs migrate importgit filter-repo 等工具进行协调的历史重写。

对于生成的构建产物,更好的答案通常不是 LFS。不要提交它们。而是将它们添加到 .gitignore 中:

node_modules/
dist/
coverage/
*.log

清理本地引用和对象

过时的远程跟踪分支会增加混乱,并可能减慢列出或检查引用的命令。在获取时修剪它们:

git fetch --prune

删除已合并且不再需要的本地分支:

git branch --merged
git branch -d old-feature-branch

让 Git 运行维护:

git maintenance run

在较旧的工作流中,git gc 仍然有用:

git gc

除非您知道需要它们的原因,否则避免使用激进的清理命令。例如,过期 reflog 可能会使从错误重置中恢复变得更加困难。

降低 git status 的成本

git status 必须检查工作树。如果您的项目目录包含数千个生成或依赖文件,状态可能会变得嘈杂且缓慢。

使用 .gitignore 来忽略 Git 不应考虑的文件。如果文件已被跟踪,.gitignore 不会阻止 Git 跟踪它;您必须首先从索引中删除它:

git rm --cached path/to/generated-file

对于非常大的仓库,如果您只需要树的一部分,稀疏检出可能会有所帮助:

git sparse-checkout init --cone
git sparse-checkout set services/api docs

这仅将选定的路径保留在您的工作树中。它在单体仓库中很有用,但您的团队应记录预期的稀疏路径,以便开发人员不会错过他们需要的文件。

分离获取与集成

git pull 会获取更改,然后根据配置通过合并或变基进行集成。当仓库很大或分支已分叉时,通常先获取会更清晰:

git fetch origin
git log --oneline HEAD..origin/main
git merge origin/main

这本身不会减少网络传输量。它让您在更改工作分支之前拥有控制权。

实用要点

对短期作业使用浅克隆,对大型资产使用 Git LFS,对生成文件使用 .gitignore,对过时引用进行修剪,对仅需子集的大型树使用稀疏检出。保持 Git 更新,但不要将诸如 git fsck 之类的完整性工具用作性能修复,除非您怀疑仓库损坏。

当 Git 感觉缓慢时,记下确切的命令以及时间花费在哪里:网络传输、对象处理或工作树扫描。这一个细节通常指向正确的优化方向。