有一种方法是通过排除其他文件,只保留想要的文件来实现目的。
简单来说,复制代码库,然后使用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
强制参数再次运行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'