.gitattributes与git lfs
.gitattributes
.gitattributes 是 Git 项目的一个配置文件,用来定义文件在 Git 中的行为。它可以控制 Git 如何处理特定类型的文件,比如合并策略、换行符、文本编码、diff 显示方式、LFS(Git Large File Storage)等内容。
🌟 用通俗点的话来说:
.gitattributes 就像是告诉 Git:“嘿!对于这些文件,应该用这种方式来处理。”
📘 常见用法示例
1. 控制换行符(跨平台兼容)
* text=auto
自动处理文本文件的换行符(Windows CRLF / Linux LF),避免因为换行符不同而导致的“假变更”。
2. 为特定类型文件设置合并策略
*.lock merge=ours
3. 指定 diff 工具
*.md diff=markdown
告诉 Git:.md 文件用 markdown 的方式来高亮 diff。
4. 使用 Git LFS 管理大文件
*.psd filter=lfs diff=lfs merge=lfs -text
比如设计图 .psd 用 Git LFS 管理,避免 Git 本身仓库变大。
5. 防止某些文件类型被 Git 自动转换为文本
*.png binary
告诉 Git:.png 是二进制文件,不要尝试 diff 或修改。
🧩 .gitattributes 文件的格式:
<文件匹配模式> <属性1> <属性2> ...
Git LFS
上面说到的git lfs:
🧠 什么是 Git LFS?
Git LFS(Large File Storage) 是 Git 官方推荐的用于管理大文件的扩展工具。
“Git 适合管理代码,不适合管理大文件;但我们可以用 Git 来记录大文件的‘引用’,真正的文件存在其他地方。”
场景 | 举例 | 原因 |
---|---|---|
设计文件 | .psd、.ai、.xd、.fig | 图形文件大、不适合 diff |
二进制资源 | .zip、.exe、.apk、.dmg | Git 无法增量存储、会迅速膨胀 |
媒体文件 | .mp4、.wav、.mov、.mp3 | 文件大、频繁修改导致仓库变重 |
模型参数 | .pt、.ckpt、.h5、.onnx | 机器学习模型超大,代码和模型分离更好 |
文档附件 | .docx、.pdf | Git diff 无法解析,频繁更新导致提交记录暴涨 |
🔍 和普通 Git 的区别
项目 | 普通 Git | Git LFS |
---|---|---|
文件存储 | 把文件本体存进 Git 仓库 | 只存一个“指针”,文件放 LFS 服务 |
仓库大小 | 大文件改一次就膨胀一次 | 文件替换不膨胀代码仓库 |
diff 和合并 | 只能对文本做 diff/merge | LFS 文件通常无法 diff |
clone/pull 速度 | 慢,大文件会被拉下 | 只拉指针文件,LFS 后台异步下载 |
适合的文件 | 代码、脚本、配置 | 多媒体、模型、设计稿等二进制文件 |
🔧 使用 Git LFS 的基本流程
git lfs install
告诉 Git 哪些文件要用 LFS 管理
git lfs track "*.psd"
git lfs track "*.mp4"
提交 .gitattributes 文件(记录 track 配置)
git add .gitattributes
git commit -m "Track large files with Git LFS"
像正常 Git 一样 add/commit/push 即可
git add design.psd
git commit -m "Add design file"
git push
Git 会把 design.psd 的实际内容上传到 LFS 服务,而 Git 仓库里只存一个“指针”文件(如 20 字节的 placeholder)。
**Git 是版本控制,Git LFS 是“帮 Git 管不动的大文件”。**它们配合使用可以大大减轻仓库体积,提高协作效率。
✅ 普通 Git vs Git LFS 的本质区别(通俗理解)
🧱 普通 Git:
每次提交时,
整个文件的内容都会被记录下来
对于小的 .py、.js 文件没什么问题,但如果是一个 100MB 的视频或者模型文件,每次修改一下都会重新存储整个文件,Git 仓库很快就爆炸了。
🚀 Git LFS:
Git 只记录一个 “
指针
真正的文件内容被存储在专用的 LFS 存储中,避免 Git 仓库体积膨胀。
假设你有一个 200MB 的模型文件 model.ckpt:
操作 | 普通 Git | Git LFS |
---|---|---|
第一次提交 | Git 仓库 +200MB | Git 仓库 +几KB(指针) |
改了 1% 内容再提交 | 又 +200MB(共 400MB) | 只更新 LFS 存储,Git 仓库无变化 |
Clone 仓库 | 拉下 400MB | 拉下几个 KB 的指针,再异步下载大文件 |
所以,用 LFS 就是为了:
• 保持 Git 仓库轻量
• 提高 clone/pull/push 的速度
• 更适合多媒体和大文件协作开发
全量保存?
🤯 Git 是不是每次都全量保存文件?
表面上看是的,Git 每次提交的时候都会记录整个文件的快照(snapshot)。
❗Git 并不是传统意义上的“diff-only”(只存改动),但也
不是完全的全量备份
使用了混合存储数据和节省空间
🧠 Git 的真正存储逻辑(核心机制)
内容寻址存储(Content-Addressable Storage)
换句话说:
• Git 会把文件内容根据内容计算一个哈希值(SHA-1 / SHA-256)。
• 如果两个版本的某个文件内容一样,它们指向的是同一个对象,不会重复存储!
• 只有变动的文件内容才会被重新存一份。
看起来是“每次提交都保存了完整快照”,其实是“只为变动的文件生成新对象,其他都复用”。
✅ 改一个字,Git 还是要重新存这个文件?
是的 —— 如果这个文件是文本文件(非巨大),Git 默认以“文件为单位”来判断是否需要更新。
所以哪怕你只改了一个字,Git 就会计算新 hash,然后重新存一个新的“Blob 对象”记录整个文件的内容(哪怕只改了一点点)。
所以 Git 没有引入块级增量备份技术,只用了 “内容哈希 + 树形结构 + 指针复用” 来优化空间使用。