我想要将多个Git仓库(例如repoA和repoB)合并为一个新的仓库。新仓库(repoNew)应该包含每个repoA和repoB在单独的子目录中。由于我迄今为止只在本地工作,我可以对仓库做任何操作。
在这种情况下,标准方法似乎是使用git filter-branch
重写每个repoA和repoB的历史记录,使其看起来好像它们一直在子文件夹中,然后将它们合并到repoNew中。
第一步让我感到困扰。我很清楚类似于如何重写历史记录以使所有文件都在子目录中,除了我已经移动的文件? (丹·莫尔丁的答案)的SO答案,这正是我想要的。
他建议采取以下步骤:
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: cannot move 'src' into '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'
该命令似乎仍然随机失败。我尝试了几次,每次失败的 "unable to move" 发生在不同的提交上。我观察到,当我排除
.gitignore
时,通过所有提交的机会似乎增加了。我能够连续在我的三个不同存储库中执行移动操作而没有失败。当我再次在另一个临时副本的存储库上尝试时,它又失败了。由于有时我也很难删除我的临时副本,因为某个进程据称正在使用某些文件,所以问题可能与 Windows 7 文件访问处理有关,但我无法作出严肃的假设。
当然,一直尝试直到成功是荒谬的,这可能在具有大量提交的存储库上无法奏效(我的只有约30个)。
信息:我在 Windows 7 64位企业版上使用 git-bash 和 git version 1.7.10.msysgit.1。