AIによるコミットメッセージを試してみる
2023/10/31時点。
node製。6.5k stars。最終commitは2023/05。
node製。4.7k stars。最終commitは2023/10/05。
go製。774k stars。最終commitは2023/10/31。
所感
- conventional commitsには全部対応してる
- 後ろの2つがメンテされてそう
- 日本語に対応しているのは後ろの2つっぽい。
- goだと環境気にしなくてよさそう。homebrewでインストールできる。
- opencommitはcommitlint対応
- CodeGPTはコードレビュー機能
ということで個人的には導入しやすさ的にはCodeGPTがなんとなく一番良さそう、時点でopencommitって感じ。とりあえず試してみる。
CodeGPT
- Support Azure OpenAI Service or OpenAI API.
- Support conventional commits specification.
- Support Git prepare-commit-msg Hook, see the Git Hooks documentation.
- Support customize generate diffs with n lines of context, the default is three.
- Support for excluding files from the git diff command.
- Support commit message translation into another language (support en, zh-tw or zh-cn).
- Support socks proxy or custom network HTTP proxy.
- Support model lists like gpt-4, gpt-3.5-turbo ...etc.
- Support do a brief code review.
インストール
homebrewで。
$ brew tap appleboy/tap
$ brew install codegpt
$ version: 0.6.2 commit: 77b2e90
OpenAIのAPIキーをセット
$ codegpt config set openai.api_key sk-XXXXXXXXXXXX
設定は$HOME/.config/codegpt/.codegpt.yaml
に保存されるとあるが、APIキーは別にセットされていない?というか設定ファイルが作成されるので、直接設定しろってことなのか?
色々やってみたけど更新されない。直接ファイルを設定すれば問題なさそうではあるが、一旦issueあげておいた
https://github.com/appleboy/CodeGPT/issues/126 マージされました。
設定を確認
$ codegpt config list
Key Value
git.diff_unified 3
git.exclude_list
git.template_file
git.template_string
openai.api_key ****************
openai.api_version
openai.base_url
openai.frequency_penalty <nil>
openai.headers
openai.max_tokens 300
openai.model gpt-3.5-turbo
openai.model_name
openai.org_id
openai.presence_penalty <nil>
openai.provider openai
openai.proxy
openai.skip_verify false
openai.socks
openai.temperature 1
openai.timeout 10s
openai.top_p <nil>
output.lang en
デフォルトでいくつか設定されているものがある。適宜設定すればよい。
$ codegpt config set output.lang ja
$ codegpt config set openai.max_tokens 4000
実際の使い方
サンプルのレポジトリを作ってみる。
$ mkdir codegpt-sample && cd codegpt-sample
$ git init
$ echo "# codegpt-sample" > README.md
$ git add .
ではコミットメッセージを生成。--preview
だと実際にコミットはされない。
$ codegpt commit --preview
Summarize the commit message use gpt-3.5-turbo model
We are trying to summarize a git diff
PromptTokens: 521, CompletionTokens: 6, TotalTokens: 527
We are trying to summarize a title for pull request
PromptTokens: 177, CompletionTokens: 7, TotalTokens: 184
We are trying to get conventional commit prefix
PromptTokens: 305, CompletionTokens: 1, TotalTokens: 306
We are trying to translate a git commit message to Japanese language
PromptTokens: 95, CompletionTokens: 42, TotalTokens: 137
================Commit Summary====================
ドキュメント: プロジェクトドキュメントにREADME.mdファイルを追加
- README.mdファイルを追加しました。
==================================================
Write the commit message to .git/COMMIT_EDITMSG file
--preview
なしでコミットしてみる。
$ codegpt commit
Summarize the commit message use gpt-3.5-turbo model
We are trying to summarize a git diff
PromptTokens: 521, CompletionTokens: 4, TotalTokens: 525
We are trying to summarize a title for pull request
PromptTokens: 176, CompletionTokens: 6, TotalTokens: 182
We are trying to get conventional commit prefix
PromptTokens: 304, CompletionTokens: 1, TotalTokens: 305
We are trying to translate a git commit message to Japanese language
PromptTokens: 93, CompletionTokens: 38, TotalTokens: 131
================Commit Summary====================
ドキュメント: プロジェクトリポジトリにREADMEファイルを追加
- READMEファイルを追加
==================================================
Write the commit message to .git/COMMIT_EDITMSG file
Git record changes to the repository
[main (root-commit) 4c9151e] ドキュメント: プロジェクトリポジトリにREADMEファイルを追加
1 file changed, 1 insertion(+)
create mode 100644 README.md
コミットヒストリーでも実際にコミットされていることが確認できる。
$ git log
commit 4c9151eb1aaca7bb2a9817ef29ebb1d0b269d32e (HEAD -> main)
Author: kun432 <kun432@users.noreply.github.com>
Date: Tue Oct 31 13:03:21 2023 +0900
ドキュメント: プロジェクトリポジトリにREADMEファイルを追加
- READMEファイルを追加
Signed-off-by: Kuniaki Shimizu <kun432@users.noreply.github.com>
git hookにも対応している。
$ codegpt hook install
Install git hook: prepare-commit-msg successfully
You can see the hook file: .git/hooks/prepare-commit-msg
$ echo -e "\n## Author\n\n- kun432" >> README.md
$ git add
$ git commit
エディタが開いて、コミットメッセージが予め生成された状態となる。
git hookをアンインストールするには以下
$ codegpt hook uninstall
コードレビュー
コードレビューもできる。
ファイルを編集してgit addする。
$ echo -e "## Usage\n- just do it." >> README.md
$ git add .
レビュー
$ codegpt review
Code review your changes using gpt-3.5-turbo model
We are trying to review code changes
PromptTokens: 108, CompletionTokens: 52, TotalTokens: 160
We are trying to translate code review to Japanese language
PromptTokens: 131, CompletionTokens: 115, TotalTokens: 246
================Review Summary====================
提供されたコードパッチを基にすると、重要な変更は行われていないようです。コードパッチは単にREADME.mdファイルに新しい行を追加するだけです。
そのため、このコードパッチに対して修正が必要なバグのリスクやセキュリティの脆弱性、改善の提案はありません。
==================================================
おわりに
brewコマンドで簡単にインストールできるので、環境構築が不要なのは良い。やはりこの手のツールはgoで書かれていると良いなと思うところ。機能的にもよく使うものは一通りカバーされているし、コードレビューできるのも良いと思う。
とりあえずシンプルにまず始めてみるにはいいと思う。
OpenCommit
ざっと見た感じ
- node.js製
- Winner of GitHub 2023 HACKATHON
- CIでも使える。GitHub MarketplaceにActionがある
- commitlintに対応
あたりで機能が豊富そうに思える。Mac新調してからはあまりローカルに環境作らずにdevcontainerを使いたいと思ってたのだけど、グローバルなツールだとちょっと厳しいので、今回はnode環境を作りつつやってみる。
インストール
node環境作ってないのでそこから。バージョン管理はvoltaで。
$ brew install volta
$ volta setup
別ターミナルで。
$ volta install node@20
$ node -v
v20.9.0
opencommitをインストール
$ npm install -g opencommit
OpenAIのAPIキーをセット
$ oco config set OCO_OPENAI_API_KEY=sk-XXXXXXXXXX
設定ファイルは$HOME/.opencommit
にある。APIキーをセットしただけだとこんな感じ。
OCO_OPENAI_API_KEY=sk-XXXXXXXXXX
OCO_OPENAI_MAX_TOKENS=undefined
OCO_OPENAI_BASE_PATH=undefined
OCO_DESCRIPTION=false
OCO_EMOJI=false
OCO_MODEL=gpt-3.5-turbo-16k
OCO_LANGUAGE=en
OCO_MESSAGE_TEMPLATE_PLACEHOLDER=$msg
OCO_PROMPT_MODULE=conventional-commit
ということで以下あたりを設定してみる。
$ oco config set OCO_MODEL=gpt-3.5-turbo
$ oco config set OCO_LANGUAGE=ja
$ oco config set OCO_OPENAI_MAX_TOKENS=3000
$ oco config set OCO_EMOJI=true
実際の使い方
サンプルレポジトリを作ってみる
$ mkdir opencommit-sample && cd opencommit-sample
$ git init
$ echo "# opencommit-sample" > README.md
$ git add .
コミットはoco
コマンドで行う
$ oco
以下のように生成されるので、OKならば"Yes"を選択。
┌ open-commit
│
◇ 1 staged files:
README.md
│
◇ 📝 Commit message generated
│
└ Generated commit message:
——————————————————
📝 ドキュメント(README.md): README.mdファイルを追加
——————————————————
│
◆ Confirm the commit message?
│ ● Yes / ○ No
└
コミットはされたようだけど、なんかエラー出てる。
◇ Confirm the commit message?
│ Yes
│
└ ✔ Successfully committed
│
└ [main (root-commit) fb98012] 📝 ドキュメント(README.md): README.mdファイルを追加
1 file changed, 1 insertion(+)
│
◇ 📝 Commit message generated
│
└ ✖ Command failed with exit code 128: git push
fatal: No configured push destination.
Either specify the URL from the command-line or configure a remote repository using
git remote add <name> <url>
and then push using the remote name
git push <name>
どうもpushまで自動的に行うのかな?一応コミットは出来てる。
$ git log
commit fb98012af1965cb17368622b3a46e570f48c60b4 (HEAD -> main)
Author: Kuniaki Shimizu <kun432@users.noreply.github.com>
Date: Wed Nov 1 09:10:08 2023 +0900
📝 ドキュメント(README.md): README.mdファイルを追加
リモートブランチ設定して再度やってみる。
$ echo -e "\n## Usage\n\n- Just do it.\n" >> README.md
$ git add .
$ oco
なるほど、リモートブランチがある場合はpushするかどうかを確認してくれるのね。
┌ open-commit
│
◇ 1 staged files:
README.md
│
◇ 📝 Commit message generated
│
└ Generated commit message:
——————————————————
📝 ドキュメント(README.md): 使用方法のセクションを追加
——————————————————
│
◇ Confirm the commit message?
│ Yes
│
└ ✔ Successfully committed
│
└ [main dcf1b18] 📝 ドキュメント(README.md): 使用方法のセクションを追加
1 file changed, 5 insertions(+)
│
◆ Do you want to run `git push`?
│ ● Yes / ○ No
└
◇ Do you want to run `git push`?
│ Yes
│
◇ ✔ Successfully pushed all commits to origin
まあローカルだけっていう使い方は少ないだろうけども、ちょっとfatalで返されるとビビるよね。無効にするオプションとかないのかなー。-h
つけても大したメッセージが出ない。
コミットログはこんな感じでいいですね。大したこと書いてないけども。
git hookにも対応している。
$ oco hook set
┌ setting opencommit as 'prepare-commit-msg' hook at .git/hooks/prepare-commit-msg
│
└ ✔ Hook set
コミットしてみる。
$ echo -e "\n## Author\n\n- kun432\n" >> README.md
$ git add .
$ git commit
エディタが開いて、コミットメッセージが予め生成された状態となる。
git hookをアンインストールするには以下。
$ oco hook set
GitHub Actions
OpenCommitはGitHub Actionsにも対応している。
以下のようなGitHub Actionsの設定を追加しておく。
name: 'OpenCommit Action'
on:
push:
# 無視するブランチを列挙する
# 通常はこのブランチのリストで十分だが、必要なら他のブランチも追加する
branches-ignore: [main master dev development release]
jobs:
opencommit:
timeout-minutes: 10
name: OpenCommit
runs-on: ubuntu-latest
permissions: write-all
steps:
- name: Setup Node.js Environment
uses: actions/setup-node@v2
with:
node-version: '16'
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: di-sukharev/opencommit@github-action-v1.0.4
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
env:
# OpenAI APIキーをレポジトリのGitHub Actionsのsecretに設定しておく
# OpenAI APIーの取得: https://platform.openai.com/account/api-keys
# レポジトリのsecretの設定: <レポジトリURL>/settings/secrets/actions
OCO_OPENAI_API_KEY: ${{ secrets.OCO_OPENAI_API_KEY }}
# 好みに合わせてカスタマイズ
OCO_OPENAI_MAX_TOKENS: 3000
OCO_OPENAI_BASE_PATH: ''
OCO_DESCRIPTION: true
OCO_EMOJI: true
OCO_MODEL: gpt-3.5-turbo
OCO_LANGUAGE: ja
OCO_PROMPT_MODULE: conventional-commit
OpenAI APIキーをActionsのSecretにOCO_OPENAI_API_KEY
で登録しておく。
では適当なブランチを切って適当なコミットメッセージでコミットしてpushする。
$ git checkout -b sample-branch
$ echo -e "## Thanks\n\n- OpenCommit\n" >> README.md
$ git add .
$ git commit -m "fix"
$ git push --set-upstream origin sample-branch
Actionsが実行されている。
該当のブランチでPRを作成してみると、コミットメッセージが修正されているのがわかる。
CommitLintとの連携?
OpenCommitはデフォルトでConventional Commitsなコミットメッセージを生成するようになっているが、commitlintなどを既に使っている場合はそちらにあわせることもできるらしい。
commitlintあまり詳しくないので詳細は割愛するけど、適当に動かしてみた感じだと、
- ローカルにcommitlintの設定が行われていれば、その内容を元にOpenCommit用の設定ファイルが作成される
- 設定ファイルをみると、commitlintの設定を元にプロンプトが生成されており、これでコミットメッセージが生成される模様。
という感じなので、既にcommitlint使っている、という場合でもうまく使えるんじゃないかなという気はした。
おわりに
機能はCodeGPTよりも豊富だと思う。Node.jsなプロジェクトなら全然アリ。個人的には他言語のプロジェクトで使う場合にNode.js環境を用意するのはな〜、、、と思ったのだけど、devcontainer化しておけば気にしなくても良さそう。
VSCode + Copilotで生成してくれるようになったらしい。
まとめ(2023/11/4時点)
- まだ試してなくて、とりあえず気軽にローカルで試してみるならCodeGPTが良さそう。環境依存しないし。
- Node.jsプロジェクトで使う、既存のcommitlint設定も維持する、CIで使う、みたいな場合はOpenCommitで。
- 有償でもいいから、コミットメッセージ以外も含めてまるっといろいろ、ならGitHub Copilot
って感じかなぁ。いずれにせよ開発フローに影響する部分だと思うので、チーム開発の場合はチーム事情にあわせて検討することになるのではないかという気がする。
CodeGPT環境依存せずに使えて良さそう、このためにわざわざNode.js環境作るのもな~、というのが最初の印象なんだけど、翌々考えてみればVSCode+devcontainerが自分のメイン環境なので、別に全然気にすることないなと思いなおしてるところ。
Copilotは悩み中・・・コミットメッセージだけじゃなくて諸々便利になるのはわかってるんだけども、自分の場合はgitはコマンドで叩くことのほうが多い上、AI関連は他にも結構いろいろ支払いあってチリツモなのよね・・・
GitHub Copilotのセキュリティ・ライセンスについて。当初あまりわかってなくて、個人だと学習されてしまうと思っていたけど、どうも自分の理解が不足していたみたい。
ざっと見た限り、コミットメッセージのカスタマイズ、例えばissue番号紐付ける、とかはどちらもできるようだけども、プロンプトのカスタマイズまでは出来ない模様。コードを変更すれば出来なくはなさそうではあるけれども。まあコミットメッセージにそこまでのニーズはないのかもしれない。