正如文档在这里指出的那样:
--subdirectory-filter <directory>
Only look at the history which touches the given subdirectory. The result will
contain that directory (and only that) as its project root. Implies
[Remap_to_ancestor].
我认为问题在于合并提交实际上并没有触及给定的子目录,这意味着 subdirectory-filter 甚至不查看它们,因此无法保留它们。因此,我们必须使用另一个过滤器来检查每个提交。tree-filter 非常适合这个,但是我们必须编写一个脚本来执行我们想要对每个提交执行的操作。
此外,我的问题实际上比示例更广泛,因为我的project-root
文件夹有我想删除的兄弟姐妹。子目录过滤器将删除它们,但为了使用树过滤器这样做,它有助于find
救援。
将每次运行的命令放在单独的文件中很方便。
对于这样的回购结构:
.git/
someDirectory/
someFile.txt
otherDirectory/
dontDeleteThisOne/
project-root/
xyz/
abc/
这对我有用:
git filter-branch --tree-filter /absolute/path/to/filterScript.sh --tag-name-filter cat -- --all
其中 /absolute/path/to/filterScript.sh 是包含以下内容的可执行脚本:
#!/bin/bash
#save the folder dontDeleteThisOne so it won't get deleted
git mv -fk dontDeleteThisOne project-root && \
#remove everything not under project-root
find . -maxdepth 1 -mindepth 1 '(' -name project-root -o -name '.git' ')' -prune -o -exec git rm -rf --ignore-unmatch '{}' ';' && \
#move the contents of the project-root directory up to root
git mv -fk project-root/{,.[!.],..?}* .;
生成的回购结构是这样的:
.git/
dontDeleteThisOne/
xyz/
abc/
此结果等同于 的结果git filter-branch --subdirectory-filter project-root
,除非合并提交根据需要保留在历史记录中。
当然,这比使用子目录过滤器花费的时间要长得多......