将 git 仓库从 submodule 转换为 subtree

简介: 将 git 仓库从 submodule 转换为 subtree

三个脚本

Alexander Mikhailian

cat .gitmodules |while read i
do
  if [[$i == \[submodule*]]; then
    mpath=$(echo $i | cut -d\" -f2)
    read i; read i;
    murl=$(echo $i|cut -d\  -f3)
    mcommit=`eval "git submodule status ${mpath} |cut -d\  -f2"`
    mname=$(basename $mpath)
    echo -e "$name\t$mpath\t$murl\t$mcommit"
    git submodule deinit $mpath
    git rm -r --cached $mpath
    rm -rf $mpath
    git remote add $mname $murl
    git fetch $mname
    git branch _$mname $mcommit
    git read-tree --prefix=$mpath/ -u _$mname
fi
done
git rm .gitmodules
BASH

🐾Warning:

下文的两个脚本, 写死了 branch 是 master, 如果主分支不是 master, 需要做相应修改.

Nikita240 - Stack Overflow

📚️Reference:

我对它进行了修改和改进。现在,新的 subtree 将指向与旧 submodule 相同的提交。以前,脚本只是从目标存储库下载最新的提交,这可能会导致兼容性问题。

#!/bin/bash -x
# This script will convert all your git submodules into git subtrees.
# This script ensures that your new subtrees point to the same commits as the
# old submodules did, unlike most other scripts that do this.
# THIS SCRIPT MUST BE PLACED OUTSIDE OF YOUR REPOSITORY!!!!!!!!!!
# Otherwise, the script will interfere with the git commits.
# Save the script in your home directory as `~/subtrees.sh`
# `cd` into your repository
# Run `~/subtrees.sh`
# Enjoy!
# extract the list of submodules from .gitmodule
cat .gitmodules |while read i
do
if [[$i == \[submodule*]]; then
    echo converting $i
    read i
    # extract the module's prefix
    mpath=$(echo $i | grep -E "(\S+)$" -o)
    echo path: $mpath
    read i
    # extract the url of the submodule
    murl=$(echo $i|cut -d\= -f2|xargs)
    echo url: $murl
    # extract the module name
    mname=$(basename $mpath)
    echo name: $mname
    # extract the referenced commit
    mcommit=$(git submodule status $mpath | grep -E "\S+" -o | head -1)
    echo commit: $mcommit
    # deinit the module
    git submodule deinit $mpath
    # remove the module from git
    git rm -r --cached $mpath
    # remove the module from the filesystem
    rm -rf $mpath
    # commit the change
    git commit -m "Removed $mpath submodule at commit $mcommit"
    # add the remote
    git remote add -f $mname $murl
    # add the subtree
    git subtree add --prefix $mpath $mcommit --squash
    # commit any left over uncommited changes
    git commit -a -m "$mname cleaned up"
    # fetch the files
    git fetch $murl master
    echo
fi
done
git rm .gitmodules
git commit -a -m "Removed .gitmodules"
BASH

GaspardP - Stack Overflow

📚️Reference:

我稍微修改了一下,调用 subtree add 而不是 read-tree。它将从.gitmodule 中获取 submodule 的列表,并提取模块的前缀、名称和网址。然后它删除每个 submodule,并在同一位置添加它们作为 subtree。它还将每个 submodule 的 remote 添加为 remote,这样你就可以通过提供它的名字而不是它的网址来更新 subtree 了(即 git subtree pull -P Foo Foo master --squash 而不是git subtree pull -P Foo https://example.com/foo.git master --squash)。

如果你想把 subtree 的全部历史导入你的版本库,你可以去掉 --squash 参数。使用 --squash,将只导入 subtree 的 HEAD 到你的版本库。这可能是大多数人想要的。

#!/bin/bash -x
# extract the list of submodules from .gitmodule
cat .gitmodules |while read i
do
if [[$i == \[submodule*]]; then
    echo converting $i
    # extract the module's prefix
    mpath=$(echo $i | cut -d\" -f2)
    # skip two lines
    read i; read i;
    # extract the url of the submodule
    murl=$(echo $i|cut -d\= -f2|xargs)
    # extract the module name
    mname=$(basename $mpath)
    # deinit the module
    git submodule deinit $mpath
    # remove the module from git
    git rm -r --cached $mpath
    # remove the module from the filesystem
    rm -rf $mpath
    # commit the change
    git commit -m "Removed $mpath submodule"
    # add the remote
    git remote add -f $mname $murl
    # add the subtree
    git subtree add --prefix $mpath $mname master --squash
    # fetch the files
    git fetch $murl master
fi
done
git rm .gitmodules
BASH

📚️参考文档

相关文章
|
3月前
|
敏捷开发 测试技术 持续交付
阿里云云效产品使用合集之如何将个人账号下的Git仓库转移到企业账号下
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。
|
3月前
|
IDE 网络安全 开发工具
【Azure App Service】Local Git App Service的仓库代码遇见卡住不Clone代码的问题
【Azure App Service】Local Git App Service的仓库代码遇见卡住不Clone代码的问题
【Azure App Service】Local Git App Service的仓库代码遇见卡住不Clone代码的问题
|
9天前
|
Ubuntu Shell 开发工具
ubuntu/debian shell 脚本自动配置 gitea git 仓库
这是一个自动配置 Gitea Git 仓库的 Shell 脚本,支持 Ubuntu 20+ 和 Debian 12+ 系统。脚本会创建必要的目录、下载并安装 Gitea,创建 Gitea 用户和服务,确保 Gitea 在系统启动时自动运行。用户可以选择从官方或小绿叶技术博客下载安装包。
24 2
|
1月前
|
Shell 开发工具 git
git学习三:git使用:删除仓库,删除仓库内文件
通过GitHub的设置页面删除仓库,以及如何使用Git命令行删除仓库中的文件或文件夹。
146 1
git学习三:git使用:删除仓库,删除仓库内文件
|
1月前
|
开发工具 git 索引
git上面中新建gitignore文件,并且去除已经在仓库版本管理中的文件夹
git上面中新建gitignore文件,并且去除已经在仓库版本管理中的文件夹
65 4
|
1月前
|
存储 开发工具 git
Git 远程仓库地址管理:添加、修改和验证
Git 远程仓库地址管理:添加、修改和验证
56 4
|
1月前
|
编译器 开发工具 数据安全/隐私保护
Git——多人协作/版本控制,在一个gitee仓库下开发(Gitee版教程)手把手教学,包好用的!
本文提供了一个关于如何在Gitee上进行多人协作和版本控制的详细教程,包括新建和初始化仓库、克隆仓库、邀请好友共同管理仓库以及注意事项,旨在帮助用户顺利进行代码协作开发。
189 0
Git——多人协作/版本控制,在一个gitee仓库下开发(Gitee版教程)手把手教学,包好用的!
|
2月前
|
开发工具 git
IDEA更改远程git仓库地址
【9月更文挑战第27天】本文介绍了两种在IntelliJ IDEA中更改远程Git仓库地址的方法:一是通过图形界面,在VCS设置中直接修改;二是通过IDEA内置的命令行工具使用`git`命令进行更改。具体步骤包括从版本控制菜单进入项目设置、修改远程仓库URL,以及使用`git remote set-url`命令更新仓库地址,并验证修改结果。这些方法适用于项目迁移或更换仓库地址的情况。
547 6
|
2月前
|
Linux 开发工具 git
linux自建仓库git之钩子不生效
linux自建仓库git之钩子不生效
|
1月前
|
网络协议 网络安全 开发工具
【Git快速入门】Git代码管理手册与协同开发之远程仓库(四)
【Git快速入门】Git代码管理手册与协同开发之远程仓库(四)