Gitにまつわるエトセトラ

git

新年度ですね。アキです。いや、季節は春なんですが、今回のブログ担当が僕、アキです。どうも。


弊社でも多くの開発現場と同様、Gitでのバージョン管理を行なっています。フレッシュな若者達がうっかり変なコミットをしたり、戻そうとして泥沼にはまったり、勢いでforce pushしてしまったりするんでしょうか。ワクワクしますね!


今回は各種コマンドでどうこう、というお話ではなくそれ以外のGitの話をしてみようと思います。


基本にて王道のコミットメッセージついて再考察してみる


簡単ですが奥が深いと思っているコミットメッセージ。結局のところログなので大切なことは、



  1. 可読性を持つこと

  2. 被検索性を持つこと


が大前提ですね。後から探すのが楽で、見たらすぐ何かわかる、というのが理想です。


さんざん今まで議論され尽してきた感がありますが、今いちど、このルールを再確認しましょう。
How to Write a Git Commit Message


また、commitizenというプロジェクトがあります。
これはルールにのっとって対話式にコミットメッセージを作成するCLIなんですが、デフォルトの設定が秀逸です。



タイプ(スコープ): タイトル



というフォーマットを使います。
タイプは例えば、fixfeatdocbuildchoreなどが入ります。
スコープはある場合記入し、タイトルのところには先程コミットメッセージのルールにのっとったようなメッセージが続きます。
そしてもちろん必要な場合は3行目から詳細を書きます。


個人的には日本人のみで構成される開発チームの場合は可読性と検索性に考慮していれば日本語コミットでも良いと思っています。ただし、英語の言語特性では動詞、つまり一番核となるものが最初に来ます。そのため分かりやすいメッセージになりますが、日本語の言語特性の場合、最後に来ることが基本になります。
日本語でわかりやすいコミットメッセージにしようと思ったら、英語よりさらにルールを追加するのが良いでしょう。例えば、



修正: ◯◯のバグ



とか



機能: ◯◯の実装



のように。先に動詞をもってくる、体言止めにする、読点はつけない、みたいにすると良さそうです。また同音異義語や同じような意味も多いので使う言葉をあるていど絞ったほうが良いかもしれません。最初に言った被検索性に留意したいですね。


Protected Branchを使う(GitHubの場合)


GitのシステムにGitHubを使っているなら、Protected Branchの設定ができます。これは設定したブランチに対してforce pushが効かなくなるように保護してくれるものです。例えばmasterやproductionブランチが重要な場合、運用コストがかからないので設定しておくのが良さそうです。


その他にもstatus check機能で、PullRequest時にCI上のテストが通らないとマージを行なえない、など設定することも可能です。


Git hooksを活用する


GitHub上でCIによるテストが回るように、ローカルでも特定のGitコマンドをトリガーにして特定の動作を自動でおこなうことができます。これはGitHubではなくGit自体の機能なのでどのような環境でも使うことができます。


例えば、コミット時にLinterやformatterをかける、Push時にテストを回す、など。また、工夫次第では特定のブランチの場合、プッシュをリジェクトなんていうこともできます。


設定の仕方は/.git/hooksにそれぞれのトリガー用のシェルスクリプトを置くだけです。


僕の場合はmaster、もしくはproductionブランチにプッシュしようとすると警告を出して確認するスクリプトが走るようにしています。これは自分ではmasterからトピックブランチ生やして作業していたと思ったら生えてなかった! ってことがあったからです。上で説明したProtected Branchではforce pushしか防げないので、両方設定するよにしています。
具体的には以下のスクリプトを/.git/hooks/pre-pushとして保存するだけです。
(実行権限の付与が必要です)


#!/bin/bash

while read local_ref local_sha1 remote_ref remote_sha1
do
for branch in "master" "production"; do
if [[ "${remote_ref##refs/heads/}" = "${branch}" ]]; then
echo "警告:重要なブランチにプッシュしようとしています。正気ですか? [y/N]"
exec < /dev/tty
read ANSWER
case $ANSWER in
"Y" | "y" ) echo "プッシュします";;
* ) echo "プッシュをキャンセルしました";exit 1;;
esac
exit 0
fi
done
done

Git Hooks を活用するための便利なもの


Rubyでは、pre-commit時だけでよければpre-commit、全てのトリガーに対応するならばovercommitなどがあります。
特に後者はカスタムスクリプトも走らせられるので、上で説明した自作のpre-pushなどを併用することができます。


またNode.js系が使えれば、huskyが有名ですね。こちらはpackage.json内にトリガーに応じたコマンドを記述するので|&&でつなげば自作スクリプトも併用できます。特にlint-stagedと組み合わせることが多いです。


テンプレートを活用する(GitHub)


GitHubを使っているならIssueやPullRequestも使っていると思います。実はこれらはテンプレートを決めて、新規作成時に自動で挿入してくれる機能があります。


使いかたはプロジェクト直下、または/.github内にPULL_REQUEST_TEMPLATE.mdISSUE_TEMPLATE.mdをそれぞれ置くだけです。


例えば要望のIssueのテンプレートなら


## 要望概要

## ゴール
<!-- この要望を達成したと見なす条件 -->

## タスク
- [ ] タスク1

とか。PullRequestのテンプレートなら


## 概要
FIX or RESOLVE or CLOSE: #

## 内容

## 想定する影響範囲

## 動作に必要なコミットに含まれない変更
<!-- e.g. 環境変数, DBの更新 など -->

## 補足

とか、実はまだ完全に定まってはいないんですが、ちょこちょこ使っています。


テンプレートの効能として、ある一定のクオリティを保った内容になるとともに、ガイドができて内容を書きやすくなるので、積極的に使うほうがいいと思います。特にIssueについては非エンジニアの人が作る開発現場もあると思います。そういう時にテンプレートがあれば、まず状況を確認するの必要な情報が入りやすくなるのでオススメです。




この記事へのコメント