主分支中Git repo foo的结构
foo/refs/a.txt
foo/bar/refs/b.txt
在其他分支refs/
可能在很多其他地方
从Git(历史记录)中删除目录引用的所有实例(及其内容) 环境:使用Git Bash的Windows 7
find . -name refs -depth -exec rm -rf {} \;
成功,所有refs/
及其内容都已删除(如果我不使用-depth
,则会报告错误,即即使这些目标已被删除,也不会存在正确地)。
git filter-branch --index-filter \
'find . -name refs -depth -exec git rm -rf --cached --ignore-unmatch {} \;' \
--prune-empty --tag-name-filter cat -- --all
从图中可以看出(将temp/a
视为temp/foo
)命令会运行并重写所有提交,但不会删除refs/
,因此以某种方式查找的输出是未按预期返回filter-branch --index-filter
。
类似的事情似乎适用于其他人 我错过了什么?
PS。是的,我已经阅读了数百个关于此的数百个帖子,文章等数小时,但它对我来说并不适用。
答案 0 :(得分:4)
虽然我的旧答案显然有助于原始海报部分地解决了他的问题,但似乎我可能实际上并不正确--index-filter
仅适用于Git命令,因为在documentation for git filter-branch
中,它给出了除Git命令外,还有一个与非Git shell命令一起使用的过滤器示例:
git filter-branch --index-filter \
'git ls-files -s | sed "s-\t\"*-&newsubdir/-" |
GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
git update-index --index-info &&
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
可能就是这样,如果您要使用带有--index-filter
的非Git命令,那么他们有来操作存储库的索引,如上所示文档中的示例。
所以基本上,我不知道为什么原始海报的原始索引过滤器不起作用,但可能是他试图访问索引的部分存储库的情况filter不允许访问,或者他使用的任何非Git命令实际上都没有修改索引。
此外,as I point out in the comments,
Git实际上将
.git/refs/
下的所有引用存储在非裸存储库中,工作副本根目录中......所以命令find . -name refs -depth
实际上也会挖掘这些目录。
所以也许这会导致在过滤器分支期间出现可怕的错误?
我认为问题可能是您尝试使用非{Gid shell工具filter-branch --index-filter
选项而不是--tree-filter
选项:
git filter-branch --index-filter \
'find . -name refs -depth -exec git rm -rf --cached --ignore-unmatch {} \;' \
--prune-empty --tag-name-filter cat -- --all
与为--tree-filter
检查每个提交的新工作目录并在其上运行传递的shell脚本不同,--index-filter
仅对Git repo本身的索引文件进行操作(它不是检查一个工作副本来操作)...所以只有Git命令才能使用它。
这可能是你运气好的原因,因为它将Git命令传递给filter-branch --index-filter
:
git filter-branch --index-filter \
'git rm -f --cached --ignore-unmatch *.zip && \
git rm -rf --cached --ignore-unmatch refs' \
--prune-empty --tag-name-filter cat -- --all
这是git-filter-branch(1) --tree-filter
的文档:
这是用于重写树及其内容的过滤器。参数在shell中计算,工作目录设置为签出树的根目录。
这是--index-filter
(强调我的)的文档:
这是重写索引的过滤器。 它类似于树过滤器,但不检查树 ,这使得它更快。经常与
git rm --cached --ignore-unmatch ...
一起使用,请参阅下面的示例。对于毛病例,请参阅git-update-index(1)。