《Git/Gitlab进阶》十五:合并两个项目为一个并保留合并前所有历史记录

本章主要测试讲解

  • 如何将两个 git 管理的项目合并成一个项目,并保留住各自项目中所有的历史提交记录。(后续可以自行拓展到三个、四个……的合并)

本篇内容,不建议跳过,如果有这个需求,还请仔细详细查看,谢谢。

测试过程

前置说明

git 管理的项目合并,还要保留之前的提交历史记录,则表明不能直接异动到原项目.git 文件夹仓库,需要通过其它方式把子项目的.git 文件夹合并到一起,才能保存住所有提交信息。

项目准备

  • 先从 github 克隆了两个项目用于测试,一个是 dayjs,一个是 moment;
  • 计划是把 dayjs 和 moment 合并为一个项目,名为 timetools;
    • 该项目包含两个文件夹,一是 dtool,对应原本的 dayjs;
    • 二是 mtool,对应原本的 moment。

效果,合并前

- dayjs                 => 独立的 dayjs 项目,有自己的.gitignore 和 .git/
- moment                => 独立的 moment 项目,有自己的.gitignore 和 .git/

合并后:

- timetools/            => 即最开始的 dayjs,整合完后更名
  - .gitignore          => 合并两个 repos 的忽略文件
  - .git/               => 最终仅余一个 repo
  + dtool/              => 对应 dayjs
  + mtool/              => 对应 moment

克隆的项目,内容如下:

1.png

使用git log --oneline | wc -l获取提交数量。

粗略可见,dayjs 的提交为 1046 次,moment 提交为 3724 次。
注意分支名,dayjs 为 dev,moment 为 develop。

大概流程

  • 1 进入 dayjs 文件夹,将 moment 作为远程仓库添加到 dayjs 来;
  • 2 合并添加的库 moment 到原本的 dayjs 项目;
  • 3 创建 mtool 文件夹,把 moment 的 develop 分支合并到 mtool 文件夹;
  • 4 完成 moment 转移提交;
  • 5 完成 dayjs 文件的迁移;
  • 6 完成项目合并并查看历史记录。

测试步骤

进入 dayjs 文件夹,将 moment 作为远程仓库添加到 dayjs 来

使用命令:

git remote add -f moment D:/davidsu/Desktop/GitlabTest/full/moment

命令说明:
git remote add 添加远程仓库路径

  • -f 的作用是在添加后立刻 fetch。
  • D:/davidsu/Desktop/GitlabTest/full/为需要被合并 moment 项目的绝对路径

如下图:

2.png

合并添加的库 moment 到原本的 dayjs 项目

使用命令(注意分支名):

git merge --strategy ours --no-commit --allow-unrelated-histories moment/develop

命令说明:
git merge 为合并分支

  • –strategy ours 解析合并,在合并时,如果遇到冲突,以我的为准。(本例是在 dayjs 中合并 moment,遇到冲突以 dayjs 的为准)。结果就是:
    • moment 的历史记录被合并到 dayjs 的历史记录中。
    • moment 的文件树被读取并和 dayjs 的文件树比对进行冲突解析。
  • –no-commit 合并解析完成后中断,停留在最后的提交步骤之前。
    • 只要你还没 commit,那么 merge 的结果就暂时保存在缓存区中,只有完成提交步骤合并才算彻底完成(文件树被正式改变)。
  • –allow-unrelated-histories 允许合并无关的历史记录。
    • 如果不添加此选项,可能会出现fatal: refusing to merge unrelated histories错误。

如下图:

3.png

创建 mtool 文件夹,把 moment 的 develop 分支合并到 mtool 文件夹

使用命令:

mkdir mtool    # 创建文件夹
git read-tree --prefix=mtool/ -u moment/develop

命令说明:
git read-tree 给定的树信息读入索引

  • –prefix 用于指定文件树读取后保存的路径,相对于当前路径并且一定要追加 /。
  • -u 是说在读取后更新 index,使得 working tree 与 index 保持同步。

这个命令的意义在于,之前的git merge命令可能会在解决冲突的时候,把 moment 的文件树弄得比较混乱,再使用read-tree去修复一下。

如下图(再次提醒,=前后不要空格):

4.png

完成 moment 转移提交

上一步已经修复了文件数,执行完之后,仍然在 MERGING 状态,需要提交一次修改。

使用命令:

git commit --message '完成moment 的迁移,新目录为 mtool'

如下图(MERGING 过成已完成):

5.png

完成 dayjs 文件的迁移

以上,已把 momet 项目迁移到了 dayjs 下的 mtool 文件夹了。现在要迁移 dayjs 文件夹了。

在 dayjs 文件夹下,新建文件夹 dtool

mkdir dtool

再把所有原本属于 dayjs 的文件移动到新建的 dtool 去。
也就是除了 dtool/、mtool/、.git/、.gitignore 之外的所有。

剪切完之后,把这个原本的 dayjs 的文件夹重命名为 timetools。

完成项目合并并查看历史记录

到这一步,原本的 dayjs 项目,就变成了 timetools 项目,里面的 dtool 文件夹就是 dayjs 项目。

不过还差一点,之前只是把文件放进去了,还需要合并.gitignore 文件。

在新的 timetools 文件夹下,运行:

cat mtool/.gitignore >> .gitignore

把原本 moment 项目,现在的 mtool 文件夹下的.gitignore 的内容,合并到现在 timetools 文件夹下的.gitignore 中,完成忽略文件的合并。

如下图:

6.png

到这里,合并作业就基本完成了,最后在添加提交一次,做合并项目的记录

git add --all;
git commit --message '迁移整合完成!'

如下图:

7.png

合并前后的文件夹结构如下:

8.png

查看合并后的项目历史记录,如下图:

9.png

提交数:4772 = 1046 + 3724 + 2。

总结

以上,完成了两个项目合并到一个项目的示例接操作演示,后续有更多的项目想要合并,可以类似。

本示例使用步驟

  • 进入 dayjs
  • git remote add -f moment D:/davidsu/Desktop/GitlabTest/full/moment
  • git merge –strategy ours –no-commit –allow-unrelated-histories moment/develop
  • mkdir mtool
  • git read-tree –prefix=mtool/ -u moment/develop
  • git commit –message ‘完成 moment 的迁移,新目录为 mtool’
  • mkdir dtool (还在 dayjs 下面)
  • 拷贝 dayjs 的原始项目文件(除了 .git/ 和 .gitignore 以外)至 dtool/;
  • 拷贝完之后,可以把原本文件夹名 dayjs 改为 timetools;
  • 把此时 mtool 下的.gitignore 文件内容,整理合并到 timetools 下的.gitignore 文件中去。
  • 合并完之后,再全部添加提交一次,做为整合操作的记录:
    • git add –all; git commit –message ‘迁移整合完成!’

整理引用原作者步骤:
目标:将 frontend 项目与 backend 项目,合并到 project 项目下的 client 文件夹与 server 文件夹。

  1. $ [~] cd frontend
  2. $ [frontend] git remote add -f backend /fullpath/to/backend
  3. $ [frontend] git merge --strategy ours --no-commit backend/master
  4. $ [frontend] mkdir -p server
  5. $ [frontend] git read-tree --prefix=server/ -u backend/master
  6. $ [frontend] git commit --message '完成 backend 的迁移,新目录为 server'
  7. $ [frontend] mkdir -p client
  8. # 拷贝 frontend 的原始项目文件(除了 .git/ 和 .gitignore 以外) 至 client/
  9. $ [frontend] cd ..; mv frontend/ project/; cd project
  10. $ [project] cat server/.gitignore >> .gitignore
  11. # 整理合并后的 .gitignore,修复其中的路径缺失并保存;修复各种项目依赖的缺失,本地测试。
  12. $ [project] git add --all; git commit --message '迁移整合完成!'

参考文件:
https://segmentfault.com/a/1190000000678808

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

推荐阅读更多精彩内容