我想将多个Git存储库(比如repoA和repoB)合并到一个新的存储库中。新存储库(repoNew)应该在单独的子目录中包含每个repoA和repoB。由于我到目前为止只在本地工作,我可以对存储库做任何我想做的事。
在这种情况下,似乎标准方法是使用git filter-branch
重写每个repoA和repoB的历史记录,使其看起来好像始终在子文件夹中,然后将它们合并到repoNew中。
第一步是困扰我的事情。我很清楚如How can I rewrite history so that all files, except the ones I already moved, are in a subdirectory?(Dan Molding的回答)中的答案,这正是我想要的。
他提出了以下内容:
git filter-branch --prune-empty --tree-filter '
if [[ ! -e repoA ]]; then
mkdir -p repoA
git ls-tree --name-only $GIT_COMMIT | xargs -i mv {} repoA
fi'
结果应该是<repoA-GIT-base>
下的文件夹结构现在应该在<repoA-GIT-base>/repoA
中。然而,这种情况并非如此。以上命令在不同的提交中随机失败,并显示“mv:无法将'src'移动到'repoA / src'等消息
如上所述重写历史记录时如何避免错误的提交?
修改
您应该考虑从移动中排除.gitignore
,如下所示:
git filter-branch --prune-empty --tree-filter '
if [[ ! -e repoA ]]; then
mkdir -p repoA;
git ls-tree --name-only $GIT_COMMIT |
grep -ve '^.gitignore$' |
xargs -i mv {} repoA;
fi'
该命令似乎仍然随机失败。我试了好几次,每次在不同的提交中都发生了“无法移动”的失败。我观察到,当我排除.gitignore
时,通过所有提交的机会似乎增加了。我能够连续在我的三个不同的存储库上执行移动而不会失败。当我再次尝试它时,只是为了获得一个存储库的另一个丢弃副本的乐趣,它再次失败了。
由于涉嫌使用某些文件的过程,我有时也很难删除我的丢弃副本,这个问题可能与Windows 7文件访问处理有关,但我无法做出严肃的假设那里。
继续尝试直到成功当然是荒谬的,并且可能无法在有很多提交的存储库上工作(我的只有~30)。
信息:我在Windows 7 64位企业版上使用git-bash与git版本1.7.10.msysgit.1。
答案 0 :(得分:2)
我怀疑你正在寻找git subhistory的内容。这是一个非常小的项目,似乎没有得到很好的维护,但它的设计也几乎完全符合您的描述。试一试!
答案 1 :(得分:1)
我已经编写了一个基于libgit2的程序来过滤git分支用于另一个目的,我稍微改变了一下你想做的事情。你可以尝试一下。
它位于github的git_filter的subdir分支中:
https://github.com/slobobaby/git_filter/tree/subdir
我刚刚在我们的100000提交存储库上测试了它,花了43秒。
我编写了该程序,因为基于git filter-branch的解决方案需要数天到数周才能完成。
示例配置过滤“test”存储库并将所有内容放在“test”子目录中 - 您可以将其更改为执行所需操作。