目录标题

  • 例子
    • 不开LFS
    • 开LFS
    • 例子小结
  • 详解
    • GIT HOOK 及GIT attributes提供无感使用体验
    • lfs 源文件缓存及文件指针对应规则

例子

这里做些例子展示,方便理解。

不开LFS

git init: 提交大文件,文件166m
git add isbin.bin
git commit -m "初始化"
: --------------- 本地仓库大小 321  MB  (≈实际文件166+ git log变更166)---------------: 修改文件
echo a >> isbin.bin
git add isbin.bin
git commit -m "修改大文件"
: --------------- 大小 476 MB (约等 321MB + 166M)---------------: 二次修改文件
echo b>>isbin.bin
echo b>>text.txt
git add isbin.bin text.txt
git commit -m "修改大文件2次"
: --------------- 大小 631 MB (约等 478MB + 166M) ---------------  : 推送远端(使用本地裸仓库,git init --bare 创建,方便演示)
git push --progress "D:\lfs\noLFSbare" master: 从远端克隆(使用本地裸仓库,方便演示)
git clone D:\lfs\noLFSbare --progress
: --------------- clone 库的大小 631 MB ;源文件和庞大的git log变更历史 ---------------

开LFS

git init: 开启 lfs 功能及文件追踪
git lfs install
git lfs track "*.bin"
git add .gitattributes
git commit -m "LFS初始化": 上传大文件,文件166m
git add isbin.bin
git commit -m "初始化"
: --------------- 大小 333 MB (另外加上166m git lfs 缓存) ---------------: 修改文件
echo a >> isbin.bin
git add isbin.bin
git commit -m "修改大文件"
: --------------- 大小 499 MB (另外加上166m *2 git lfs 缓存)---------------: 二次修改文件
echo a >> isbin.bin
git add isbin.bin
git commit -m "修改大文件"
: --------------- 大小 666 MB  (另外加上166m *3 git lfs 缓存)---------------: 推送远端(使用本地裸仓库,git init --bare 创建,方便演示)
git push --progress "D:\lfs\LFSbare" master: 从远端克隆(使用本地裸仓库,方便演示)
git clone D:\lfs\LFSbare --progress
:--------------- clone下来的仓库 大小 333 MB (真实文件另外加上166m git lfs 缓存)
:真实文件是缓存拷贝出来,其实clone下载只有一半---------------: clone 下来的新仓库 回退版本
git reset --hard HEAD~1
: --------------- 大小 499 MB ---------------
: 回退版本时从lfs 下载上一版本的文件做本地缓存,并替换工作目录下的文件

例子小结

需要注意的是一个混淆点,GIT LFS不能缩减本地仓库的大小,只有在频繁变更二进制文件,才可以有效缩减的远端仓库大小,提高clone或者pull的速度!

详解

查看git log历史中的大文件文件,我们可以看到这些庞大的二进制文件,都转换成文件指针文本,大致格式如下。

version https://git-lfs.github.com/spec/v1
oid sha256:efe51849f1f4d4003a64ba0d430425e991d5f9c1c64691663ad58192b3bb8932
size 174684142

那问题来了,我们在例子中使用的提交命令是明明一样的。LFS是那是如何将文件做转换的呢?

GIT HOOK 及GIT attributes提供无感使用体验

在一个本地仓库执行git lfs install或者clone带lfs的仓库时,在.git\hooks文件夹中有一下四个文件
执行对应git操作时会自动或前或后执行对应的钩子函数,查看里面的内容也非常简单,判断git lfs是否存在并且执行配套的git lfs命令。

而另一个则是 GIT attributes文件,lfs 跟踪文件时,添加一个文件.attributes文件,简单来说,就是对bin文件,git 识别成文本,指定filter、merge及diff文件比对规则,其中filter用来执行检出和stage时源文件和文件指针转换的操作。

*.bin filter=lfs diff=lfs merge=lfs -text

git attributes介绍

git hook与 attributes都是git的原生特性。

lfs 源文件缓存及文件指针对应规则

从上面的一些说明,我们可以已经可以对 git lfs的性质做一下简单的总结了,他只是一个git的外挂式的插件,或者说一个enhancer,利用git原生特性,让git 不在管理真实的二进制文件,而是一个pointer性质的文件。

那lfs如何根据这些文件指针获取真正的源文件的呢?

同样,git lfs 默认会在当前仓库的.git目录创建lfs文件夹,这里面存储着git lfs的各个版本的源文件缓存,需要注意这些是缓存,而不是git的一部分,这也是能提高git性能的根本原因,这些缓存删除对git没有任何影响,上面的例子中我们可以看到,clone 带lfs的仓库,虽然只会下载最新版本的文件指针指向的文件版本,而历史文件只有当我们做另外的reset或者checkout之类的操作是,才会去下载。

指针获取对应文件规则:
文件指针有一个oid 对象id,对应的文件则是.git/lfs/objects/OID[0:2]/OID[2:4]/OID

例如

version https://git-lfs.github.com/spec/v1
oid sha256:efe51849f1f4d4003a64ba0d430425e991d5f9c1c64691663ad58192b3bb8932
size 174684142

则对应的文件缓存应当在**.git\lfs\objects\ef\e5**
文件名efe51849f1f4d4003a64ba0d430425e991d5f9c1c64691663ad58192b3bb8932
如果不存在则会像lfs服务器下载。

走服务器的http请求大概如下,主要还是根据sha256算出来的oid。

// POST https://lfs-server.com/objects/batch
// Accept: application/vnd.git-lfs+json
// Content-Type: application/vnd.git-lfs+json
// Authorization: Basic … (if needed)
{
“operation”: “download”,
“transfers”: [ “basic” ],
“ref”: { “name”: “refs/heads/main” },
“objects”: [
{
“oid”: “12345678”,
“size”: 123
}
],
“hash_algo”: “sha256”
}

GIT LFS 原理杂谈相关推荐

  1. git lfs原理和使用

    如果我们用git管理的项目中出现了一些大文件, 同时若其数量比较多, 而且更新又比较频繁, 那么当首次clone该项目时, 就会不可避免地将这些大文件的当前版本和历史所有版本的文件都下载下来, 虽然你 ...

  2. Git LFS笔记(文档、博客、issue摘录)

    Git LFS 文章目录 Git LFS 1. What is Git LFS? 1.1 Creating a new Git LFS repository 1.2 Cloning an existi ...

  3. Git 存储原理及相关实现

    Git 是目前最流行的版本控制系统,从本地开发到生产部署,我们每天都在使用 Git 进行我们的版本控制,除了日常使用的命令之外,如果想要对 Git 有更深一步的了解,那么研究下 Git 的底层存储原理 ...

  4. Git LFS 入门指南

    Git LFS 入门指南 出于好意:设计团队开始把他们大尺寸的图形文件添加到你的项目仓库当中,然而引起的结果是,你看着仓库不断增大直到数 GB 大小...... 在 GIT 中以二进制文件来运行确实是 ...

  5. git lfs安装及使用方法

    什么是git LFS LFS是Large File Storage的缩写,用了帮助git管理大的文件 原理:不同于git每次保存diff,对于git来说,如果是模型或者一些设计大文件,改变一点,对于仓 ...

  6. Git详解之九 Git内部原理

    以下内容转载自:http://www.open-open.com/lib/view/open1328070620202.html Git 内部原理 不管你是从前面的章节直接跳到了本章,还是读完了其余各 ...

  7. Git命令家底儿及Git数据通信原理详解

    声明:本文为CSDN原创投稿文章,未经许可,禁止任何形式的转载. 作者:周立伟(花名:华序,ITeye博客),关注分布式.高并发和Java中间件的研究. 责编:钱曙光,关注架构和算法领域,寻求报道或者 ...

  8. eclipse查看git地址_Git大文件管理:函数计算和OSS支持的Git LFS服务器

    此服务器支持Batch API和File Locking API.项目地址与文档: https://github.com/zhxxch/git-lfs-one/​github.com LFS 是个好东 ...

  9. Git内部原理之深入解析Git的引用和包文件

    一.Git 分支本质 如果对仓库中从一个提交(比如 1a410e)开始往前的历史感兴趣,那么可以运行 git log 1a410e 这样的命令来显示历史,不过需要记得 1a410e 是查看历史的起点提 ...

  10. git lfs出现This repository is over its data quota

    报错如下: batch response: This repository is over its data quota. Account responsible for LFS bandwidth ...

最新文章

  1. java sql编辑器_Java工程师完整学习路线
  2. thinkphp 引入时间_thinkphp 文章发布日期时间修改问题
  3. audio to text
  4. 关于c++静态成员函数
  5. 获取摄像机,摄像机切换Learn Unreal Engine (with C++)
  6. PHP独特学习模式_php基础知识
  7. sharepoint搜索pdf文档
  8. 只有程序员能看懂的十个笑话 2014-08-05 16:07 54人阅读 评论(0) 收藏...
  9. flask从表单中的提交中获取数据(不使用第三方库)
  10. appliedzkp的zkevm(7)定制化Proof System
  11. ajax的Provisional headers are shown
  12. 祛痘收缩毛孔的简单方法 - 生活至上,美容至尚!
  13. 人脸检测实战高级:使用 OpenCV、Python 和 dlib 完成眨眼检测
  14. 写贺卡给毕业师姐怎么写计算机系的,写给师姐的毕业祝福语赠言 送给师姐的毕业祝福语大全...
  15. LTE连接态读取系统消息SIB24疑问
  16. 汉字转拼音(不带音调)
  17. 古代人用什么来洗衣服?
  18. MiniFilter文件系统学习
  19. ccd视觉定位教程_CCD视觉定位的激光焊接装置的制作方法
  20. C语言从入门到精通——进阶6 C语言文件操作

热门文章

  1. IPV6IPV4网址
  2. VSCode插件---Code Runner
  3. excel合并两列内容_10.表格中如何将两列文本内容合并
  4. CPA、CPS、CPC、CPM推广是什么意思?
  5. 电脑小白须知!N卡和A卡有什么区别?A卡和N卡的区别,一个动图秒懂!
  6. 模式识别--绪论 什么是模式识别?模式识别的主要方法及具体应用
  7. Git分支管理Git branch相关参数命令,git branch -v git branch --merged git branch --no-merged git commit -a -m
  8. C语言常见问题(4):Collapsible if statements should be merged
  9. 谷歌VR展示360度全景图
  10. 格鲁夫给经理人的第一节课读书笔记