合并仓库并保留提交历史

最近整改仓库,打算使用mono-repo的仓库管理模式来管理公司代码。

所以需要将原先散落的仓库合并,但是开发要求将原来仓库的提交历史保留。

场景:

我有两个仓库repoA, repoB, 我想把repoA的master合并到repoB中的子目录:project/repoA中并保留repoA的提交历史。

我试了很多方法,速度总结一下。

1.git官方文档给出的方法,但我没有跑成功。

Git - Advanced Merging

但是我在试验这个的时候解决了一个问题,解决了我一个问题,因为后面会经常遇到。

fatal: refusing to merge unrelated histories

 解决方法:命令后面加上:--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的,可能就是修复上面我那个问题的,但是脚本我没有跑成功,遂放弃。

有空的时候又试了一下上面这篇文章中提供的脚本,的确好用。

在开始脚本之前,现在原来的仓库找到首尾提交:

git filter-branch --tree-filter '(echo === $GIT_COMMIT:; git ls-tree $GIT_COMMIT) >> /tmp/tree.log'

 在/tmp/tree.log中找到第一个commit和最后一个commit,接下来脚本会根据首尾comimt点进行运行。

#!/usr/bin/env bash

first=6b6391aee8beef6b5de8cd358502902859683e0e  # 替换为自己的首节点
last=f04bdc9098ac3aa08bd37b704d846fc5cc862dc8   # 替换为最近的节点
subdir=test_sub                                 # 子目录名称

git filter-branch --tree-filter '
  first='"$first"'
  last='"$last"'

  subdir='"$subdir"'
  log_file=/tmp/filter.log

  [ "$GIT_COMMIT" = "$first" ] && seen_first=true

  if [ "$seen_first" = "true" ] && [ "$seen_last" != "true" ]; then
    echo "=== $GIT_COMMIT: making changes"
    files=$(git ls-tree --name-only $GIT_COMMIT)
    mkdir -p $subdir
    for i in $files; do
      mv $i $subdir || echo "ERR: mv $i $subdir failed"   #主要就是通过这条命令来修改目录的,你可以根据自己的需要来调整,比如我想改名字,就不需要mkdir了,直接mv $i $subdir就可以了,非常万能。
    done
  else
    echo "=== $GIT_COMMIT: ignoring"
  fi \
    >> $log_file

  [ "$GIT_COMMIT" = "$last" ] && seen_last=true

  status=0  # tell tree-filter never to fail
'

在repoA下新建一个脚本,将以上这段代码拷贝进去并运行,运行完可以在/tmp/filter.log中查看日志。

=== 6b6391aee8beef6b5de8cd358502902859683e0e: making changes
=== daffede59c65e59aaa20a74e5f72c1fd37527cb0: making changes
=== 79d1663c8cf6486c47382c203b5f97f68c15444f: making changes
=== 0b3064423f903f0e13b8a37d8201312ca4f0e16f: making changes
=== 9cbdec606d3bb60fd4196c47d8a015bea1cfa3cc: making changes
=== 79aad516fc1f43cbaf382ebd29a0bc459a00aff3: making changes
=== f04bdc9098ac3aa08bd37b704d846fc5cc862dc8: making changes

最后再查看该repoA,发现本地文件都已经被放到test_sub下了,可以用git ls-files -s查看,文件前面也都加上了test_sub的路径。

修改完历史后,将这个仓库合并到新仓库就可以了:

git pull /repo/repoA/ --allow-unrelated-histories   #/repo/repoA就是我们刚刚处理完的本地路径

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值