Git中对大仓库的处理实践

目录

1.背景

1.1处理拥有大量历史记录的库

1.1.1浅克隆是简单的的解决办法

1.1.2另一个解决办法是 filter-branch (过滤分支)

1.1.3浅克隆的替代者:只克隆一个分支

1.2处理拥有巨大二进制资产的库

2.仓库现状

3.仓库改造

3.1第一步:先建立一个VM分支,并推送至服务器

3.2第二步:轻量化master分支

3.3第三步:删除仓库目录,重新克隆

4.仓库使用


1.背景

背景章节参考:https://www.oschina.net/translate/how-to-handle-big-repositories-with-git?cmp

两种大代码库

实际工作中可能会遇到git大仓库的场景。

如果仔细想想,大概会有两种导致仓库大规模增长的原因:

  1. 项目累积了非常长的历史(项目成长了很长一段时间并且积累了包袱)。
  2. 项目包括了巨大的二进制资产,需要与代码一起跟踪配对。
  3. 两者皆有。

1.1处理拥有大量历史记录的库

将一个库视为大规模库的界线非常高 - 比如 Linux 内核的最后一个版本记录了超过 1500 万行代码,但人们仍然愿意完整阅读。

1.1.1浅克隆是简单的的解决办法

为了更快、更节省开发者和系统时间也更节约磁盘空间,第一个解决办法是使用 git 进行浅克隆。通过浅克隆可以只克隆某个库最后的历史记录。怎么做到?只需要使用 --depth 选项,比如:

git clone --depth depth remote-url

想像一下,如果你的项目库中积累了 10 年甚至更长时间的历史记录 - 比如 JIRA 是我们往 git 迁移的一个 11 年的老库 - 累积节约的时间非常显著。完整的克隆 JIRA 有 677 MB,如果包含工作目录还有另外的 320+ MB,总共超过 47,000 多次提交。通过浅克隆的方式检出 JIRE 需要 29.5 秒,而检出完整的历史记录则需要 4 分 24 秒。随着时间地推移及项目二进制资产的增长,这个差距也会成比例的增长。任何情况下,构建系统都会大大受益于这种技术(指浅克隆)。

1.1.2另一个解决办法是 filter-branch (过滤分支)

巨大的库往往存在着大量错误的提交或无用的资源,对此,使用 filter-branch 是个很好的解决办法。这个命令可以根据预先定义的模式对项目历史进行过滤、整理、修改,甚至跳过一些文件。它是 git 工具集中的一个非常强大的工具。目前已经有脚本可以用于识别 git 库中的大型对象,所以它使用起来非常容易。

使用 filter-branch 的示例:

git filter-branch --tree-filter 'rm -rf /path/to/spurious/asset/folder' HEAD

filter-branch 有一个小小的缺点:一旦使用了 filter-branch,实际上已经重写了整个项目历史,因此每次提交的 ID 都会发生变化。这要求每个开发者都要重新克隆更新后的库。

所以,如果你打算使用 filter-branch 来进行一次清理行动,应该警告你的团队,计划一个短期的冻结来进行操作,然后通知大家重新克隆库。

1.1.3浅克隆的替代者:只克隆一个分支

从 2012 年 4 月发布的 git 1.7.10 开始,你可以通过只克隆某一个分支来限制历史记录的数量,就像这样:

git clone URL --branch branch_name --single-branch [folder]

对于长期运行分发的分支,或者你在有很多分支的情况下,这个特殊的技巧都非常有用。如果你只有极少数分支,那这个办法不会带来显著的效果。

1.2处理拥有巨大二进制资产的库

第二类大型仓库中的代码含有巨大的二进制资产。游戏团队要处理巨大的 3D 模型,Web 开发团队需要跟踪图像资产,CAD 团队可能需要操作和跟踪二进制交付物的状态。所以有各种不同的软件团队在使用 git 的过程中会遇到这样的问题。

git 在处理二进制资产的时候并不是特别差劲,但它也不会干得特别好。默认情况下,git 会完整压缩存储二进制资产的所有后续版本,如果你有很多二进制资产的情况下,这显然不是最佳方案。

可以通过一些基本的调整来改善情况,比如运行垃圾回收 git gc,或者在 .gitattributes 中对部分二进制类型进行调整,以使用 delta 方式的提交。

2.仓库现状

.

|-- icb1

|   |-- image

|   |   |-- bzImage

|   |   `-- icb1_zeos_linux_defconfig

|   `-- src

|       `-- linux-4.13.2

|           `-- linux-4.13.2_icb1.tar.gz

|-- imx8qm

|   |-- android-8.1

|   |   |-- image

|   |   |   |-- defconfig

|   |   |   |-- fsl-imx8qm-mek.dtb

|   |   |   `-- Image

|   |   `-- src

|   |       `-- kernel_imx_android.tar.gz

|   `-- linux-4.9.69

|       |-- image

|       |   |-- defconfig

|       |   |-- fsl-imx8qm-mek.dtb

|       |   `-- Image

|       `-- src

|           `-- kernel-imx8qm.tar.gz

`-- zcu102

    |-- image

    |   |-- defconfig

    |   |-- Image

    |   `-- zcu102_phy.dtb

    `-- src

        `-- linux-2017.3

            |-- linux-xlnx-2017.3_video_ea.tar.gz

            `-- system-top.dts

 

从目录结构可以看出,我们资源库中存在着大量的二进制文件,占用空间已经达到十几个G字节,而且随着项目的增加,仓库必然更大,几百个G,甚至上T。随着项目的演进,资源库中会存入其他资料,如文档、脚本等轻量级文件。如果为了看某些文档而将整个仓库克隆下来,显然是不划算的。

 

3.仓库改造

目前仓库所有二进制代码都处于master分支。为了解决上面描述的问题,我们可以引入GIT的分支管理。

我们的构想是:轻量化master分支,对其他资源如文档、脚本、源码、镜像分别建立不同的分支来进行管理。Git 克隆时只克隆master分支,然后对需要的分支进行单独处理。这样,既节省了克隆时间,又节省了存储空间。

下面,就对目前仓库进行改造。

3.1第一步:先建立一个VM分支,并推送至服务器

因为目前仓库只有源码镜像文件,所以,只需要先把框架搭建起来;后面要增加文档、脚本等就比较方便。

git branch VM

git checkout VM

touch readme

git add readme

git commit -m “VM branch first commit” 

git push origin VM:VM

3.2第二步:轻量化master分支

目前采取的措施很暴力,直接清空master分支,让其不保存任何资源。这里就会用到“背景”部分提到的核武器级选项“filter-branch”

git checkout master

git filter-branch --tree-filter 'rm -f passwords.txt' HEAD

git gc --aggressive --prune=now

git push --force origin master

--tree-filter 选项在检出项目的每一个提交后运行指定的命令然后重新提交结果。在本例中,你从每一个快照中移除了一个叫作 passwords.txt 的文件,无论它是否存在。

我们这里可以使用:git filter-branch --tree-filter 'rm -rf *' HEAD命令,直接删除所有。

3.3第三步:删除仓库目录,重新克隆

因为,前面利用 filter-branch修改了整个仓库的文件及提交记录,如前面“背景”部分提到的,你需要重新克隆工程,才能体验到“.git文件夹”减小的快感。

git clone user@gitpath

这样,架构已经搭建好了,如果后面要添加新的分支,就可以直接操作了。在新建分支时,默认会保留master的提交记录,如果你不想这样,可以用下面的命令:

git branch newbranch

git checkout --orphan newbranch

--orphan参数可以让你去掉历史遗留提交记录

4.仓库使用

经历了上面的仓库改造后,如果新用户的你直接克隆整个仓库,仍然会将仓库包含的所有分支信息的.git文件夹下载下来。虽然其是压缩后的数据文件,但当二进制文件很多时,.git文件夹也会非常之大。

所以,我们可以只克隆仓库的master分支下来(几十KB),它包含了本地仓库与远程仓库的联系。然后,再建立一个本地分支来跟踪远程你需要的分支。这样,你就可以在本地只保留需要的分支的数据文件。时间和空间都可以节省。命令示例入下:

//只检出master分支

git clone gaojianyun@ipaddr:/home/gaojianyun/test.git --branch master --single-branch

git branch test                     //建立本地分支

git checkout test                   //切换到本地分支

git pull origin vm                  //拉取远程需要的分支

//下面是需要提交更改步骤

git push --set-upstream origin test:vm  //首次建立联系

git push origin                    //首次过后,就可以直接push了

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值