一种相反的方法是-删除除要保留的文件以外的所有内容。
基本上,制作存储库的副本,然后用于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 current所允许的接近(据我所知)。
同样,请只在存储库的副本上运行它!-但总的来说,要删除除“ 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'