開発のリードタイムをより厳密に測るために空コミットを入れるようにする話
こんにちは、石坂です。
今回は、「プロジェクト開始からプルリクエスト(PR)のオープンまでのリードタイムを、より厳密に計測するために空コミットを導入する」という取り組みについてご紹介します。あわせて、ローカルでブランチを切り替えたタイミングで自動的に空コミットを行うためのスクリプト例を詳しくご紹介します。
背景と課題
アスエネでは、ソフトウェア開発の生産性を可視化するためにGitHubのログを活用しています。
今の仕組みでは、ファーストコミットからPRのオープンまでの時間や、レビューからマージ完了までの時間などを自動的に計測できます。
しかし、実際の開発現場では「お客様からの要求があってから実装の初期段階を終える(最初のコミットを行う)まで」にも時間がかかっています。設計や情報整理、事前検証などコードを書き始める前にも多くのタスクがあるためです。
しかし何もしないと、このファーストコミット以前の時間が記録されず、リードタイムの計測から抜け落ちてしまいます。これは改善や見積もり精度を高めるうえで大きな課題でした。
解決策:プロジェクト開始時に空コミットを挿入
そこで私たちは、プロジェクト開始(ブランチ作成)と同時に空コミットを入れるという方法を選択しました。
- プロジェクト開始タイミングでブランチを作成する
- ブランチを作成したら、まだ何の変更も行っていない状態で
git commit --allow-empty
を行う - 以降の通常実装やPR作成までの時間を、リードタイムとして正しく計測できる
このように、「空コミット」がリードタイム計測の起点になるイメージです。結果として「設計や要件定義、調査に費やした時間」もリードタイムとしてカウントできるようになります。
スクリプトによる自動化
なぜスクリプト化するのか
手動で git commit --allow-empty
を行う方法でも十分に機能しますが、「空コミットを忘れる」リスクがあります。また、チーム全員が同じフローを徹底するのも大変です。
そこで、ローカルのGitフックやGitHub Actionsなどを活用して、自動化を検討しました。
ローカルフック:post-checkoutフックを使う例
ローカルのGitには、特定の操作(コミット直前、ブランチ切り替え直後など)で任意のスクリプトを実行できるフック機能があります。その中で、ブランチを切り替えたタイミングで呼び出されるのがpost-checkout
フックです。
ポイント
-
pre-commit
フックは「コミット実行前」に呼ばれるため、「ブランチ作成直後」に空コミットを作る用途には不向きです。 - 一方で
post-checkout
フックなら、git checkout -b <new-branch>
などで新規ブランチに切り替えた直後にスクリプトが動きます。
以下にサンプルスクリプトを示します。
bash
コードをコピーする
#!/bin/sh
# post-checkoutフックに渡される引数
# $1: 以前のHEAD (コミットハッシュ)
# $2: 新しいHEAD (コミットハッシュ)
# $3: "1"=ブランチ切り替え、"0"=単純なファイルチェックアウト
OLD_REF=$1
NEW_REF=$2
CHECKOUT_TYPE=$3
# ブランチ切り替えの場合にのみ処理を行う
if [ "$CHECKOUT_TYPE" = "1" ]; then
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
# ここでは "新規ブランチ" かどうかの厳密な判定は省略し、
# とりあえずブランチ切り替え時に必ず空コミットを実行する例とします。
# originに同じブランチがあるかチェック
if git ls-remote --heads origin "$CURRENT_BRANCH" | grep -q "$CURRENT_BRANCH"; then
echo "[ERROR] Remote branch '$CURRENT_BRANCH' already exists. Choose a different branch name."
exit 1
fi
# stage されているファイルがある場合はエラー終了させる
if ! git diff --cached --quiet; then
echo "[ERROR] Staged changes are present. Please commit or stash them before checking out a new branch."
exit 1
fi
echo "Switched to branch: $CURRENT_BRANCH"
echo "Creating an empty commit..."
# 空コミットを作成
git commit --allow-empty -m "プロジェクト開始: auto empty commit on branch=$CURRENT_BRANCH"
fi
ファイルの設置場所・権限
- このスクリプトを
<リポジトリ>/.git/hooks/post-checkout
として保存します。 -
chmod +x .git/hooks/post-checkout
で実行権限を付与しておきます。
動作確認
-
git checkout -b feature/new-project
のように新規ブランチを作成・チェックアウトすると、本スクリプトが呼び出され、空コミットが作成されます。 - もしすでにステージングエリアにファイルがあった場合は、エラーを出して終了します。
こうしたフックはあくまでもローカル開発環境ごとに設定しなければならないため、チーム全員で使う場合には共有や教育が必要になります。
GitHub Actions でのサーバサイドの自動化
ローカルフックだとどうしても「設定していない」問題が残ります。そこで、GitHub上でブランチを作成することでGitHub Actionsを使ったサーバサイドの自動化も有効です。
yaml
コードをコピーする
name: Auto Empty Commit
on:
create:
branches:
- '*'
jobs:
empty-commit:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Create an empty commit
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git commit --allow-empty -m "プロジェクト開始: branch=${{ github.ref }}"
git push origin HEAD:${{ github.ref }}
-
on: create
を利用すると、新しいブランチがリポジトリに作成された瞬間にワークフローが走ります。 - そして空コミットを自動的にプッシュします。
この方法だと、開発者が意識しなくてもブランチ作成のたびに空コミットが入るので、開発開始時にGitHub上でブランチを作成するという運用をしていればチーム全体でミスなく運用できます。反面、リポジトリ設定や権限周り、Workflowの挙動(例:Protected Branchの設定など)によっては調整が必要です。
運用することでの期待値
-
リードタイムの「隠れ時間」が可視化できるようになる
- 要求~設計~ファーストコミットまでに費やした時間をデータで把握できる
-
見えなかった付加価値を認識しやすくなる
- コードを書いていなくても、設計や調査という「価値のある時間」が計測対象に含まれる
-
運用ルールの定着が鍵
- ローカルフックの場合は各自の環境に依存するので、GitHub Actionsのようなサーバサイドの仕組みを併用するのがおすすめ
まとめ
- 「プロジェクト開始」から「PRオープン」までの本当のリードタイムを可視化するために、空コミットを導入する仕組みを構築
- ローカルのGitフック(
post-checkout
)やGitHub Actions(on: create
)を活用することで、コミットを自動化・ミスの削減 - 特に、ステージにファイルが残っている場合にエラー終了させるといった細かいロジックを入れることで、混乱や意図しないコミットを防ぐことが可能
設計や要件定義といった「コードを書き始める前の作業」をしっかり可視化できるようになると、チームとしての計画やコミュニケーションも格段にやりやすくなります。
もし同様の課題を抱えている方は、ぜひ一度試してみてください!
Discussion