git filter repo 能否从许多按日期交织提交的 repos 中创建一个 monorepo?
Can git filter repo create a monorepo from many repos interweaving commits by date?
使用 git-filter-repo 是否可以将 N 个存储库组合成一个单一存储库,重新编写提交,以便提交交织,或者 "zippered" 按日期更新?
目前,我仅使用 2 个回购协议对此进行测试,每个回购协议都有自己的子目录。操作后,每个 repo 的提交彼此 "top" 而不是交织在一起。我真正想要的是能够通过编写的数据获得完全线性的历史记录,而无需添加合并提交。
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
强调 eftshift0 的评论:变基和重写历史可能导致提交以看似荒谬的时间顺序排序。
如果您知道所有提交都是有序的(例如:父提交的提交日期始终比其子提交的提交日期 "older"),您可以生成git rebase -i
脚本中的正确提交列表。
[edit] 考虑之后,这对于您的用例可能就足够了:
使用 --date-order
查看您的回购历史:
git log --graph --oneline --date-order
如果提交序列符合您的预期,您可以使用 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
然后 rebase 你的 repo 的完整历史:
git rebase -i --root
在编辑器中,copy/paste 您使用第一个命令创建的脚本,
保存并关闭。
希望您能得到一个无冲突的统一历史。
使用 git-filter-repo 是否可以将 N 个存储库组合成一个单一存储库,重新编写提交,以便提交交织,或者 "zippered" 按日期更新? 目前,我仅使用 2 个回购协议对此进行测试,每个回购协议都有自己的子目录。操作后,每个 repo 的提交彼此 "top" 而不是交织在一起。我真正想要的是能够通过编写的数据获得完全线性的历史记录,而无需添加合并提交。
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
强调 eftshift0 的评论:变基和重写历史可能导致提交以看似荒谬的时间顺序排序。
如果您知道所有提交都是有序的(例如:父提交的提交日期始终比其子提交的提交日期 "older"),您可以生成git rebase -i
脚本中的正确提交列表。
[edit] 考虑之后,这对于您的用例可能就足够了:
使用 --date-order
查看您的回购历史:
git log --graph --oneline --date-order
如果提交序列符合您的预期,您可以使用 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
然后 rebase 你的 repo 的完整历史:
git rebase -i --root
在编辑器中,copy/paste 您使用第一个命令创建的脚本, 保存并关闭。
希望您能得到一个无冲突的统一历史。