8

主分支中 Git repo foo 的结构

foo/refs/a.txt  
foo/bar/refs/b.txt  

在其他分支机构refs/可能在很多其他地方

目标

从 Git(历史)环境中删除目录引用(及其内容)的所有实例:使用 Git Bash 的 Windows 7

删除 refs(Git 不参与,尝试这个只是为了看看它自己工作)

find . -name refs -depth -exec rm -rf {} \;

成功,所有refs/及其内容都被删除(如果我不使用-depth,find会报错,即使正确删除了dirs也不存在)。

从 Git 中删除 refs

git filter-branch --index-filter \
'find . -name refs -depth -exec git rm -rf --cached --ignore-unmatch {} \;' \
--prune-empty --tag-name-filter cat -- --all

通过重写 Git 历史记录从 Git 中删除目录引用

如图所示(认为temp/aas temp/foo),该命令运行并重写所有提交,但没有refs/被删除,因此 find 的输出不会filter-branch --index-filter按预期返回。

类似的事情似乎对其他人有用。
我错过了什么?

PS。是的,我已经阅读了数百篇关于此的帖子、文章等几个小时,但无论如何它对我不起作用。

4

1 回答 1

6

更新

虽然我的旧答案显然帮助原始发帖人部分解决了他的问题,但似乎我实际上可能不正确,--index-filter唯一适用于 Git 命令的,因为在文档中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

可能的情况是,如果您要使用带有 的非 Git 命令--index-filter,那么它们必须对存储库的索引进行操作,如文档中的上述示例所示。

所以基本上,我不确定为什么原始发布者的原始索引过滤器不起作用,但可能是他试图访问索引过滤器不允许访问的存储库的一部分,或者他使用的任何非 Git 命令实际上都没有修改索引。

此外,正如我在评论中指出的那样

Git 实际上将其所有引用存储.git/refs/在非裸存储库中,在工作副本根目录中......因此该命令find . -name refs -depth实际上也会挖掘这些目录。

那么也许这会导致过滤器分支期间出现严重错误?

旧答案

我认为问题可能是您尝试使用带有filter-branch --index-filter选项而不是--tree-filter选项的非 Git shell 工具:

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 存储库本身的索引文件进行操作(它不检查工作副本以进行操作)......所以只有 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)

于 2013-07-07T23:18:45.400 回答