git commitのタイミングで差分のあるファイルのみ整形する

2022-07-29

はじめに

複数人で開発をすると人によってコードの書き方が違ってくるので、コードレビューやコード修正がしにくいということはあります。その問題を解決するためにコードフォーマッターを導入することで解決すると思います。しかし、コードフォーマッターを実行するタイミングは、まちまちなのかなと思います。コードをビルドするタイミング、エディタ上でコードを保存するタイミング、CI 上で整形などなど…しかし、これらのタイミングだと以下の問題があるのかと思っています。

  • コードをビルドするタイミング
    • ビルドするほどじゃないコード修正のときにビルドしないといけないので面倒
  • エディタ上でコードを保存するタイミング
    • vim や VS Code など人によって使っているエディタが違うときに設定方法が違ってくるので面倒
  • CI 上で整形
    • 最近の CI はクレジットを消費して実行するものが多いので、貴重なクレジットを整形に使うのはもったいない(クレジット消費が多いのは体感なので間違ってるかも)

これらの問題を解決するコードフォーマッターのタイミングが、git commitかなと思いました。git なら人によって環境が違うということもなくpre-commitを作ればチームで設定を使い回せるのもいいと思っています。今回はそんな commit のタイミングで差分のあるファイルに対してコードを整形する方法について紹介します。

設定方法

リポジトリ直下に.githooksを作って、pre-commitファイルを作成します。今回は SwiftLint で Swift ファイルを、clang-format で C++ファイルのコードを整形するシェルスクリプトを載せています。フォーマッターを実行している箇所を、使いたいものに環境によって変更して下さい。事前に、SwiftLint や、clang-format など使うフォーマッターをインストールして下さい。

SwiftLintのpre-commit
#!/bin/bash

STAGED_FILES=$(git diff --diff-filter=d --staged --name-only)

echo "$STAGED_FILES" | grep -e '\(.*\).swift$' | while read -r file; do
  swiftlint autocorrect --format --path "${file}"
  git add "${file}"
done
clang-formatのpre-commit
#!/bin/bash

STAGED_FILES=$(git diff --diff-filter=d --staged --name-only)

echo "$STAGED_FILES" | grep -e '\(.*\).cpp$' -e '\(.*\).h$' | while read -r file; do
  clang-format -i -style=file "${file}"
  git add "${file}"
done

そしてリポジトリ直下で以下のコマンドを実行します。

pre-commitを設定するコマンド
git config core.hooksPath .githooks
chmod +x .githooks/pre-commit

これでgit commitのタイミングで自動で整形されます。pre-commitは commit の直前に実行されるので、フォーマットした後は、再度整形したファイルをgit addします。シェルスクリプト内で再度git addしないと整形前のステージングされたファイルが commit されます。このスクリプト実行後に整形されたファイルが commit されます。

最後に

今回は commit のタイミングでコードを整形する方法について紹介しました。設定も簡単なのでおすすめです。 この設定を導入する時は、一度、プロジェクト全体にフォーマッターで整形して、master(main)リポジトリなりに反映しないと、編集箇所以外の箇所も整形して差分が大変なことになりますのでご注意して下さい。

Tatsumi0000

Written by Tatsumi0000 モバイル開発が好きなエンジニアのブログです. GitHub

Copyright © 2023, Tatsumi0000 All Rights Reserved.