这样做的一种方法是相反的 - 删除除您要保留的文件之外的所有内容。
基本上,制作存储库的副本,然后用于git filter-branch
删除除要保留的文件/文件夹之外的所有内容。
例如,我有一个项目,我希望从中提取文件tvnamer.py
到一个新的存储库:
git filter-branch --tree-filter 'for f in *; do if [ $f != "tvnamer.py" ]; then rm -rf $f; fi; done' HEAD
这用于git filter-branch --tree-filter
完成每个提交,运行命令并重新提交生成的目录内容。这是极具破坏性的(因此您应该只在存储库的副本上执行此操作!),并且可能需要一段时间(在具有 300 个提交和大约 20 个文件的存储库上大约需要 1 分钟)
上面的命令只是在每个修订版上运行以下 shell 脚本,您当然必须修改它(使其排除您的子目录而不是tvnamer.py
):
for f in *; do
if [ $f != "tvnamer.py" ]; then
rm -rf $f;
fi;
done
最大的明显问题是它会留下所有提交消息,即使它们与剩余文件无关。脚本git-remove-empty-commits修复了这个..
git filter-branch --commit-filter 'if [ z$1 = z`git rev-parse $3^{tree}` ]; then skip_commit "$@"; else git commit-tree "$@"; fi'
您需要使用-f
force 参数filter-branch
再次运行任何内容refs/original/
(基本上是备份)
当然,这永远不会是完美的,例如,如果您的提交消息提到其他文件,但它大约是 git 当前允许的(据我所知)。
同样,只在您的存储库的副本上运行它!- 但总而言之,要删除除“thisismyfilename.txt”以外的所有文件:
git filter-branch --tree-filter 'for f in *; do if [ $f != "thisismyfilename.txt" ]; then rm -rf $f; fi; done' HEAD
git filter-branch -f --commit-filter 'if [ z$1 = z`git rev-parse $3^{tree}` ]; then skip_commit "$@"; else git commit-tree "$@"; fi'