【问题标题】:Do I need Git LFS for local repos?本地存储库是否需要 Git LFS?
【发布时间】:2020-12-31 00:04:22
【问题描述】:

我创建了一个专门存储在本地的 Git 存储库,我问自己,我是否真的需要 Git LFS 来存储二进制文件?据我所见,.gitattributes 已正确配置为:

*.psd binary

是的,文件位于.git/objects/...,但它们被压缩并且不占用太多空间。综上所述,如果我从不从远程存储库推/拉到远程存储库,那么本地存储库中的 Git LFS 有什么好处?

谢谢!

【问题讨论】:

  • 据我所知,设置binary属性只会影响git diff的行为。我认为它不会影响文件的存储方式。
  • 有道理!谢谢!

标签: git git-lfs


【解决方案1】:

虽然 Git 提交是存储库内容的完整“快照”,但它实际上并没有再次存储文件。 Git 将文件的内容存储为由内容校验和标识的“blob 对象”;只有内容、文件名和权限存储在树对象中。如果您对文件提交更改,Git 会再次将整个文件(压缩)存储为新的 blob;任何未更改的文件都将重用现有的 blob。如果您有两个内容相同的文件,它们将共享同一个 blob。

如果没有 git-lfs,每次您提交对二进制文件的更改时,整个文件(压缩)都必须再次存储在一个新的 blob 中。由于 Git 存储库是项目的完整历史,因此一段时间后它可能会占用大量磁盘空间。如果空间很紧,那可能对您很重要。

幸运的是,您不必现在就做出此决定。如果存储库太大,您可以随时retroactively apply git-lfs later using the BFG Repo Cleaner

【讨论】:

  • 谢谢!你知道为什么吗?如果文件没有改变,它应该会导致相同的提交文件 sha,不是吗?
  • @DanielStephens 不,如果文件不更改,它将导致相同的 blob ID,并且内容不会重复。 The commit ID is made up of a bunch of things。见git-scm.com/book/en/v2/Git-Internals-Git-Objects
  • 谢谢!你能详细说明你的第一句话吗?只是让我了解差异。我会接受这个作为答案
  • @DanielStephens 怎么样?
  • @DanielStephens 不是将大文件的历史内容存储在磁盘上,而是将它们存储在云存储中并按需获取它们。由于您在本地进行提交,我认为它会缓存它们。您可能必须手动清除 lfs 缓存。
【解决方案2】:

这取决于您的工作流程和您可以使用的设施。

Git 将文件的版本存储为 blob。这些 blob 被 diff 压缩,因此只存储差异。因此,文件大小只会略微增加。

如果版本控制文件是二进制文件或单个更改重组整个文件的文件,情况就不同了。在这种情况下,Git 会存储每个文件的副本,从而使存储库快速增长。

Git 和 Git-LFS blob 大小的比较

Git 在 diff 压缩甚至大文件方面做得很好。我发现大文件的压缩效果非常好(大小完全变化):

type change file as git blob after git gc as git-lfs blob
Vectorworks (.vwx) added geometry 28,8 MB +26,5 MB +1,8 MB +26,5 MB
GeoPackage (.gpkg) added geometry 16,9 MB +3,7 MB +3,5 MB +16,9 MB
Affinity Photo (.afphoto) toggled layers 85,8 MB +85,6 MB +0,8 MB +85,6 MB
FormZ (.fmz) added geometry 66,3 MB +66,3 MB +66,3 MB +66,3 MB
Photoshop (.psd) toggled layers 25,8 MB +15,8 MB +15,4 MB +25,8 MB
Movie (mp4) trimmed 13,1 MB +13,2 MB +0 MB +13,1 MB
delete a file -13,1 MB +0 MB +0 MB +0 MB

如果你没有要推送到的遥控器,最好不要使用 Git-LFS,因为 Git-LFS 版本化文件似乎根本没有添加额外的压缩(见上文) .

这里学到的一个重要教训是,Git 的差异压缩方法不适用于 .fmz 等真正的二进制文件。这些将是 Git-LFS 版本控制的最佳候选者。

对于其他看似非文本但其结构类似于文本(.vwx 或 .afphoto)的文件类型,diff 方法表现良好。在单个用户场景中,总体存储库大小而不是提交速度很重要,我不会将这些放在 Git-LFS 版本控制下,因为 Git blob 大小明显小于 LFS blob,从而节省了本地和远程空间.

Git-LFS 的好处

Git-LFS 通过将旧版本的大型二进制文件存储在存储库之外(远程)的位置并用指针文件替换它来解决这个问题。如果需要旧版本,则客户端从远程拉取它。因此,如果设计者从远程拉取最新状态,他只会下载最新状态和指针文件。

因此,只有当您有权访问位于启用 LFS 的服务器上的远程时,才能促进 Git-LFS。如果没有服务器将 blob 推送到,则 LFS 跟踪的 blob 将保留在本地 repo 中,因此没有利用减少本地存储消耗的优势。

通常,远程是启用 LFS 的 git 提供程序,这对于某些项目来说可能过于昂贵。但是,也有一些解决方案可以在本地托管 Git-LFS 远程。

如何在本地仓库中集成 Git-LFS

从本质上讲,Git-LFS 只允许通过 HTTPs 传输数据。因此,您需要一个单独的 Git-LFS 服务器来存储大文件。但是,本地托管没有“官方服务器”implementation。但是有一些unofficial 方法,比如Git-LFS Folderstore 可以做到这一点。

Git-LFS Folderstore 提供了一种在本地管理 Git-LFS 远程的方法。它适用于本地机器和网络驱动器。如果您使用的是 Mac OS X,则可以通过将 lfs-folderstore 可执行文件 lfs-folderstore 复制到 /usr/local/bin 来进行设置,然后:

# Creating a remote repository on a volume (attached drive or NAS)
cd path/to/remote
mkdir origin

# create a bare git repository in origin
cd origin
git init origin --bare

# Add remote to local repository
cd path/to/local/repository
git remote add origin <path/to/remote/origin>

# Enable Git-LFS in local repository
git lfs install

# Track filetype psd
git lfs track "*.psd"

# Configure lfs of the local repository
git config --add lfs.customtransfer.lfs-folder.path lfs-folderstore
git config --add lfs.standalonetransferagent lfs-folder
git config --add lfs.customtransfer.lfs-folder.args "Volumes/path/to/remote/origin"

# Commit changes
git commit -am "commit message"

# Push media to remote
`git push origin master`

如果您的远程路径包含空格,请使用"'

如何清理本地仓库

您可以通过调用 Git 垃圾收集器 git gc 来压缩 git 存储库的大小。它不会触及 Git-LFS 的 blob。

Git-LFS 只会从本地存储库 .git/lfs/objects/ 中删除 blob,前提是它们已被推送到远程并且包含 blob 的提交比最近(3 天)旧。如果您想手动操作,请使用以下命令:

# remove lfs duplicates
# https://github.com/git-lfs/git-lfs/blob/main/docs/man/git-lfs-dedup.1.ronn
git lfs dedup

# clean old local lfs files (>3 days of commit)
# https://github.com/git-lfs/git-lfs/blob/main/docs/man/git-lfs-prune.1.ronn
git lfs prune

【讨论】:

    【解决方案3】:

    添加到@Schwern 已经提供的出色答案并解决 OP 的评论。

    这是来自 atlassian 的 GIT LFS 文档的 link - 支持此扩展的公司。

    这个想法是二进制文件是从“远程”存储库懒惰地下载的,即在结帐过程中而不是在克隆或获取期间。

    技术上 git lfs 存储“懒惰”评估的指向二进制文件的指针。

    这很有意义,因为 git 有一个“承诺”,能够在每次提交后为您提供对代码库状态的访问,因此可能出现以下情况:

    1. 提交 A:添加大二进制文件 a.bin(假设 a.bin 在版本 1 中)
    2. 推送更改
    3. 提交 B:对二进制文件 a.bin 进行了更改(a.bin 现在是版本 2)
    4. 推送更改
    5. 现在检查提交 A 的 SHA1 - git 必须在版本 1 中为您提供 a.bin。

    即使您决定删除 a.bin 并提交它也是如此,在“提交 A”之后应该仍然有可能访问文件系统状态。 因此,如果您明确不需要,至少在本地存储版本 1 是没有意义的。

    还有一点要注意,直接解决问题并澄清:是的,您必须在本地启用 git lfs 支持,但此外,您还必须在远程存储库上启用 git lfs 支持(我曾经使用 bit bucket 做到过,我'确信它的竞争对手也支持这一点)。

    【讨论】:

    • 谢谢!这是一个很好的补充!但在我看来,只有在涉及远程存储库的情况下,Git LFS 才必不可少且有益,对吗?如果 repo 永远不会离开机器,那么它就没有那么有益了,对吗?
    • 嗯,是的,我想是的,虽然我从未见过有人只在本地使用 git lfs...
    猜你喜欢
    • 1970-01-01
    • 2021-03-10
    • 2017-05-16
    • 2020-04-28
    • 1970-01-01
    • 1970-01-01
    • 2016-11-13
    • 2023-03-20
    • 1970-01-01
    相关资源
    最近更新 更多