3

我们有一个相当大的代码库,包含大约 60000 个提交。我们希望在保留 git 历史记录的同时重新格式化所有 .java 文件。因此,我们采用的方法是使用 git filter-branch --tree-filter 重新格式化整个代码库,同时保持历史记录不变。但是,有几个问题我无法找到答案。

  1. 当我应用 --tree-filter 并传递重新格式化根目录中所有 .java 文件的命令时,会发生重写,但最后,我会在暂存区看到所有 .java 文件。重写的每一步都需要提交还是自动发生?

  2. git filter-branch 似乎接受了一系列提交,这让我想知道是否可以在每次重写之前保存提交 ID,并在失败的情况下恢复。恢复很重要,因为整个过程可能需要几天才能完成(即使在强大的计算实例上)。

  3. 为了重新格式化整个代码库, --index-filter 会起作用吗?

更新:澄清

  • 代码库大约有 220 万行 Java 代码。不进行 git rewrite 会导致大约 10%-12% 的代码库被归因于错误的作者。那是大约 200K 行的 java 代码,这是我们想要避免的。Git rewrite 让它看起来像是做出改变的人做了正确的事情。
4

2 回答 2

2

作为BFG(一种更快、更简单的替代方法git-filter-branch)的作者,我很乐意提及它,尽管它不 - 开箱即用 - 重新格式化 Java 源代码。

您提到 git-filter-branch 操作的 resume-after-failure 会很有帮助-当然,因为 git-filter-branch 太慢了。没有办法恢复 git-filter-branch操作 - 但如果它更快,它就不是什么大问题了。BFG 可以比 git-filter-branch快数百倍,因为它只清理任何给定版本的文件一次 - 不像git-filter-branch,它每次都清理同一个文件,每次提交。

BFG 支持文件中的直接文本替换,但正如我所说,它不执行 Java 源重新格式化。有两种选择可以让它发挥作用:

  1. 正如Christian Hoffmeister 最近所做的那样,将 BFG 作为库调用- 在您的情况下,传入一个调用Jalopy或其他一些 Java 源代码格式化程序的自定义TreeBlobModifier 。
  2. 更改 BFG,使其支持脱壳以调用任意 bash 命令 - 有点像git-filter-branch's--tree-filter--index-filter- 但我仍然希望它更快。

选项 2 实施起来并不难。但是,我想知道您是否可以详细说明为什么要采取这种激进的行动——改写历史?相对于重写提交和让每个人适应变化的历史的麻烦,拥有完美格式化的历史真的有很大的好处吗?为什么不一次性重新格式化您的最新提交?

于 2014-09-29T20:47:49.060 回答
1

Re 1:--tree-filter不需要单独的提交:它只是将与某个提交对应的树转储到临时目录中,运行您的过滤器,然后将生成的目录作为新提交的新树。 所有更改,包括创建或删除的文件,都会导致不同的“新”提交,并且如手册页所述,.gitignore并且使用所有其他忽略规则(因此,如果您创建 .bak 文件或其他任何文件,通常只会使用.gitignore它,您必须在树过滤器中手动删除它)。

所有这些工作都是在 git 的基本“重写”临时目录的子目录中完成的,你可以设置它,-d但默认为.git-rewrite. (过滤器的子目录——所有的过滤器,包括树过滤器——是$tempdir/t,但这不应该是相关的。)它也都是用一个特殊的临时索引(暂存区)文件($tempdir/index)完成的。

请注意,整个临时目录在git filter-branch退出时已被删除。


回复 2:是的,可以保存要过滤的 ID,它在所有过滤器运行期间位于 $GIT_COMMIT(环境变量)中。(由于过滤器大多是evaled,您甚至可以修改环境以传递其他变量或更改一些变量;请参阅 filter-branch 脚本)。


--index-filterRe 3:本质上,和之间的区别在于--tree-filter--tree-filter树提取到临时目录中,运行您的过滤器,然后卷起(可能修改的)树为新提交创建新树。相比之下,--index-filter将树加载到索引文件中;运行你的过滤器,它可以修改索引;然后使用生成的索引为新提交创建新树。

换句话说,树过滤器实际上是对索引进行解包和重新打包。这就是索引过滤器更快的原因:它跳过了解包/重新打包步骤。如果您必须修改实际文件,那么将它们全部解包、修改所有文件并重新打包显然更简单。如果许多文件不会被修改,您可以通过仅解压缩有趣的文件、修改这些文件并重新打包修改后的结果来获得一些速度,但要做到这一点,您需要一些坚韧不拔的低级 git 知识。(你可以很容易地git checkout找到git add每个文件,但你还必须找到要修改的文件。)

于 2014-09-29T18:43:25.150 回答