一次 Git-LFS 的迁移记录。
网上说了一大堆 Git-LFS 的作用和好处,我觉得都是把官方文档零零碎碎翻译一下。在我看来,对于普通开发者而言,Git-LFS 的作用很简单,就是让你 pull 代码的时候不用每次都把一大堆大文件一块 pull 下来,而且我个人使用体验还有切换分支之类的操作都变快了。
Git-LFS 安装
sudo apt/yum install git-lfs
即可,然后 git lfs install
。
Git-LFS 使用
追踪和推送
在一个已经初始化后的 Git 仓库中使用 Git-LFS 来追踪大文件,命令如下:
git lfs track <filepattern>
track 会产生一个 .gitattributes
文件,和 .gitignore
类似,也是 git 自己的文件,用于描述 Git-LFS 的文件名匹配模板。一般而言,文件中的每一行类似这种:
*.pbtxt filter=lfs diff=lfs merge=lfs -text
-text
就是表示这个文件不是文本文件。其余的就是告诉 Git 在处理 filter、diff、merge 时将 pbtxt 文件通过 LFS 的方式处理,打开 .gitconfig
可以看到相关命令的替换。
用 Git-LFS track 追踪档案之后,就可以添加、提交和推送到远端目录上,你在首次推上去的时候,会要一些时间将大型档案传输到远端。这里是很多教程很模糊的地方,事实上,Git-LFS 并不是什么魔法,仍然要将文件同步到远端。有的 git 仓库页面会显示 Git-LFS 的标记,gitlab 就可以,好评,tx 自用的工蜂,呵呵。
拉取
其他用户使用这个仓库的时候,使用 git clone
会拉取普通的文件,但是 LFS 追踪的文件不会被拉下来。如果这些文件本地没有,则需要使用 git lfs pull
从远程仓库拉取。
现在的 git 貌似是直接能够拉取所有文件,包括 lfs 文件,如果不想拉取 lfs 文件,可以使用
GIT_LFS_SKIP_SMUDGE=1 git clone
总结来看,Git-LFS 唯一的目的就是于其他 clone 使用者来说,他们若不需要异动大型档案,就不需要进行git lfs pull 的动作,于是那个原本的大型档案会变成一个130 bytes 的文字档。即使他clone 整个master,也是很小的储存库。Git-LFS 的使用无关档案大小,唯一的重点在于某些档案你想放在 master 内,或是说必须放在master 内,而其他人又不需要同步这个档案的话,就可以使用 Git-LFS 的方式来管理此档案。
Git-LFS 迁移
这个才是比较实用的,因为很多仓库是用着用着才想着用 lfs…
对于一个已经用了一段时间的 Git 仓库,直接执行 git lfs migrate import --include="*.bin" --everything
,可以将所有本地分支上的匹配文件的提交历史版本都转换为 lfs,这个时候无论你切换到哪个分支,都会出现 .gitattributes
文件,且内容都是一样的。
如果只想更新某个分支的话,可以使用
git lfs migrate import --include="*.bin" --include-ref=refs/heads/master
可以通过 git lfs ls-files
查看哪些文件被转换成 lfs 了。
切换成功后,就需要把切换之后的本地分支提交到远程仓库了,需要手动 push 更新远程仓库中的各个分支。这里有个极大需要注意的地方,就是转换会更改所有提交的 hash,因此 push 的时候需要使用 force 选项,而当其他人员再次使用 pull 去远程拉取的时候会失败。这里当然可以使用 pull --allow-unrelated-histories
来把远程仓库被修改的历史与本地仓库历史做合并,但是最好是重新拉取。
切换成功后,git 仓库的大小可能并没有变化,主要是之前的提交还在,因此需要做一些清理工作:
1 | git reflog expire --expire-unreachable=now --all |
但是,如果不是历史记录非常重要的仓库,建议不要像上述这么做,而是重新建立一个新的仓库。个人经验,迁移可以使用,但并没那么美好。
附一个迁移相关的基础教程
Git-LFS 需要多次输入密码的问题
解决 Git-LFS 使用导致 push 需要输入多次用户名和密码。
Linux:
1 | # Set git to use the credential memory cache |
其他平台可以参考:Caching your GitHub password in Git