我想将两个 repos A 和 B 合并到一个公共 repo C 中。A 和 B 在根文件夹级别都有很多文件,所以我想在 repo C 的根文件夹中创建文件夹 A 和 B ,并将每个原始 repo 的内容放在其匹配的文件夹中。
有没有git mv
在过程中不使用的情况下这样做?问题是我正在使用 Xcode,不幸的是它没有遵循重命名文件的历史记录,所以我想尽可能避免移动。实际上,我想将每个 repo 直接合并到它的子文件夹中。
有很多方法可以实现这一点,并且该问题的博客文章和 SO 答案的数量是其两倍。最简单的解决方案可能是使用git-stitch-repo工具。
另一种选择(我没有尝试过)是关注这篇博文。但它非常血腥,如果您有想要移动到子目录的点文件,则需要进行一些调整。
git-subtree
脚本。add
将创建合成历史,就好像原始代码始终位于指定目录中一样。通过建立在迈克尔建议的博客文章上,我已经能够进行合并。原始帖子只负责合并主分支 - 我已将其扩展为从合并的存储库中提取所有分支,因此不会丢失任何历史记录。
重申一下,我发现了许多其他建议的方法来进行这种合并,但没有一个既保存历史又不重命名路径(导致 Xcode 无法显示历史)。
# Init a git repo which will contain the merge of the two repos, each in its own subdirectory
cd ~/dev
mkdir Merged
cd Merged
git init
# Dummy initial commit to create a master branch
git commit --allow-empty -m "Initial commit"
# Clone first repo
cd ..
git clone <RepoA url>
cd RepoA
# Checkout all branches
for remote in `git branch -r | grep -v master `; do git checkout --track $remote ; done
# Prepend subdirectory to all committed files paths in all branches
git filter-branch -f --prune-empty --tree-filter ' mkdir -p .sub;
find . -mindepth 1 -exec mv {} .sub;
mv .sub RepoA
' -- --glob=refs/heads/*
# Garbage cleanup
git gc --aggressive
# Same steps for second repo
cd ..
git clone <RepoB URL>
cd RepoB
# Checkout all branches
for remote in `git branch -r | grep -v master `; do git checkout --track $remote ; done
# Prepend subdirectory to all committed files paths in all branches
git filter-branch -f --prune-empty --tree-filter ' mkdir -p .sub;
find . -mindepth 1 -exec mv {} .sub;
mv .sub RepoB
' -- --glob=refs/heads/*
# Garbage cleanup
git gc --aggressive
# Merge modified repos into unified repo
cd ../Merged
git remote add RepoA ../RepoA
git remote add RepoB ../RepoB
git fetch --all
for remote in `git branch -r`; do git checkout -b $remote --track $remote ; done
# Merge wanted branches (usually master) from each original repo into the master branch of the unified repo
git checkout master
git merge RepoA/master
git merge RepoB/master
# Remove remotes
git remote rm RepoA
git remote rm RepoB
# Garbage cleanup
git gc --aggressive
# All done
# Optionally push into a new empty remote repository
git remote add RepoMerged <Merged Repo URL>
git push --all RepoMerged