🐚

shell スクリプトで頑張って semantic commit を実現する

2023/08/02に公開

はじめに

皆様コミットメッセージの規約は何を採用していますでしょうか?
Conventional Commits が有名だと思いますが、今のプロジェクトでは Semantic Commit Messages を採用しています。

これを shell スクリプトで楽してコミットメッセージを作ろうって魂胆です。
ちなみにコードはほとんど Chat-GPT(GPT4) で生成しています。

正直な話

git-cz とか commitizen をカスタマイズなりして使う方が良いです。
導入するのが政治的にめんどくさそうなので、git 管理外でよしなにする感じです。。

正直もうちょっといい方法がありそうな気はしています。
(コミットテンプレートとかでよしなにできないか・・・とかなんとか)

完成図

実行すると以下のようになります。
https://youtu.be/TbzC3vBwdvg

手順

  1. 任意の場所にシェルスクリプトファイルを作成します
# サンプルでは home ディレクトリに commit.sh というファイル名で作成します
cd ~
touch commit.sh
# 作成時は各種権限がないので追加します
chmod 777 ./commit.sh
  1. 任意のエディタで ~/commit.sh を開き、以下の内容を貼り付けます
#!/bin/bash

# color
RED='\033[31m'
GREEN='\033[32m'
YELLOW='\033[33m'
BLUE='\033[34m'
NC='\033[0m'


# 許可された type と scope の定義
types=(
  "feat:     ユーザー向けの新機能であり、ビルドスクリプトの新機能ではない"
  "fix:      ビルドスクリプトの修正ではなく、ユーザーのためのバグ修正"
  "docs:     ドキュメントの変更"
  "style:    書式設定、セミコロンの欠落など"
  "refactor: プロダクションコードのリファクタリング"
  "test:     不足しているテストの追加、テストのリファクタリング"
  "chore:    gruntタスクの更新など、プロダクションコードの変更なし"
  "update:   node module をアップデート"
  "spike:    spike コミット(コメントあり)"
  "spike-no-comment: spike コミット(コメントなし)"
)

# コンソールの履歴を削除
clear

# ステージされた変更がなければキャンセル
if [ -z "$(git diff --cached --shortstat 2> /dev/null)" ]; then
  printf "${RED}コミットする変更がありません${NC}\n"
  exit 1
fi

# ステージされた変更の表示
echo "ステージされた変更:"
printf "${GREEN}$(git diff --name-only --cached)${NC}\n"

# type の入力
PS3="Commit Type: "
select typeKey in "${types[@]}"; do
  if [[ -n "$typeKey" ]]; then
    type=$(echo $typeKey | cut -d: -f1)
    printf "${BLUE}Selected Type: $(echo $type)${NC}\n"
    break;
  else
    printf "${RED}Invalid selection${NC}\n"
    exit 1
  fi
done

# subject の入力(spike コミットのコメント無しの場合は省略)
if [ "$type" != "spike-no-comment" ]; then
  while true; do
    echo "Commit Subject:"
    read -e subject
    #
    if [ -z "$subject" ]; then
      printf "${YELLOW}コミットメッセージは空欄にできません。再度入力してください。${NC}\n"
    else
      break
    fi
  done
else
  subject=""
fi

# コミットメッセージの生成
message="$type"
if [[ -n "$scope" ]]; then
  message+="($scope)"
fi
if [[ -n "$subject" ]]; then
  message+=": $subject"
fi

# pre-commit のチェックをスキップするかどうか
verify=""
if [[ "$type" == "spike" || "$type" == "spike-no-comment" ]]; then
  # spike コミットの場合はチェックをスキップ
  verify="--no-verify"
else
  read -e -p "コミット前のチェックを省略しますか? (初期値: 省略しない) [y/n] " answer
  if [[ "$answer" = "y" ]]; then
      verify="--no-verify"
  fi
fi

# 最終的なコミットメッセージをコンソールに表示(pre-commit のチェックに失敗したとき用)
printf "${BLUE}Commit Message --------------------------------------------${NC}\n"
printf "git commit -m '$message' $verify\n"
printf "${BLUE}-----------------------------------------------------------${NC}\n"

# コミットの実行
echo -e $message | git commit -F - $verify
  1. コマンド実行用にエイリアスを設定します
echo -e "alias commit='~/commit.sh'" >> ~/.bashrc
  1. 設定内容を更新
source ~/.bashrc

以上!

使い方

commit したいプロジェクト(ディレクトリ)で commit と実行すれば作成したシェルが実行されます。

  • ステージされている変更がない場合はコミットされずにキャンセルします
  • typescope は左側に表示されている数字を入力します
    正しく入力できれば Selected Type: feat のように表示されます
  • scope に何も指定しない場合は 4(none: 未選択) を入力してください
  • subject は必須です
    空のまま enter キーを押下すると再度入力をもとめられます
  • detail はオプションです
    入力しない場合は空のまま enter キーを押下してください

余談

つけようとおもったけどつけなかった機能

よくある確認する系のスクリプトですが、いちいち y を入力するのが面倒だったのでなくしました。
コミットに厳格なプロジェクトとかだと追加して良いかもです。

read -p "Are you sure you want to commit these changes? [y/n] " answer
if [[ "$answer" != "y" ]]; then
    echo "Commit cancelled."
    exit
fi

Discussion