《Git/Gitlab进阶》十六:将单一项目拆成多个小项目并保留各自的历史记录
本章主要测试讲解
- 如何将一个 git 管理的较大的项目按文件夹拆分成几个小项目,且各个小项目只保留自己文件夹中的文件的历史记录。
- 两种方式实现
- 使用
git filter-branch
的实现 - 使用
git subtree
的实现(推荐)
- 使用
本篇内容,不建议跳过,假如有这个需求,还请仔细详细查看,谢谢。
测试过程
前置说明
与项目合并相反,这是需要把单一项目的.git 的提交记录,抽取出各自子项目想要的部分。不过,相对于合并,拆分要简单些。
就不考虑把一个单独的文件拆成一个项目了。假如实在需要,就把这个单个文件,也放到一个文件夹中,再拆这个文件夹就可。
本地 git 仓库使用的是相对路径,所以直接修改 root folder 不会影响 git 历史记录
项目准备
不将上一篇合并好的 timetools 再拆开。直接使用之前从 github 上克隆的 dayjs 项目作业。
在作业前,dayjs 的结构是这样的:
1.png
查看一下,此时所有的日志 log 修改的文件名。如下图(这里是可以看到所有文件修改内容和提交数量):
2.png
dayjs 项目中,dayjs/src/有两个文件夹,locale/和 plugin/,示例伪装 locale/需要拆出来,做一个单独的项目。
大概流程
1 使用
git filter-branch
- 重写提交历史记录
- 清理.git 的 object 文件夹(假如觉得有必要的话)
- 查看日志信息
2 使用
git subtree
- 进入 dayjs,创立一个临时分支
- 创立一个新的 git 空项目
- 将原仓库的临时分支 my-locale 拉到新仓库
使用git filter-branch
实现–不推荐,仅作理解,不感兴趣可略过
重写提交历史记录
$ git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter src/locale -- --all
命令说明:
git filter-branch
通过重写分支来重写 Git 修订历史记录,并在每个修订版上应用自己设置过滤器。
- –tag-name-filter <command> 该参数控制我们要如何解决旧的 tag,cat 即表示原样输出;
- –prune-empty 删除空的(对子目录没有影响的)提交;
- –subdirectory-filter <directory> 指定子目录路径;
- – –all
-- all
参数必需跟在 – 后面,表示对所有分支进行操作。假如你只想保存当前分支,也可以不增加此参数。
此操作会花点时间,执行完成,可以看到,原版的 dayjs 下的文件,变成了这样:
执行后
清理.git 的 object 文件夹(假如觉得有必要的话)
git reset --hardgit for-each-ref --format="%(refname)" refs/original/ |xargs -n 1 git update-ref -dgit reflog expire --expire=now --allgit gc --aggressive --prune=now
git for-each-ref 根据给定的集合对它们进行排序之后,迭代所有匹配的 ref <pattern>并根据给定的显示它们。
- –format=<format> %(fieldname)从所显示的 ref 及其指向的对象插入的字符串。
git-update-ref-安全地升级存储在 ref 中的对象名称
- 带-d 标志,它在验证命名的<ref>依然包含<oldvalue>后将其删除
git reflog expire 修剪较旧的引用日志条目。
- –expire=<time> 修剪早于指定时间的条目。
- –all 解决所有引用的引用日志。
git-gc 清除不必要的文件并优化本地存储库
- –aggressive 此选项将导致 git gc 更积极地优化存储库,但花费更多时间。
- –prune=<date> 修剪比日期更旧的松散对象(默认为 2 周前)
清理的执行如下图:
清理object
查看日志信息
其实最重要就只有第一步而已,完成之后,现在可以查看到现在的 dayjs 的日志
如下图:
执行后的日志
现在只有原来在 dayjs/src/locale 里面的文件被修改的提交记录被保留,其它的都丢掉了。
只需把这个现在的 dayjs 修改成 locale,就完成了大项目拆分成子项目的操作。
使用git subtree
实现–推荐做法
同样,使用最开始的从 github 中拉下来的 dayjs 做源项目。
进入 dayjs,创立一个临时分支
git subtree split -P src/locale -b my-locale
命令说明:
git subtree
合并子树并将存储库拆分为子树。
这个命令不在本来的 git 参考文件上,不过用法比较简单,可以在这里查看的更多用法。
- split
从<prefix>子树的历史中提取一个新的合成项目历史。新的历史记录仅包括影响<prefix>的提交(包括合并),并且这些提交中的每个现在都在项目的根目录而不是子目录中具备<prefix>的内容。因而,新创立的历史记录适合作为单独的 git 存储库导出。 - -P <prefix> = –prefix=<prefix> 在存储库中指定的子树的路径
- -b <branch> 创立一个分支
如下图
创立临时分支
创立一个新的 git 空项目
在与 dayjs 平级的路径下,创立一个文件夹,例如 my-locale(和上一步创立的分支名没任何关系),并进入,而后 git 初始化
cd ..mkdir my-localecd my-localegit init
如下图:
新建空git项目
将原仓库的临时分支 my-locale 拉到新仓库
git pull ../dayjs my-locale
如下图
空项目完成临时分支的拉取
查看日志,效果一致,如下图:
一样的日志
对于一开始说的,单个文件,想要这样做,似乎不行。如下图。
单个文件拆成项目
还是放到文件夹吧。
总结
- 使用
git filter-branch
拆分子项目,是会把除了需要被拆分的部分,一律都删除了,包括.git 仓库里的东西。这是在本来的项目上进行作业。 - 使用
git subtree
是在原项目中创立了临时分支,再拉取到新的 git 空项目,不会对原项目进行异动,原项目甚至不会知道子项目的存在。 - 假如提交的次数较多,为了挑选所有的历史记录,都会比较耗时间。但不修改原项目的
git subtree
,显然更好。 - git subtree 创立子项目命令小计
cd <source-project> git subtree split -P <prefix> -b <temp-branch> cd .. mkdir <sub-project> cd <sub-project> git init git pull <source-project path> <temp-branch>
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 《Git/Gitlab进阶》十六:将单一项目拆成多个小项目并保留各自的历史记录