使用git rewrite重新格式化整个代码库

时间:2014-09-29 17:28:54

标签: git version-control git-filter-branch git-rewrite-history

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

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

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

  3. 为了重新格式化整个代码库,请将--index-filter工作吗?

  4. 更新:澄清

    • 代码库大约有220万行Java代码。不进行git重写会导致大约10%-12%的代码库归因于错误的作者。这是我们想要避免的大约200K行代码。 Git重写让它看起来像是做出改变的人做得对的。

2 个答案:

答案 0 :(得分:2)

作为the BFG的作者(git-filter-branch的更快,更简单的替代方案),我很乐意提及它,尽管它不是 - 不属于 - box - 做Java源重新格式化。

你提到git-filter-branch操作失败后的恢复会有所帮助 - 当然,因为git-filter-branch太慢了。有no way to resume a git-filter-branch操作 - 但如果它更快,它就会成为一个大问题。 BFG可以是many hundred times faster而不是git-filter-branch,因为它只清除任何给定版本的文件一次 - 不像git-filter-branch,每次提交都会清除同一个文件。

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

  1. 调用BFG作为库,Christian Hoffmeister recently did - 在您的情况下,传入调用TreeBlobModifier或其他Java源代码格式化程序的自定义Jalopy
  2. 更改BFG,使其支持shelling以调用任意bash命令 - 有点像git-filter-branch&#39} s --tree-filter--index-filter - 但我仍然希望,相当快。
  3. 选项2难以实现。但是,我想知道你是否可以详细说明你为什么要采取这个激烈的行动 - 重写历史?相对于重写提交和让每个人都适应变化的历史的麻烦,拥有完美格式化的历史真的有很大的好处吗?为什么不对您的最新提交进行一次性重新格式化?

答案 1 :(得分:1)

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

所有这些工作都是在git' base"的基础目录中完成的。临时目录,您可以使用-d进行设置,但默认为.git-rewrite。 (过滤器的子目录 - 包括树过滤器在内的所有这些都是$tempdir/t,但这不应该是相关的。)它也都是通过特殊的临时索引完成的(暂存区域) )文件($tempdir/index)。

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


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


回复3:基本上,--index-filter--tree-filter之间的区别在于--tree-filter将树提取到临时目录中,运行过滤器,然后汇总(可能已修改)树为新提交创建新树。相反,--index-filter将树加载到索引文件中;运行你的过滤器,可以修改索引;然后使用结果索引为新提交创建新树。

换句话说,树过滤器实际上解压缩并重新打包索引。这就是索引过滤器更快的原因:它会跳过解包/重新打包步骤。如果你必须修改实际文件,只需解压所有文件,修改所有文件并重新打包所有文件就更简单了。如果许多文件赢得被修改,通过解包有趣的文件,修改那些文件并重新包装修改后的结果,你可以获得一些速度,但要做到这一点你需要一点点坚韧不拔低级别的git知识。 (您可以轻松地git checkoutgit add每个文件,但您还必须找到要修改的文件。)