How do I format all commits in a branch?

158 Views Asked by At

I'd like to run an auto-formatting tool (e.g. Prettier, go fmt, clang-format, terraform fmt ...) on all commits in a branch. I could manually edit each commit in the branch using an interactive rebase (git rebase -i) but that is quite tedious if there are a lot of commits on the branch.

How do I automatically apply the auto-formatting to each commit in the branch?

2

There are 2 best solutions below

0
qff On

You can use git rebase --exec like so:

git rebase \
  --strategy-option=theirs \
  --exec '<formatting/linting command here>' \
  --exec 'git add `git show --name-only --pretty="" HEAD`' \
  --exec 'git commit --amend --no-edit' \
  <base branch, e.g. "main" or "master">

Source: https://blog.scottlogic.com/2019/03/04/retroactively-applying-prettier-to-existing-branches.html

Note: This is also possible using git filter-branch --tree-filter but that command is now discouraged and produces a warning when invoked on the command-line. The suggested alternative git-repo-filter cannot do this directly, but contains an example lint-history-command which is able to do this.

0
Guildenstern On

The problem with git-rebase(1) for formatting is that it can lead to merge conflicts. Which are irrelevant: you are just normalizing all of the commits, so there shouldn't be any real conflicts.

But what if every step of the rebase was run on the snapshot (the tree)? Then the run of the previous step would not interfere with the current step. So if the formatting changes consisted of for example:

  • Use four-space indent instead of two-space
  • Use one-arg-per-line for function calls on long lines
  • Always add a space between operators

Then it seems that we should neither introduce textual conflicts nor any logical conflicts.

And that's what the third-party git-branchless(1) tool does with git test fix:

git test fix --exec 'cargo fmt --all'

Or replace cargo fmt --all with some other formatting command that formats all tracked files.