2017-03-16 125 views
4

我有一个复杂的git回购从中我想删除ALL文件和历史,除了两个文件夹,让我们说:删除所有除从混帐历史的某些文件夹

foo/a 
bar/x/y 

虽然git filter-branch --subdirectory-filter会让我选择一个文件夹,然后创建新的根目录,似乎没有给我任何选择两个目录的选项,并保留它们的位置。

git filter-branch --tree-filter--index-filter看起来像它会让我迭代历史中的每一个提交,我可以在不需要的文件夹上使用git rm

我似乎无法找到任何工作方式来获取这些命令,只保留我想要的两个文件夹,同时清除其他所有内容

谢谢!

+1

的解决办法是: 'git filter-branch --prune-empty --index-filter'git ls-files | grep -vE“foo/a/| bar/x/y /”| xargs git rm -rf --cached --ignore-unmatch'' –

回答

1

你是对的:树滤波器或索引滤波器将是与git filter-branch做到这一点的方式。

树形过滤器比较容易,但速度要慢得多(容易慢10到100倍)。树型过滤器的工作方式是,您提供的命令在临时目录中运行,该目录包含所有且仅存在于原始(即时复制)提交中的文件。您的命令留下的任何文件都保留在复制的提交中。您的命令在临时目录中创建的任何文件也都位于复制的提交中。 (您可以在临时目录中创建或删除目录,因为Git只存储这些文件。)因此,要删除除 A和B以外的所有内容,请编写一个命令,删除除了A或B:

find . -name A -prune -o -name B -prune -o -print0 | xargs -0 rm 

例如。

索引过滤器比较难,但速度更快,因为Git不必将所有文件复制到文件树中,然后重新扫描文件树以构建新索引,以便复制原始提交。相反,它只提供一个索引,然后可以使用命令(例如git rm -rf --cached --ignore-unmatch)或git update-index来处理最常见的情况。但是,现在唯一的工具是Git中操纵索引的工具。没有花哨的Unix find命令。

你当然有git ls-files,它读出索引的当前内容。因此,你可以写在任何一种语言,你喜欢的节目(我会使用Python先到这里,大概,别人可能会用Perl开始),在本质上的作用:

for (all files in the index) 
    if (file name starts with 'A/' or 'B/') 
     do nothing 
    else 
     add to removal list 
invoke "git rm --cached" on paths in removal list 

如果你愿意相信,没有文件名中有嵌入式换行符,上面可以常规shell来完成的:

git ls-files | IFS=$'\n' while read path; do 
    case "$path" in A/*|B/*) continue;; esac 
    git rm --cached "$path" 
done 

这还不是特别有效的(一个git rm --cached每道!),但应该工作“开箱即用”作为--index-filter

(未经测试,但可能工作,应该是显著更有效:。通过grep -vgit ls-files输出删除所需的文件和管道grep输出为git update-index --force-remove --stdin这仍然不承担任何换行符路径名)

+0

Thanks @torek!不熟悉'find'我不得不对它解构一些,直到我找到它的工作,但这将需要大约一个小时。 我找到了一个很好的解决方案: 'git filter-branch --prune-empty --index-filter'git ls-files | grep -vE“foo/a/| bar/x/y /”| xargs git rm -rf --cached --ignore-unmatch',尽管一次迭代超过了我可以管到'xargs'的参数数量。 我解决了这个通过首先删除整个大文件夹,使用'git filter-branch --prune-empty --index-filter'git rm -rf --cached --ignore-unmatch c/d/e /'HEAD' –

0

对于文件,我这样做了git fast-export。但我不确定这会对目录产生影响。所以我建议使用git fast-exportfind的组合。

git fast-export HEAD -- `find foo/a bar/x/y -type f` >../myfiles.fi 

然后创建一个新的回购,并导入流。

git init 
git fast-import <../myfiles.fi 
相关问题