git filter repo 可以从许多按日期交织提交的存储库中创建单一存储库吗?

bri*_*anc 6 git bash github git-filter-repo

使用git-filter-repo是否可以将 N 个存储库组合成一个单一存储库,重写提交,以便提交交织在一起,或者按日期“压缩”?目前,我仅使用 2 个存储库对此进行测试,每个存储库都有自己的子目录。操作后,每个存储库的提交都位于彼此的“顶部”,而不是交织在一起。我真正想要的是能够通过创作数据拥有完全线性的历史记录,而无需添加合并提交。

历史


rm -rf ___x
mkdir ___x
cd ___x

echo "creating the monorepo"
git init
touch "README.md"
git add .
git commit -am "Hello World!"

declare -A data
data=( 
    ["foo"]="https://github.com/bcanzanella/foo.git"
    ["bar"]="https://github.com/bcanzanella/bar.git"
)

for d in "${!data[@]}"; 
do  {
    REPO_NAME=$d
    REPO_REMOTE=${data[$d]}

    # since we can use a foo/bar as the repo identifier, replace the / with a -
    REPO_DIR_TMP="$(mktemp -d -t "${REPO_NAME/\//-}.XXXX")"

    echo "REPO REMOTE: $REPO_REMOTE"
    echo "REPO NAME: $REPO_NAME"
    echo "REPO TMP DIR: $REPO_DIR_TMP"
    echo ""

    echo "Cloning..."
    git clone "$REPO_REMOTE" "$REPO_DIR_TMP"

    echo "filtering into ..."
    cd $REPO_DIR_TMP && git-filter-repo --to-subdirectory-filter "$REPO_NAME"
    # cat .git/filter-repo/commit-map

    ## merge the rewritten repo
    git remote add "$REPO_NAME" "$REPO_DIR_TMP"

    echo "fetching..."
    git fetch "$REPO_NAME"

    echo "merging..."
    git merge --allow-unrelated-histories "$REPO_NAME/master" --no-edit

    ## delete the rewritten repo
    echo "Removing temp dir $REPO_DIR_TMP..."
    rm -rf "$REPO_DIR_TMP"

    echo "Removing remote $REPO_NAME..."
    # git remote rm "$REPO_NAME"

    echo "$REPO_NAME done!"
} 
done
Run Code Online (Sandbox Code Playgroud)

LeG*_*GEC 3

强调 eftshift0 的评论:变基和重写历史可能会导致提交按看似荒谬的时间顺序排序。

如果您知道所有提交都是有序的(例如:父提交的提交日期始终比其子提交的提交日期“早”),您也许能够生成要提供的正确提交列表在脚本中git rebase -i


[编辑]经过思考,这可能足以满足您的用例:

使用以下命令查看您的存储库的历史记录--date-order

git log --graph --oneline --date-order
Run Code Online (Sandbox Code Playgroud)

如果提交序列符合您的预期,您可以使用它git log来生成rebase -i序列脚本:

# --reverse   : 'rebase -i' asks for entries starting from the oldest
# --no-merges : do not mention the "merge" commits
# sed -e 's/^/pick /' : use any way you see fit to prefix each line with 'pick '
#        (another valid way is to copy paste the list of commits in an editor,
#         and add 'pick ' to each line ...)
git log --reverse --no-merges --oneline --date-order |\
  sed -e 's/^/pick /' > /tmp/rebase-apply.txt
Run Code Online (Sandbox Code Playgroud)

然后重新设置您的存储库的完整历史记录:

git rebase -i --root
Run Code Online (Sandbox Code Playgroud)

在编辑器中,复制/粘贴使用第一个命令创建的脚本,保存并关闭。

希望您能获得一个不冲突的统一历史。