0 评论

0 收藏

分享

[git相关技术] git大文件储存机制是什么-为什么有大文件会出错并且处理大文件非常麻烦-优雅草卓伊凡

git大文件储存机制是什么-为什么有大文件会出错并且处理大文件非常麻烦-优雅草卓伊凡
推送push 提示报错 Enumerating objects: 57113, done.
Counting objects: 100% (57113/57113), done.
Delta compression using up to 4 threads
Compressing objects: 100% (19261/19261), done.
Writing objects: 100% (57113/57113), 351.98 MiB | 1.15 MiB/s, done.
Total 57113 (delta 33913), reused 56036 (delta 33703), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (33913/33913), done.
remote: Powered by GITEE.COM [1.1.5]
remote: Set trace flag 1845f086
remote: Find the desired index: ea82a120fbf1e854ec32fe3db709d1dca033eb3d, size: 142.084MB, exceeds quota 100MB
remote: Please remove the file from history and try again
To https://gitee.com/youyacao/siyu-api.git
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to ‘https://gitee.com/youyacao/siyu-api.git
这样的报错就是大文件问题
为什么 Git 大文件处理如此麻烦?1. Git 的存储机制设计
Git 的本质是内容寻址文件系统:
# Git 存储的不是文件差异,而是文件快照每次提交 = 整个项目的快照(不是差异对比)
工作流程:
  • 当你提交文件时,Git 将文件内容作为 blob 对象存储
  • 每个 blob 通过 SHA-1 哈希值唯一标识
  • 即使你删除了文件,该 blob 仍然存在于 .git/objects 中
2. Git 的”永久记忆”特性# 示例:大文件的永久存在# 第1次提交:添加 150MB 文件git add large_file.zipgit commit -m "Add large file"# 第2次提交:删除该文件  git rm large_file.zipgit commit -m "Remove large file"# 问题:large_file.zip 仍然在历史中存在!3. 仓库膨胀问题
数据不会自动清理:
  • 所有历史版本的文件都保存在 .git/objects
  • 即使分支被删除,相关的对象仍然存在
  • 只有通过 gc(垃圾回收)才会清理不可达对象
为什么需要 BFG 这样的工具?原生 Git 命令的问题:git filter-branch 的缺陷:# 原生方法 - 极其缓慢且复杂git filter-branch --tree-filter 'rm -f large_file.zip' -- --all# 问题:# 1. 为每个提交创建新的提交对象# 2. 处理整个历史记录,非常耗时# 3. 容易出错,语法复杂# 4. 内存占用高BFG 的优势:
BFG 的工作原理:
// BFG 的核心优化:1. 直接操作 Git 对象数据库2. 只更新包含目标文件的提交3. 使用更高效的算法处理大文件4. 自动处理引用更新
性能对比:
处理 10,000 个提交的仓库:- git filter-branch: 2-5 小时- BFG: 2-5 分钟技术深度解析Git 对象模型:.git/objects/├── 12/3456789...    # blob 对象(文件内容)├── ab/cdef012...    # tree 对象(目录结构)└── cd/ef12345...    # commit 对象(提交信息)大文件的影响:
1. 克隆速度:
# 包含大文件的仓库克隆git clone https://gitee.com/your/repo.git# 必须下载所有历史版本的大文件,即使当前版本没有
2. 磁盘空间:
# 仓库实际大小远大于工作目录du -sh .git     # 可能几个 GBdu -sh .        # 可能只有几 MB
3. 操作性能:
git status    # 需要检查所有文件哈希git push      # 需要上传所有对象为什么不能简单”删除”?Git 的不可变数据结构:# 简化的 Git 提交链commit_C = {    'parent': commit_B,    'tree': tree_C,    'message': 'Delete large file'}commit_B = {    'parent': commit_A,     'tree': tree_B,  # 包含大文件    'message': 'Modify something'}commit_A = {    'parent': None,    'tree': tree_A,  # 包含大文件    'message': 'Add large file'}
关键问题:要删除 commit_A 中的大文件,必须重写 commit_B 和 commit_C,因为它们的父提交会改变。
解决方案的演进传统方法的问题:# 方法1:浅层克隆(不解决根本问题)git clone --depth 1 https://repo.git# 方法2:新建仓库(丢失所有历史)rm -rf .git && git init现代解决方案:
1. Git LFS(Large File Storage):
# 将大文件存储在外部,Git 只保存指针git lfs installgit lfs track "*.psd" "*.zip"git add .gitattributes
2. BFG Repo-Cleaner:
# 专门为清理大文件优化java -jar bfg.jar --strip-blobs-bigger-than 100M .
3. git-filter-repo(Git 2.24+):
# Git 官方推荐的新工具git filter-repo --strip-blobs-bigger-than 100M总结:为什么这么复杂?
  • 架构决定:Git 的快照式存储本质决定了大文件会永久存在
  • 完整性要求:重写历史会影响所有相关提交的哈希值
  • 性能考虑:需要高效处理可能包含数百万对象的仓库
  • 安全需求:确保历史重写不会损坏仓库完整性
这就是为什么我们需要 BFG 这样的专业工具——它们在保持 Git 强大功能的同时,解决了特定的性能和历史清理问题。对于包含大文件的仓库,这些工具是必不可少的。

优雅草论坛2022年8月11日大改,优雅草论坛变回只服务于客户的提问交流论坛,详情查看优雅草8月11日大改,原因详情查优雅草外卖乐关闭

回复

举报 使用道具

全部回复
暂无回帖,快来参与回复吧
yac2025
优雅草的临时工
主题 368
回复 0
粉丝 0