对一系列Git提交运行git-clang-format

11

我已经写了一系列Git提交,但代码格式很糟糕。
在将它们推送到Github之前,我想对每个提交运行git-clang-format,以获得一个漂亮的格式化代码历史记录。

有没有一些rebasegit-clang-format的组合可以实现这一点?

3个回答

18
那看起来就是git filter-branch的工作了,它可以重写你想要的提交。由于这些提交尚未推送,改变它们的内容(因此也改变了它们的SHA1)并不是什么大问题。
而且效果类似于rebase或cherry-picking,只不过你可以对每个被重播的提交运行任何命令。
你可以对最近的几个提交运行filter-branch
参见 "使用git filter-branch重构代码库",作者Elliot Chance
git filter-branch --tree-filter 'git-clang-format' -- <SHA1>..HEAD

考虑到git-clang-format语法,你可以将其应用于每个提交中的已更改文件。
例如,对于.cpp文件:
git filter-branch --tree-filter 'git-clang-format $(\
  git diff-index --diff-filter=AM --name-only $GIT_COMMIT |\
    grep .cpp) || true' -- <SHA1>..HEAD

更新2017年,使用Git 2.14.x/2.15(2017年第四季度),你可以看到一个示例:
请参考提交2118805提交6134de6(2017年8月14日)由Brandon Williams(mbrandonw提交。
(由Junio C Hamano -- gitster --合并于提交a36f631,2017年9月25日) Makefile:添加样式构建规则
添加“style”构建规则,该规则将在HEAD和当前工作树之间运行git-clang-format。结果是建议更改的差异。
.PHONY: style
style:
    git filter-branch --tree-filter 'git-clang-format || true' -- <SHA1>..HEAD

2022年:正如thakis评论中所指出的,D117414git-clang-format添加了返回代码,解决了llvm/llvm-project问题53220

https://reviews.llvm.org/D117414 在任何文件更改时会使 git-clang-format 退出并返回代码 1。因此,现在您需要编写 git filter-branch --tree-filter 'git-clang-format || true' -- <SHA1>..HEAD - undefined
@thakis 感谢您的反馈:我已经相应地编辑了答案。 - undefined

4

目前我手动完成这个过程,以免格式出错。例如:重新组织头文件可能会导致编译失败。

步骤从最新的提交开始。如果你从HEAD~#开始,则几乎永远不会有变化,除非它们是原子且不相关的。git clang-format只更改您更改的代码(以及相关的代码块),而不更改其他未修改的代码。

  1. git clang-format HEAD~1 :结果将显示已更改的文件。编译并验证。
  2. 将这些新文件作为临时提交进行提交。
  3. git rebase -i HEAD~2
  4. 将新提交更改为“修复”并完成rebase。

(您可以在命令行上手动执行此操作,但出于某种原因,我仍然使用编辑器完成这一操作。)

然后,您需要重复HEAD〜2、HEAD〜3等步骤,直到完成整个链条。

关于此的一些注意事项。在某些情况下,clang-format会多次更改相同的代码。它已经越来越少发生了,但有时必须忽略它们。


与其创建一个新的提交并将其压缩,你也可以通过使用 --amend 直接更新 HEAD。 - psykid

2
如果你想在每次提交中仅对更改的行应用clang-format,请执行以下操作:
# The first commit you want to edit.
# You can use the following command if it’s a child of origin/master.
export FIRST_COMMIT=$(git rev-list --ancestry-path origin/master..HEAD | tail -n 1)

git filter-branch --tree-filter 'git-clang-format $FIRST_COMMIT^' -- $FIRST_COMMIT..HEAD

对于每个提交,这将执行以下操作:

  1. 将提交检出为原始历史记录中的状态
  2. 计算与FIRST_COMMIT的父级(例如origin/master)的差异。 (注意:如果您仅计算与当前提交的父级的差异,则可能会撤消在其他提交上进行的clang-format更改!)
  3. clang-format影响的行
  4. 在先前的提交之上创建提交的副本

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