![見出し画像](https://assets.st-note.com/production/uploads/images/122386346/rectangle_large_type_2_7a726f65a4084d6fa2f33843fa5d318b.png?width=1200)
ChatGPTを使ってGitのコミットメッセージを自動生成する
コミットメッセージはちゃんと書くに越したことはないが、定型文になりがち。なら、たたき台をChatGPTに生成してもらえばいいのではないか、ということで早速作ってみた。
ここで使用するのはChatGPTの非公式CLIツール。
インストールし、OPENAI_API_KEYを設定するとコマンドラインからChatGPTを利用できる。
% chatgpt "Hello, how is it going?"
Hello! I'm an AI assistant, so I don't experience emotions, but I'm here to help you with any questions or tasks you might have. How can I assist you today?
Gitのprepare-commit-msg hookからこれを呼び出せばよいという寸法だ。
#!/usr/bin/env bash
# 元のコミットメッセージを取得する
original=$(grep "^#" "$1")
# diffからChatGPTでコミットメッセージを生成する
chatgpt '' > $1 <<EOF
Generate a descriptive commit message explaining the following diff, following the Conventional Commits format.
$(git diff --name-status -- "$pattern")
$(git diff --cached | head -n100)
EOF
# 元のコミットメッセージを追記する
echo "$original" >> $1
# /path/to/git/hooksの中にprepare-commit-msgスクリプトを置いておく
git config --global core.hooksPath /path/to/git/hooks
すると、こんな感じで、diffの内容を参照してコミットメッセージを生成してくれる。
feat(git-hooks): add prepare-commit-msg hook
This commit adds a new prepare-commit-msg hook script to the project. The script is respons
ible for generating a descriptive commit message from the provided diff, while adhering to
the Conventional Commits format. The script retrieves the original commit message, generate
s a new message using ChatGPT, and appends the original message to the generated one.
しかし、これではrebaseやamendのときの挙動がおかしくなってしまうため、ブランチ上にいない場合や、既存のコミットメッセージがある場合はスキップする。
# Abort if it is not on a branch
if [[ $(git rev-parse --abbrev-ref HEAD) == "HEAD" ]]; then
exit 0
fi
# Abort if a preivious commit message already exists
if (( $(grep -v "^#" "$1" | wc -l) > 1 )); then
exit 0
fi
feat(commit message): generate descriptive commit message from diff
This commit updates the prepare-commit-msg hook script to generate a descriptive commit mes
sage from the diff. It skips execution when on a non-branch state (e.g., during a rebase) a
nd when the commit message already exists (e.g., during an amend).
さらに、GitHub上でdiffを折りたたむように.gitattributesで設定している項目については除外したいので、AWKを使って少しこねくり回した。
pattern=.
if [ -e .gitattributes ]; then
pattern=$(awk 'NF==0 {next} /^#.*/ {next} /linguist-generated=true/ {print ":^" $1}' < .gitattributes)
fi
chatgpt 'Generate a terse but descriptive commit message from the following diff' \
"$(git diff --cached -- "$pattern" | head -n100)" > $1
feat: Exclude generated files from diff
Excludes generated files from the diff in `prepare-commit-msg` script. The pattern for excluding files is determined based on the presence of a `.gitattributes` file. If the file exists, it uses an awk command to extract the pattern for exclusion from the file.
すべてまとめたものがこちら。
https://github.com/fumieval/dotfiles/blob/master/git-hooks/prepare-commit-msg
まとめ
ChatGPTのコマンドラインインターフェイスとgit hooksを組み合わせ、コミットメッセージの生成を容易に実現することができた。さらに、ChatGPTがConventional Commitsの知識を持っているため、そのフォーマットに対応させることができた。
この記事が気に入ったらサポートをしてみませんか?