三个脚本Alexander Mikhailian

cat .gitmodules |while read ido  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 _$mnamefidonegit rm .gitmodules

?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 .gitmodulecat .gitmodules |while read idoif [[ $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    echofidonegit rm .gitmodulesgit commit -a -m "Removed .gitmodules"

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 .gitmodulecat .gitmodules |while read idoif [[ $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 masterfidonegit rm .gitmodules

?️参考文档

  • Convert a git repository from submodules to subtrees | Alexander Mikhailian (mova.org)
  • Convert Git submodule to subtree – Stack Overflow

三人行, 必有我师; 知识共享, 天下为公. 本文由东风微鸣技术博客 EWhisper.cn 编写.