《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 --hard
git for-each-ref --format="%(refname)" refs/original/ |xargs -n 1 git update-ref -d
git reflog expire --expire=now --all
git 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-locale
cd my-locale
git 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>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容