将子目录从Git repo复制到新的存储库(具有新的目录结构)

时间:2017-04-20 12:28:47

标签: git

此问题基于Detach many subdirectories into a new, separate Git repository

我的存储库结构如下所示:

(function() {
  const NaN = 'something';
  const Infinity = '5';
  console.log(NaN);
  console.log(Infinity);
})();

console.log(NaN); //hasn't been overwrited
console.log(Infinity); //hasn't been overwrited

//const NaN = ''; --> throws error (has already been declared)
//const Infinity = 5; --> throws error (has already been declared)

而我想这样做:

/apps
  /AAA
  /BBB
  /CCC
/libs
  /XXX
  /YYY
  /ZZZ

链接问题中提出的解决方案保留了文件夹的原始路径。我想改为在新的存储库中提取位于不同路径中的一组文件夹,其中所有文件夹都在root上。

另一个约束是,提交历史记录可能同时涉及两个文件夹,并且我希望以相同的方式保留。例如,假设原始存储库中的日志包含:

/AAA
/XXX

我希望看到新回购中的等价物:

"My commit message"
/apps/AAA/file1.txt
/libs/XXX/file2.txt

如何实现这一目标?

2 个答案:

答案 0 :(得分:1)

这个棘手的部分是历史保护。可以使用git filter-branch完成。

你几乎可以使用subdirectory-filter,但是你一次只能处理一个目录(因此它会很棘手)并且任何影响多个目录的提交都不会很好地表示在结果中..

相反,您需要使用tree-filter,不幸的是,这意味着该过程可能需要相当长的时间才能运行。基本上,该过程将检查每个提交(包括编写工作树),运行您的过滤器脚本(将移动您想要的目录并删除其他所有内容),并提交结果。你可能想在快速存储上运行它 - 如果有很多历史记录,即使RAMDisk也不会有点过分。

你的过滤器脚本应该是什么样的取决于你将要运行的环境;但是bash中的filter.sh示例可能看起来像

#! /bin/bash

mv apps/AAA .
mv libs/XXX .
rm -r apps libs

然后你运行

git filter-branch --tree-filter filter.sh --prune-empty

这会创建一些您需要清理的“备用参考号”(例如originals/refs/heads/master)。

删除这些引用后,原​​始提交仍然在回购中。如果你想摆脱它们,最干净的方法是克隆(如果在本地进行,则使用file:// url。)

答案 1 :(得分:0)

我用这种方式解决了我的问题:

1)使用git splits命令拆分原始仓库中的子目录

git splits -b tmp_branch apps/AAA libs/XXX

2)使用git-mv-with-history命令将文件夹移动到新路径(保留历史记录):

git checkout tmp_branch
git-mv-with-history apps/AAA/=. libs/XXX/=.

3)分支推送到新的仓库

git push ../new_repo/ +tmp_branch:master

或者,如果您正在使用GitHub:

git push git@github.com:accountname/new_repo +tmp_branch:master