最近整改仓库,打算使用mono-repo的仓库管理模式来管理公司代码。
所以需要将原先散落的仓库合并,但是开发要求将原来仓库的提交历史保留。
场景:
我有两个仓库repoA, repoB, 我想把repoA的master合并到repoB中的子目录:project/repoA中并保留repoA的提交历史。
我试了很多方法,速度总结一下。
1.git官方文档给出的方法,但我没有跑成功。
Git - Advanced Merging
但是我在试验这个的时候解决了一个问题,解决了我一个问题,因为后面会经常遇到。
解决方法:命令后面加上:--allow-unrelated-histories
git merge master --allow-unrelated-histories
2.这篇博文提供的方法我试了一下是可以的:
如何用 Git 合并两个库(合并历史记录,解决冲突/改写路径)_asd131531的专栏-程序员宅基地 - 程序员宅基地
cd repoB
git remote add -f repoA_remote /fullpath/to/repoA
git merge --strategy ours --no-commit repoA_remote/master
mkdir -p project/repoA
git read-tree --prefix=project/repoA/ -u repoA_remote/master
git commit --message '完成 repoA 的迁移,新目录为 project/repoA'
但是就有一个问题,就是大部分人会提到的一个问题,
git log -- project/repoA时只显示我的合并提交,并不会显示repoA的历史提交。
最完整的版本是:https://alexharv074.github.io/puppet/2017/10/04/merge-a-git-repository-and-its-history-into-a-subdirectory-of-a-second-git-repository.html
这个里面有一段是修改index的,可能就是修复上面我那个问题的,但是脚本我没有跑成功,遂放弃。
3. git patch的方法
现在原来的仓库上导出patch,加上相对路径:
参考文档:合并2个仓库并保留完整git历史信息 - 知乎 (zhihu.com)
(1)先导出patch,在原仓库(repoA)中进行
--root后面跟的是当前你想导出的起点,可以是HEAD,也可以是分支:master
git format-patch --root HEAD --no-stat --no-renames --full-index -o patches --src-prefix=a/project/repoA/ --dst-prefix=b/project/repoA/
(2)应用patch(patch的路径自己)
git apply ~/patch/patch/*.patch # patch的路径自己修改
在应用patch时似乎会卡住,但是git log -- project/repoA是可以的
4. git subtree
其实是方法2的更友好版,git出了一个subtree的工具,一条命令就可以完成仓库合并,但是存在问题跟方法2一样,下载地址:
(1) 从github上将git-subtree.sh下载下来:https://github.com/git/git 脚本路径:git/contrib/subtree/git-subtree.sh
(2) 在git-core路径做软链接, 我本机的git-core路径是:/usr/libexec/git-core
cd /usr/libexec/git-core
ln -s /usr/local/share/git-subtree.sh git-subtree
再运行git subtree就会出来help了
(3)一条命令完成迁移:(在repoB中输入)
git subtree add -P project/repoA /path/to/repoA.git master
5. git pull
最终,我参考了这篇文章里的答案,终于实现了我想要的效果。
How do you merge two Git repositories? - Stack Overflow
(1)在本地repoA里先修改提交历史,会将所有的提交都加上project/repoA的相对路径
PREFIX=project/repoA #adjust this
git filter-branch --index-filter '
git ls-files -s |
sed "s,\t,&'"$PREFIX"'/," |
GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info &&
mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE
' HEAD
(2) 将本地的repoA合并到repoB中
在reopB中输入:
git pull localpath-of-repoA --allow-unrelated-histories