LoginSignup
9
5

More than 3 years have passed since last update.

pre-commitのススメ

Last updated at Posted at 2019-12-09

この記事は Git Advent Calendar 2019 10日目の記事です。

はじめに

最近、gitのhooksでpre-commitを使い始めた
なかなか良いことが多かったので書いてみる

モチベーション

  • PHPという自由な言語なので、他人のコードを読む時に苦しみたくない
  • コードレビューの時にスペースがないとかくだらないことをチェックしたくない
  • シンタックスエラーを事前に検知したい

やったこと

  • php -lでのシンタックスチェック
  • phpmdでのお作法チェック
  • php-cs-fixerでの自動修正

上記3点をcommit時にチェック。違反や引っかかることがあった時に、commitできないという結構厳しめのルール設定

php -lについて

  • phpのシンタックスエラーをチェックしてくれる
<?php

$a = "test"
echo $a;

?>
$ php -l file.php

Parse error: syntax error, unexpected 'echo' (T_ECHO) in test.php on line 5
Errors parsing test.php

このようにあらかじめエラーを見つけてくれる

phpmdについて

公式

インストール方法

$ brew install phpmd

$ phpmd --version
PHPMD 2.7.0snapshot201907302127

このように表示されればOK

使用法

  • 使っていない変数のチェック
  • 長すぎる変数名
  • 複雑すぎるクラス

などなど様々なバグの温床をあらかじめ見つけてくれる

使い方は以下のように2通り

$ phpmd file.php text unusedcode,codesize,naming

or

$ phpmd file.php text phpmd-ruleset.xml

phpmdコマンドの後ろにファイル名またはディレクトリ、レポートフォーマット(text or xml)、使用ルールまたはルール記述xmlファイルの指定という風に書く。

ルールセットについて

上記のようにxmlファイルでルールを設定することができる。

phpmd-ruleset.xml
<?xml version="1.0"?>
<ruleset name="My first PHPMD rule set"
        xmlns="http://pmd.sf.net/ruleset/1.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0
                    http://pmd.sf.net/ruleset_xml_schema.xsd"
        xsi:noNamespaceSchemaLocation="
                    http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>
    My custom rule set that checks my code...
</description>

    <rule ref="rulesets/codesize.xml">
        <exclude name="CyclomaticComplexity" />
    </rule>
    <rule ref="rulesets/controversial.xml" />
    <rule ref="rulesets/unusedcode.xml" />
    <rule ref="rulesets/naming.xml">
        <exclude name="ShortVariable" />
        <exclude name="ShortMethodName" />
    </rule>
    <rule ref="rulesets/design.xml">
        <exclude name="CouplingBetweenObjects" />
    </rule>
</ruleset>

このように、<rule>タグで使用ルールを指定。<exclude>タグでルール内の細かいルールの除外をする。

例えば、

<rule ref="rulesets/naming.xml">
    <exclude name="ShortVariable" />
    <exclude name="ShortMethodName" />
</rule>

この場合、ネーミングに関するルールを使用するが、短すぎる(3文字以内)の変数名は引っかかるというルールを除外している。

php-cs-fixerについて

インストール方法

// composerのあるディレクトリに移動
$ cd path/to/your/project

$ composer install

$ ./vendor/bin/php-cs-fixer --version

PHP CS Fixer 2.16.0 Yellow Bird by Fabien Potencier and Dariusz Ruminski

こうなればOK。

使い方

$ ./vendor/bin/php-cs-fixer fix file.php

このようにすると、これが

<?php

$a="test";
echo $a

?>

こうなる

<?php

$a = "test";
echo $a;

これでコードの統一性がある程度出るし、変な指摘をしないで済む。

ルールについて

.php_cs.distというファイルで設定できる

<?php

return PhpCsFixer\Config::create()
    ->setRiskyAllowed(true)
    ->setRules([
        '@PSR2' => true, //基準となるルールの設定
        'array_syntax' => ['syntax' => 'short'], //配列の書き方について
        'global_namespace_import' => ['import_classes' => true, 'import_constants' => true, 'import_functions' => true],  //namespaceの書き方について
        'concat_space' => ['spacing' => 'one'] //文字列連結の際のスペースについて
    ])
    ->setFinder(PhpCsFixer\Finder::create()
        ->exclude('vendor')
        ->in(__DIR__)
    );

これ以外にもこれを使えば便利に比較することができる。

pre-commitの設定

$ cd path/to/your/project/.git/hooks

$ touch pre-commit

$ vim pre-commit
#!/bin/sh
against=HEAD

IS_ERROR=0

for FILE in `git diff-index --name-status $against -- | grep -E '^[AUM].*\.php$'| cut -c3-`; do
    if php -l $FILE; then
        ./vendor/bin/php-cs-fixer fix $FILE
        git add $FILE

        if ! phpmd $FILE text phpmd-ruleset.xml; then
            IS_ERROR=1
        fi
    else
        IS_ERROR=1
    fi
done
exit $IS_ERROR

.phpファイルのみだけがチェック対象。

導入後

  • コードレビューでクリティカルな指摘に集中できるようになった
  • コーディングスタイルが整うようになり、可読性が上がった
  • 潜在的なバグが減らせた(と思ってる)
  • 一度にcommitするとしんどいからcommit粒度が細かくなり、振り返りやすくなった

良いことだらけ。
ぜひ良いコミットライフを!

9
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5