我们有一个相当大的代码库,包含大约60000次提交。我们希望重新格式化所有.java文件,同时保留git历史记录。因此,我们采用的方法是使用git filter-branch --tree-filter来重新格式化整个代码库,同时保持历史记录的完整性。但是,有一些问题我无法找到答案。
当我应用--tree-filter并传递重新格式化根目录中所有.java文件的命令时,重写就会发生,但最后,我看到了所有的.java文件。集结区。重写的每一步都需要提交还是自动发生?
git filter-branch似乎需要进行一系列的提交,这让我想知道是否可以在每次重写之前保存提交ID并在发生故障时恢复。恢复很重要,因为整个过程可能需要几天才能完成(即使在强大的计算实例上)。
为了重新格式化整个代码库,请将--index-filter工作吗?
更新:澄清
答案 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源代码重新格式化。有两种方法可以让它发挥作用:
git-filter-branch
&#39} s --tree-filter
或--index-filter
- 但我仍然希望,相当快。选项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 checkout
和git add
每个文件,但您还必须找到要修改的文件。)