从Git仓库中拆分子目录并保留所有当前位于该子目录中的文件的历史记录

6
也许已经有解决方案了,但其他问题/答案似乎涉及稍微不同的问题(或者我真的不理解它们)。
我的意图是将Git存储库的子目录分离并使其成为独立的存储库,同时保持历史记录完好无损,但仅保留子目录的历史记录。这个问题似乎首先可以解决问题,但后来我发现其中有一个缺陷: git filter-branch --subdirectory-filter只保留与给定子目录相关的提交。但这意味着删除了影响该子目录中现有文件但已从其他位置移动到该子目录的文件的提交。
我之所以注意到这一点,是因为我“清理过”的存储库的第一个提交是“将所有内容移动到子目录X”。这意味着我的文件以前在另一个位置,但那个时候的提交没有被保留。
因此,我需要的是一个命令(或一系列命令),它可以:
  • 删除存储库中的所有提交
  • 除了包含现在位于给定子目录中的文件或其他位置中这些文件的早期版本的提交之外。

B)
可能有一些提交也包含不符合这些条件的文件。如果可以从存储库完全删除这些文件,那将是一个很好的附加功能。


编辑:

上面链接的解决方案将新存储库中的子目录内容提取到存储库的根目录中。正如@Amber指出的那样,这将导致已经存在于根目录中的文件出现问题。因此,我想要实现的是:

原始目录结构:

\Old-Repo
    \.git
    \ABC
    |- dir content
    \DEF
    |- dir content
    \GHI
    |- dir content

分离的代码库的目录结构应为:
\New-Repo-DEF
    \.git
    \DEF
    |- dir content

而不是:

\New-Repo-DEF
    \.git
    content of old DEF subdirectory

然后,我会使用正常的提交方式,将DEF子目录中的内容移动到根目录中。


1
这个问题在于 - Git如何表示超出当前顶级目录的路径? - Amber
有必要将子目录向上提取吗?我很乐意将子目录保留为新存储库中的子目录(并在常规提交后将内容拉到主目录中)(请参见我的编辑问题)。 - uli_1973
1个回答

1
根据历史记录的复杂程度,可能可以使用git filter-branch --tree-filter(如此处所述)重写它并移动文件,然后再使用--subdirectory-filter提取子目录。
换句话说,如果git log -- somedir显示"将文件XYZ移动到somedir"作为somedir目录的最早提交,则可以执行git filter-branch --tree-filter '插入一个相当简单易懂的脚本,将文件XYZ移动到somedir' HEAD。这样,在提取子存储库之前,您可以整理目录结构。
我几天前在一个相当小的仓库(~150个提交,线性历史记录)上做了这件事,并且它起作用了,但我认为如果没有一些严肃的自动化,它不会扩展。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接