我需要为本地仓库使用Git LFS吗?

8

我创建了一个Git仓库,该仓库将完全存储在本地,我想知道对于二进制文件是否真的需要Git LFS?据我所见,.gitattributes已正确配置为:

*.psd binary

是的,这些文件会落在.git/objects/...中,但它们被压缩并且不占用太多空间。那么,总结一下,如果我从未推送/拉取到远程仓库,Git LFS 在本地仓库中有哪些好处?

谢谢!


据我所知,设置 binary 属性仅影响 git diff 的行为。我认为它不会影响文件的存储方式。 - Keith Thompson
有道理!谢谢! - Daniel Stephens
另请参阅我的问题:git LFS如何比git更高效地跟踪和存储二进制数据?,以及这个问题:git lfs有什么优势? - Gabriel Staples
3个回答

13
这取决于您的工作流程和您可以访问的设施。
Git将文件版本存储为blob。这些blob是差异压缩的,只存储差异部分。因此,文件大小仅略微增加。
如果版本化的文件是二进制文件或者单个更改会重构整个文件的文件,则情况就不同了。在这种情况下,Git会存储每个文件的副本,导致存储库快速增长。
Git在差异压缩大文件方面做得很好。我发现大文件的压缩效果非常好(运行git commit或git gc后,在.git/中版本化文件的大小)。
类型 变更 文件大小 作为git-lfs blob 作为git blob 经过git gc后
Vectorworks (.vwx) 添加几何图形 28.8 MB 28.8 MB 26.5 MB 1.8 MB
GeoPackage (.gpkg) 添加几何图形 16.9 MB 16.9 MB 3.7 MB 3.5 MB
Affinity Photo (.afphoto) 切换图层 85.8 MB 85.6 MB 85.6 MB 0.8 MB
FormZ (.fmz) 添加几何图形 66.3 MB 66.3 MB 66.3 MB 66.3 MB
Photoshop (.psd) 切换图层 25.8 MB 25.8 MB 15.8 MB 15.4 MB
Movie (mp4) 剪辑 13.1 MB 13.1 MB 13.2 MB 0 MB
删除文件 -13.1 MB 0 MB 0 MB 0 MB
如果你没有一个可以推送的远程仓库,最好不要使用Git-LFS,因为Git-LFS版本化的文件似乎没有额外的压缩(见上文)。
另外一个重要的教训是,Git的差异压缩方法对于真正的二进制文件(如.fmz)不起作用。这些文件是放在Git-LFS版本控制下的最佳候选文件。
对于其他看起来非文本的文件类型,但其结构类似文本(如.vwx或.afphoto),差异方法表现良好。在单用户场景中,整个仓库的大小而不是提交速度至关重要,我不会将这些文件放在Git-LFS版本控制下,因为Git blob的大小明显小于LFS blob,从而节省了本地和远程的空间。
Git-LFS的好处
Git-LFS通过将大型二进制文件的旧版本存储在仓库之外的位置(远程)并用指针文件替换它来解决了这个问题。如果需要旧版本,则客户端从远程拉取它。因此,如果设计师从远程拉取最新状态,他只会下载最新状态和指针文件。
因此,只有在您可以访问到启用了LFS的服务器时,才能使用Git-LFS。如果没有服务器来推送blob文件,那么LFS跟踪的blob文件将保留在本地仓库中,因此无法利用减少本地存储消耗的优势。
通常,远程服务器是一个启用了LFS的git提供者,这对于一些项目来说可能太昂贵了。然而,也有一些解决方案可以在本地托管Git-LFS远程服务器。
如何在本地仓库中集成Git-LFS
原生的Git-LFS只允许通过HTTPs传输数据。因此,您需要一个单独的Git-LFS服务器来存储大文件。然而,目前还没有官方的本地托管服务器实现。但是有一些非官方的方法,比如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 blobs。

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

# 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

1
很棒的回答!从你的回答中并不是非常清楚,但我想你是在说如果添加一个28.8 MB的文件,它作为一个git blob是26.5 MB,然后在运行git gc垃圾回收之后,它只剩下1.8 MB,对吗?与git lfs的始终保持26.5 MB的blob相比。仅仅从表格上看,人们可能会认为运行git gc会在已经存在的26.5 MB git blob之上再增加1.8 MB。请澄清一下。 - Gabriel Staples
1
是的,git gc 会压缩它,而 git lfs 则保持原样。Git LFS 的唯一优点是,它会将较旧的 blob 从本地仓库移动到远程仓库,而默认的 Git 会在本地和远程都保留所有内容。 - Alexander Gogl
明白了!谢谢回复。我认为这个优点实际上并不是一个优点。 - Gabriel Staples
1
在像我这样的情况下,这可以成为一个优势,你正在使用连接到网络存储的笔记本电脑工作。在这种情况下,你可以通过将某些大型文件类型的文件历史推送到网络驱动器上来节省宝贵的本地存储空间。这种工作流程建立在存储空间廉价而时间(重建丢失版本)昂贵的假设之上。 - Alexander Gogl

8

使用git-lfs还是不使用?

git-lfs将旧版本的文件内容存储在云端,同时保留它们在磁盘上的历史记录。这有两个主要好处。

  1. 它可以大大减少仓库的初始git clone的大小。
  2. 它可以大大减少本地仓库的大小。

显然,如果仓库从未共享,则第1点不适用。

如果这些二进制文件真的很大,并且您经常更改它们,它们可能会开始影响您可用的免费磁盘空间。如果是这样,git-lfs可以通过将二进制文件的旧副本卸载到云存储中来获得好处。

幸运的是,如果本地仓库变得太大,您总是可以使用BFG Repo Cleaner后期应用git-lfs

二进制文件还是非二进制文件?

据我所见,.gitattributes已正确配置为:*.psd binary

这是与git-lfs无关的另一个问题。

如果文件被标记为二进制文件,Git 将假定它不能有用地 diff 或合并其内容。每次更改文件时,Git 将存储完整的文件副本。这显然会占用更多的磁盘空间。
即使文件是“二进制”的(即不是纯文本),如果您不将其标记为二进制,Git 也可以仅存储更改。但是,如果文件已经压缩,这会有效地随机化文件内容并使 diff 变得不可能。许多图像格式都是经过压缩的。 Alexander Gogl 在他们的答案中进行了一些实验,看起来 Git 将存储整个 .psd 文件。

1
@DanielStephens 不会,如果一个文件没有改变,它将导致相同的 blob ID,内容不会重复。提交 ID 由一堆东西组成。请参见 https://git-scm.com/book/en/v2/Git-Internals-Git-Objects。 - Schwern
1
@DanielStephens,它不是将大文件的历史内容存储在磁盘上,而是将它们存储在云存储中,并按需获取。由于您是在本地进行提交,因此我认为它会缓存它们。您可能需要手动清除LFS缓存。 - Schwern
我不明白为什么这个答案被认为是正确的。它并没有真正回答实际问题“我需要Git LFS来管理本地仓库吗?”,而是让读者倾向于得出“是的,我需要Git LFS”的结论,这显然是错误的答案。对于严格本地的存储库,拥有一个本地的Git LFS服务器将导致性能下降(更多的磁盘空间)而不是只有一个本地的Git存储库。 - Jorge Galvão
@JorgeGalvão 我认为当我写回答时问题微妙地改变了。我会进行更新。 - Schwern
你已经确定了git lfs的两个明显的“好处”:它减少了git仓库初始克隆的大小,以及减小了本地仓库的大小。但是,我认为这两个方面都是“负面”的,因为它们带来了一个巨大的代价:git checkout的时间。在过去的3年里,我在一个庞大的单一仓库中工作,其中一个单独的git checkout经常需要3小时以上,而不是几秒钟。这就是上述两个“好处”的代价。所以,今天,我强烈建议不要使用git lfs更多细节请参见我的问题链接。 - Gabriel Staples
显示剩余4条评论

3

为了补充已由@Schwern提供的出色答案并回应楼主的评论。

这里是Atlassian关于GIT LFS的文档链接link,Atlassian是支持此扩展的两家主要公司之一(另一家是GitHub)。

这个想法是二进制文件会在“远程”仓库中进行“延迟”下载,即在检出过程中而不是克隆或获取过程中进行。

从技术上讲,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,这个说法仍然成立,"commit A"之后仍有可能访问文件系统状态。所以,如果您明确不需要版本 1,则至少在本地存储它是没有意义的。

另外需要说明的是:是的,您必须在本地启用 git lfs 支持,但还需要在远程仓库上启用 git lfs 支持(我曾在 Bitbucket 上这样做过,我相信其他竞争对手也支持)。


谢谢!这是一个很棒的补充!但是对我来说,Git LFS 只有在涉及到远程仓库的时候才是必要且有益的,是这样的吗?如果仓库从未离开本地机器,它就不那么有益了,是吗? - Daniel Stephens
1
嗯,是的,我想是这样,尽管我从未见过有人仅在本地使用git lfs... - Mark Bramnik
"...二进制文件是从“远程”仓库进行懒加载下载的,也就是在检出过程中而不是在克隆或获取过程中。你刚刚完美地解释了为什么在大型代码库上使用git lfs非常糟糕:git checkout过程经常需要花费我3个多小时,而不是几秒钟。" - Gabriel Staples

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接