此问题基于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
如何实现这一目标?
答案 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