为什么使用filter-branch的--cached选项会删除工作目录中的文件?

6

我需要从一个旧的仓库中删除一些本应该被忽略的Xcode文件。因此,我运行了以下命令:

git filter-branch --index-filter 'git rm -f --cached --ignore-unmatch *mode1v3 *pbxuser' HEAD

我的理解是添加--cached不会影响当前工作目录,但git也删除了那些匹配的文件。幸运的是我有备份!但我很好奇为什么会这样做,或者我是否误解了--cached的含义?


据我所知,您不能在--index-filter中使用通配符(*) -- 至少不带引号。由git filter-branch展开的shell会使用工作树扩展通配符。 - J-16 SDiZ
你试过不加 -f 吗? - VonC
2个回答

5
罪魁祸首不是git rm命令。它的--cached选项确实像你说的那样工作。您可以在一个小的git repo中轻松尝试。
虽然man页面没有提到,但git filter-branch似乎不保留您的工作区。实际上,如果您的工作区不干净,该命令会拒绝运行,这已经是一个指示。
但即使文件已从工作区中消失,它们也没有从repo中消失。它们只是不再存在于当前分支中任何提交可达的提交中。但filter-branch存储了对重写前分支的引用,以引用名称空间refs/original/。
使用命令git show-ref查看它。
您可以检出旧版本以访问已删除的文件。您可以使用命令git cat-file blob refs/original/refs/heads/master:foo获取文件内容而无需检出(使用show-ref显示的引用,foo是所需文件的名称)。有很多可能性。
您可以使用gitk --all浏览您重写和当前分支,您会发现什么都没有真正消失。

2

git-filter-branch的行为可能会让您感到惊讶,正如您发现的那样,它在运行时不会保护您免受意外后果。

相反,我建议使用BFG Repo-Cleaner,这是一个更简单、更快速的替代方法,专门用于从Git历史记录中删除文件。其中一种使您的生活更轻松的方式是,它不会删除或以任何方式更改最新提交的文件。

您应该遵循使用说明 - 但其核心部分只需下载BFG的jar包(需要Java 6或以上版本),然后运行此命令:

$ java -jar bfg.jar  --delete-files *{mode1v3,pbxuser}  my-repo.git

您的代码库历史记录中与该表达式匹配的任何文件 - 且不在您的最新提交中的文件 - 将被删除。然后,您可以使用git gc清除无效数据:

$ git gc --prune=now --aggressive

BFG相对于git-filter-branch来说使用起来要简单得多 - 选项是围绕这两种常见用例而设计的:

  • 删除超大文件
  • 删除密码、凭据和其他私人数据

完整披露:我是BFG Repo-Cleaner的作者。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接