我有一个Git存储库,其中包含许多子目录。现在我发现其中一个子目录与另一个子目录无关,应该分离到一个单独的存储库中。
如何在保留子目录中文件的历史记录的同时执行此操作?
我想我可以制作一个克隆并删除每个克隆中不需要的部分,但我想这会在检查旧版本等时提供完整的树。这可能是可以接受的,但我更希望能够假装这两个存储库没有共享的历史。
为了清楚起见,我有以下结构:
XYZ/
.git/
XY1/
ABC/
XY2/
但我想改为:
XYZ/
.git/
XY1/
XY2/
ABC/
.git/
ABC/
原始问题希望XYZ/ABC/(*文件)变为ABC/ABC/“*文件”。在为我自己的代码实现了公认的答案后,我注意到它实际上将XYZ/ABC/(*文件)更改为ABC/(*)文件。过滤器分支手册页甚至说,
结果将包含该目录(并且仅包含该目录)作为其项目根目录。"
换句话说,它将顶级文件夹“提升”一个级别。这是一个重要的区别,因为例如,在我的历史中,我重命名了一个顶级文件夹。通过将文件夹“提升”一级,git在我进行重命名的提交时失去了连续性。
我对这个问题的回答是制作存储库的两个副本,然后手动删除每个副本中要保留的文件夹。手册页支持我:
[…]如果一次简单的提交就足以解决您的问题,请避免使用[此命令]
为了补充Paul的答案,我发现为了最终恢复空间,我必须将HEAD推到一个干净的存储库中,这样可以缩小.git/objects/pack目录的大小。
i.e.
$ mkdir ...ABC.git
$ cd ...ABC.git
$ git init --bare
在gc修剪之后,还要执行以下操作:
$ git push ...ABC.git HEAD
那你就可以了
$ git clone ...ABC.git
并且减小了ABC/.git的大小
实际上,推送清理存储库不需要一些耗时的步骤(例如gitgc),例如:
$ git clone --no-hardlinks /XYZ /ABC
$ git filter-branch --subdirectory-filter ABC HEAD
$ git reset --hard
$ git push ...ABC.git HEAD