关于git:将git仓库从submodule转换为subtree

41次阅读

共计 3021 个字符,预计需要花费 8 分钟才能阅读完成。

三个脚本

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

🐾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"

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

📚️参考文档

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

正文完
 0