我如何`git filter-branch`多个子目录并保留其父目录?

时间:2017-10-13 11:54:45

标签: git

假设我有一个文件夹结构的存储库,如下所示:

resource

我希望我可以简单地|-dir1 |-dir2 | |-subdir1 | |-subdir2 | |-subdir3 |-dir3 离开它,但我似乎遇到了两个挑战:

  • 我似乎无法提供多个git filter-branch --subdirectory-filter参数?至少它似乎不包括我想要的所有子目录。
  • git似乎剥离了父目录。

如果我想过滤我的回购以获得此结果,该怎么办?:

--subdirectory-filter

增加:

正如评论中所建议的,我尝试过:

|-dir1
|-dir2
| |-subdir1
| |-subdir3

但这很慢,所以我对它很不耐烦。 git filter-branch --tree-filter 'rm -rf dir2/subdir2' --prune-empty 似乎暗示我可以使用git help filter-branch代替--index-filter来加快速度,所以我希望我可以简单地这样做:

--tree-filter

然而,即使它似乎正在通过我的提交并做某事,它以消息结束:

  

警告:参考'refs / heads / master'保持不变

和'dir2 / subdir'及其内容仍在我的工作副本中。所以我明显误解了一些事情。我很好奇用git filter-branch --index-filter 'rm -rf dir2/subdir2' --prune-empty 做这件事的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

这实际上是问题所在:

git filter-branch --index-filter 'rm -rf dir2/subdir2' --prune-empty

索引过滤器必须在Git的索引(也称为临时区域缓存)上运行,具体取决于您正在查看的特定Git文档。)

幸运的是,对于这种特殊情况,有一个Git命令相当于rm -rf,它只在Git的索引上运行:

git rm --cached -rf --ignore-unmatch dir2/subdir2

我们需要--cached部分才能使其仅适用于索引,-r使其行为类似rm -r-f --ignore-unmatch使其行为像rm -f。因此,完整的filter-branch命令至少是:

git filter-branch \
    --index-filter 'git rm --cached -rf --ignore-unmatch dir2/subdir2' \
    --prune-empty

(您可能需要添加--tag-name-filter cat和/或其他过滤器分支选项。)

(filter-branch命令充满了小怪癖,因为它必须复制每个提交它“过滤器”,这非常慢。--tree-filter是最简单的使用因为它适用于所有正常的文件系统操作,但这也使它成为最慢的。)