使用tomono迁移multiplerepo至monorepo

tomono是一个代码库迁移工具,可以很方便的将multiplerepo的代码迁移至monorepo,并且保留所有分支和历史提交记录,有很多特性:

下面是根据实际开发过程中进行的一次迁移工作,参考该过程写的一个demo,便于记录。

1. 构建monorepo git仓库

初始化构建一个git仓库即可

git init或直接在GitHub/GitLeb/gitee构建项目,再将项目git clone下来,此处演示为GitHub构建项目:

2. 使用tomono将multiplerepo仓库迁移至构建的monorepo应用

参考tomono的应用示例即可:

2.1. 应用实践过程

  1. 在monorepo仓库的父级目录创建repos.txt文件:

内容如下:

txt 复制代码
git@github.com:7neves/multiple-repo1.git repo1
git@github.com:7neves/multiple-repo2.git repo2
  1. 下载tomonoshell命令(复制github.com/hraban/tomo...仓库下的tomono文件内容即可),在用户根目录构建~/tomono/tomono.sh脚本文件:
sh 复制代码
#!/usr/bin/env bash
set -euo pipefail ${DEBUGSH+-x}
# 这里执行后报错,先不执行,不影响
# shopt -s inherit_errexit

# Poor man's arg parse :/
arg="${1-}"
: "${MONOREPO_NAME:=scyx-frontend}"

case "$arg" in
    "")
        if [[ -d "$MONOREPO_NAME" ]]; then
            >&2 echo "monorepo directory $MONOREPO_NAME already exists"
            exit 1
        fi
        mkdir "$MONOREPO_NAME"
        cd "$MONOREPO_NAME"
        git init
        ;;

    "--continue")
        if [[ ! -d "$MONOREPO_NAME" ]]; then
            >&2 echo "Asked to --continue, but monorepo directory $MONOREPO_NAME doesn't exist"
            exit 1
        fi
        cd "$MONOREPO_NAME"
        if git status --porcelain | grep . ; then
            >&2 echo "Git status shows pending changes in the repo. Cannot --continue."
            exit 1
        fi
        # There isn't anything special about --continue, really.
        ;;

    "--help" | "-h" | "help")
        cat <<EOF
Usage: tomono [--continue]

For more information, see the documentation at "https://tomono.0brg.net".
EOF
        exit 0
        ;;

    *)
        >&2 echo "Unexpected argument: $arg"
        >&2 echo
        >&2 echo "Usage: tomono [--continue]"
        exit 1
        ;;
esac

# 创建一个空树
empty_tree="$(git hash-object -t tree /dev/null)"

# Note this is top-level in the script so it's reading from the script's stdin
# 读取stdin中的内容
while IFS=$'\r'"$IFS" read -r repourl reponame repopath; do
    if [[ -z "$repopath" ]]; then
        repopath="$reponame"
    fi

    # 添加远程仓库
    git remote add "$reponame" "$repourl"
    # 设置远程仓库的fetch规则
    git config --add "remote.$reponame.fetch" "+refs/tags/*:refs/tags/$reponame/*"
    # 设置远程仓库的tagOpt
    git config "remote.$reponame.tagOpt" --no-tags
    # 获取远程仓库的提交
    git fetch --atomic "$reponame"
    
    # 获取远程仓库的分支
    git branch -r --no-color --list "$reponame/*" --format "%(refname:lstrip=3)" | while read -r branch ; do
        # 如果分支不存在,则创建一个根提交
        if ! git show-ref --verify --quiet "refs/heads/$branch"; then
            tree="$(git commit-tree \
                "$empty_tree" \
                -m "Root commit for monorepo branch $branch")"
            git branch -- "$branch" "$tree"
        fi
        # 将当前分支设置为远程分支
        git symbolic-ref HEAD "refs/heads/$branch"
        # 重置当前分支
        git reset -q
        
        # 将远程分支合并到本地分支
        git read-tree --prefix "$repopath" "refs/remotes/$reponame/$branch"
        tree="$(git write-tree)"
        commit="$(git commit-tree \
            "$tree" \
            -p "$branch" \
            -p "refs/remotes/$reponame/$branch" \
            -m "Merge $reponame/$branch")"
        git reset -q "$commit"
    done
done

# 将当前分支重置到根提交
git checkout .

# Copyright © 2020, 2022, 2023 Hraban Luyat
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, version 3 of the License.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
# 
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
  1. 执行脚本:cat my-repos.txt | ~/tomono/tomono.sh --continue
    • 这里有几个注意点:

报错信息如上,所以注释了shell脚本第二行的代码

      • 默认构建的仓库名为core,可以修改,命令行输入进行修改:

export MONOREPO_NAME=multiple-to-mono

      • 因为该文件夹已经存在,根据脚本提示,添加了--continue指令

2.2 踩坑点

这里有个比较棘手的问题,如上本来需要迁移的仓库有两个,但是脚本执行完之后,只迁移了一个项目,对shell脚本掌握的知识比较少,查询多处资料无果,最后将my-repos.txt文件进行了修改,多复制了一份仓库地址出来,没想到解决了🤣:

scss 复制代码
git@github.com:7neves/multiple-repo1.git repo1
git@github.com:7neves/multiple-repo2.git repo2
git@github.com:7neves/multiple-repo2.git repo2

再次执行脚本:cat my-repos.txt | ~/tomono/tomono.sh --continue,正常迁移仓库:

3. 总结

至此,迁移代码的工作结束,可以看到在monorepo仓库的分支中包含了所有提交信息:

相关推荐
会一丢丢蝶泳的咻狗11 分钟前
Sass实现,蛇形流动布局
前端·css
攀登的牵牛花16 分钟前
前端向架构突围系列 - 状态数据设计 [8 - 4]:有限状态机 (FSM) 在复杂前端逻辑中的应用
前端
Lsx_16 分钟前
前端视角下认识 AI Agent 和 LangChain
前端·人工智能·agent
我是伪码农1 小时前
Vue 智慧商城项目
前端·javascript·vue.js
不认输的西瓜1 小时前
fetch-event-source源码解读
前端·javascript
用户39051332192881 小时前
前端性能杀手竟然不是JS?图片优化才是绝大多数人忽略的"降本增效"方案
前端
朱昆鹏2 小时前
开源 Claude Code + Codex + 面板 的未来vibecoding平台
前端·后端·github
lyrieek2 小时前
pgadmin的导出图实现,还在搞先美容后拍照再恢复?
前端
永远是我的最爱2 小时前
基于.NET的小小便利店前台收银系统
前端·sqlserver·.net·visual studio
从文处安2 小时前
「九九八十一难」第一难:前端数据mock指南(TS + VUE)
前端