课程
Git 是广泛使用的版本控制工具,可帮助管理软件开发项目、数据科学工作流,甚至文档代码库。然而,传统 Git 在处理大文件时存在局限。大文件会在每次提交时被复制,导致代码库膨胀,并且在拉取更改时需要复制多个大文件副本,从而使工作流变慢。因此,使用 Git 管理大文件在以下方面可能变得低效:
- 代码库体积大:将大文件直接存储在 Git 代码库中会增加其总体体积,使克隆和获取操作变慢,尤其是在处理需要上传/下载文件的远程代码库时。
- 存储和版本管理低效:每当大文件被修改,Git 会在历史中存储一个新版本,导致代码库迅速膨胀。
- 性能问题:当代码库很大时,Git 操作(如克隆、拉取、推送)会显著变慢并占用更多存储空间。
在本指南中,我们将深入了解 Git Large File Storage(Git LFS),这是一款帮助处理代码库中大文件的 Git 扩展。它让我们能够更高效地存储大文件的更改,避免额外的重复和存储开销。只要您预计代码库中会有大型二进制文件,就应该使用它。接下来我将更详细地介绍它是什么、如何工作、何时使用以及如何有效配置。
如果您是 Git 新手,欢迎查看我们的指南 如何学习 Git 和 Git 入门课程。
什么是 Git LFS?
Git Large File Storage(Git LFS)是一个用于改进大文件处理的 Git 扩展。
它通过为 Git 增加按需从远程代码库获取数据的能力,并加入一些巧妙的文件管理功能,从而改变了 Git 在获取和克隆时的工作方式。
在其他方面,用户体验与普通 Git 一样无缝且一致。
Git LFS 与标准 Git 跟踪有何不同
在传统 Git 中,我们将代码库的完整历史存储在 .git 目录中。这包括随时间变化的实际文本文件。此外,当我们执行 git fetch 或 git clone 时会下载整个代码库,以便随时能访问所有文件。而使用 Git LFS 时,情况会有所不同。
首先,Git LFS 会将大文件替换为指向远程存储的轻量级指针,减少必须在本地存储的实际文件。其次,只有在检出到某个分支时才会下载大文件,这意味着我们只会在准备处理这些文件时才下载它们。
最后,它会管理您的本地代码库存储,清理文件的旧版本,保持干净的工作环境。
Git LFS 的工作原理
Git LFS 采用基于指针的存储机制。如前所述,当您指定某个文件由 LFS 跟踪时,Git LFS 会在代码库中用指针文件替换该文件,并在本地缓存中放置一份副本。
当您推送提交时,本地缓存会更新到远程存储(例如 GitHub、GitLab、Bitbucket 的 LFS 服务器)。如果有更改并进行检出,这些更改会更新您的本地缓存,为您提供最新的工作副本。
如果您想了解最受欢迎的远程代码库之一 GitHub,欢迎查看这门GitHub 概念入门课程。
使用 Git LFS 有许多好处。它使代码库体积保持小而可控,也提升了团队处理大文件时的性能。此外,通过避免不必要的大文件重复,它能让您的本地代码库大小更易管理。
设置 Git LFS
在使用 Git LFS 之前,需要完成一些设置步骤。这个过程相对简单,主要是安装扩展。如果您已有代码库,需进行迁移;如果是新建代码库,则只需初始化 Git LFS 即可。
安装 Git LFS
要使用 Git LFS,您必须在系统上安装它。最简单的方法是前往 git-lfs 官网下载安装包。完成后,您需要在命令行中运行一次 git lfs install,以完成 Git LFS 的初始化与安装。
使用 Git LFS
安装完成后,您需要确保在每个代码库中配置 Git LFS。不同的远程 Git 托管平台(例如 GitHub 与 Bitbucket)步骤会略有差异。最好遵循您所用平台的推荐步骤。总体而言,如果是初始化新代码库,您可以在该代码库中运行 git lfs install 来初始化钩子,然后添加要跟踪的文件。如果是现有代码库,您可以使用 git lfs migrate,随后按照 .git 目录的清理流程操作:
git reflog expire --expire-unreachable=now --all
git gc --prune=now
在项目中使用 Git LFS
下面我们来了解在项目中使用 Git LFS 的一些方法。我们将涵盖在启用 Git LFS 的代码库中,对大文件进行跟踪、提交、克隆和拉取的步骤。
跟踪大文件(git lfs track)
要开始跟踪特定文件类型,可以使用 git lfs track <file type> 命令。例如,如果我想跟踪 CSV 文件,会运行:git lfs track "*.csv"。这也会将信息添加到 .gitattributes 文件中,确保针对该类文件使用 Git LFS。我们现在必须先推送 .gitattributes 文件,以确保正确跟踪 LFS 文件。
git add .gitattributes
git commit -m "Adding LFS .gitattributes"
git push origin main
添加并提交大文件
添加跟踪后,您可以像往常一样添加并提交:
git add largefile.csv
git commit -m "Adding large file with Git LFS"
git push origin main
在幕后,Git LFS 会将文件单独存储,并在代码库中用指针替代。整体体验应当相当顺畅。
克隆包含 Git LFS 的代码库(git lfs clone)
如果您使用较新的 Git 版本(>= 2.3.0),那么 git clone 命令应能同时适用于 LFS 与非 LFS 文件。若使用较旧的 Git 版本,则需要使用特定的 git lfs clone 命令。它与常规克隆不同,会依据大文件的指针信息,仅克隆每个大文件的工作副本。有关 Git 中克隆的更多信息,请查看以下教程:Git 克隆分支。
拉取大文件(git lfs pull)
如果您希望从代码库中获取并检出大型 LFS 文件,可以使用 git lfs pull。这与简单的 git pull 不同,后者只会拉取 Git 文件。
以下是一个示例工作流:
git checkout main # 切换到主分支
git pull # 从远程为该分支拉取最新 Git 文件
git lfs pull # 从远程为该分支拉取最新 Git LFS 文件
使用 Git LFS 的最佳实践
尽管 Git LFS 是一个出色的解决方案,但它也有自身的问题,且并非万能。请务必遵循以下最佳实践,以充分发挥 Git LFS 的作用:
- 仅将 Git LFS 用于大型二进制文件,不要用于代码或小型文本文件。
- 定期使用
git lfs prune修剪不必要的文件。 - 避免跟踪整个目录,这可能导致性能问题和膨胀。
- 确保所有协作者均已安装 Git LFS,以免出现文件缺失。
遵循这些通用指南,Git LFS 将会成为您的得力工具!
常见问题及其解决方法
由于 Git LFS 是 Git 的扩展,它也会带来一系列问题。尤其是它依赖于各类远程代码库,而这些平台也会有自身的问题。以下是您在使用 Git LFS 时可能遇到的一些常见问题及其解决方法。
Git LFS 身份验证问题
您可能通过多种方式遇到 Git LFS 的身份验证问题。为确保您本地的凭据配置正确,请检查以下事项:
- 使用正确的 SSH 配置:
git config lfs.url ssh://<git-url> - 检查您是否对父分支有读/写权限,因为 Git LFS 通常会跟踪到父级
- 尝试从远程代码库进行一次全新的 fetch/clone
如果问题仍然存在且您不是管理员,请与项目所有者联系,寻求权限方面的帮助。
大文件存储限制与配额
各平台可能对 Git LFS 存储设置配额。例如,GitHub 为免费和专业版用户提供 2GB 限额,企业云用户的单文件上限为 5GB。请确保您上传的文件未超过所用服务的限制,以避免错误。
将现有代码库迁移为使用 Git LFS
如果代码库已包含大文件,可使用以下命令进行迁移:
git lfs migrate import --include="*.filetype"
这会追溯性地将大文件替换为 LFS 指针。
结语
Git LFS 是高效管理大文件、保持代码库高性能和轻量化的关键工具。通过利用 Git LFS,开发者可以妥善管理代码库中的大体量文件。只要遵循最佳实践以尽量减少膨胀,LFS 就能为您的文件跟踪提供极大帮助。如果您想进一步学习 Git,请参考以下资源:
Git LFS 常见问题
克隆包含 Git LFS 文件的代码库会发生什么?
在较新版本的 Git 上运行 git clone 会自动获取代码库和 LFS 指针。如果您使用的是较旧版本的 Git,则需要运行 git lfs pull 以下载实际的大文件。或者,使用 git lfs clone 也会自动完成这一过程。
如何检查哪些文件由 Git LFS 跟踪?
运行 git lfs track 可查看被跟踪的文件模式,运行 git lfs ls-files 可列出实际由 LFS 存储的文件。
如果我在 GitHub 或其他托管服务上的 Git LFS 存储用完了怎么办?
GitHub 等服务会设置存储上限。您可以使用 git lfs prune 管理存储、购买更多空间,或使用其他外部存储解决方案。
启用 Git LFS 后还能停止使用吗?
可以,但您需要使用 git lfs migrate export --include="*.filetype" 将文件迁回标准 Git,以移除 LFS 跟踪。