1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

リモートなしのローカルリポジトリで IBM Bob のレビューワークフローを動かす

1
Posted at

はじめに

IBM Bob のレビューワークフロー(Code Reviews)は、Git のブランチ間の差分を AI がレビューしてくれる機能です。一通り試した内容は別記事にまとめました。

この記事は、リモートリポジトリを用意せず、git init しただけのローカルリポジトリでレビューワークフローを動かす方法です。

筆者の環境では、リモートが登録されていないリポジトリではレビューパネルにレビュー対象のブランチが出てこず、レビューを開始できませんでした

image.png

ただし、以下の 1 行を実行すれば回避できます。

git symbolic-ref refs/remotes/origin/HEAD refs/heads/main

リモートを作る必要はありません。参照だけ作れば通ります。 以下、なぜこれで通るのか、どこに注意が必要かを順に説明します。

テスト環境

項目 バージョン
IBM Bob 2.0.3
OS Windows 11

UI のラベルや挙動は Bob のバージョンによって変わる可能性があります。以下は筆者が実際に試した時点での内容です。

手順 1: ローカルリポジトリを作る

サンプルプログラムを置いたフォルダで、リポジトリを初期化してコミットします。本編と同じ Python スクリプトを使いました。

python;sample_shain_select.py
import sqlite3


def main() -> None:
    conn = sqlite3.connect("sample.db")
    cursor = conn.cursor()

    cursor.execute(
        "create table if not exists shain (id integer primary key, name text)"
    )
    cursor.execute("delete from shain")
    cursor.execute("insert into shain (id, name) values (?, ?)", (1, "田中"))
    cursor.execute("insert into shain (id, name) values (?, ?)", (2, "佐藤"))

    conn.commit()
    conn.close()


if __name__ == "__main__":
    main()

実行するコマンドは 4 つだけです(PowerShell で実行しました)。

git init
git add .
git commit -m "first commit"
git branch -M main

git remote addgit push もしません。実行ログは次のようになりました。

PS ...\260817reviewtestLocal> git init
Initialized empty Git repository in .../260817reviewtestLocal/.git/

PS ...\260817reviewtestLocal> git add .

PS ...\260817reviewtestLocal> git commit -m "first commit"
[master (root-commit) e1d5053] first commit
 1 file changed, 30 insertions(+)
 create mode 100644 sample_shain_select.py

PS ...\260817reviewtestLocal> git branch -M main

git init の既定ブランチ名が master の環境なので、git branch -M main でリネームしています。すでに main で初期化される設定(init.defaultBranch=main)なら不要です。

手順 2: origin/HEAD の参照を作る

ここが本題です。Bob はレビュー対象の既定ブランチを refs/remotes/origin/HEAD という参照から判定しているとみられ、git init から始めたリポジトリにはこの参照がありません。これを手作業で作ります。

git symbolic-ref refs/remotes/origin/HEAD refs/heads/main

意味は「既定ブランチを指す参照を作り、その中身をローカルの main に向ける」です。成功しても何も出力されません(無言で終わります)。

指定している値 内容
refs/remotes/origin/HEAD 作る参照。Bob が見に来るのはここ
refs/heads/main 参照の中身。ローカルの main ブランチ

参照先には実在するブランチを指定してください。 存在しないパスでも Bob のエラー自体は回避できてしまいますが、その場合は git rev-parse origin/HEAD

warning: ignoring dangling symref refs/remotes/origin/HEAD
fatal: ambiguous argument 'origin/HEAD': unknown revision or path not in the working tree.

となる壊れた参照(dangling symref)ができます。ブランチ名が main でなければ、そのブランチ名に読み替えてください。

作られたことを確認する

3 つのコマンドで確認できます。

$ git symbolic-ref refs/remotes/origin/HEAD --short
main

$ git branch -a
* main
  remotes/origin/HEAD -> main

$ git remote -v
(何も表示されない)

1 つ目が Bob が実行しているとみられるコマンドで、これが値を返せば通ります。3 つ目が空であることが重要で、リモートは 1 つも登録していません。 それでも git branch -a には remotes/origin/HEAD -> main が現れます。

ウィンドウを再読み込みする

参照を作ったあと、レビューパネルを開き直します。すでに開いている場合は表示が古いままなので、ウィンドウの再読み込みが確実です。

  1. Ctrl + Shift + P でコマンドパレットを開く
  2. 開発者: ウィンドウの再読み込み(Developer: Reload Window) を実行する

image.png

再読み込みが終わると、レビューパネルにリポジトリとレビュー対象が表示されます。

image.png

手順 3: レビュー対象を選ぶ(注意点あり)

再読み込み後、「レビュー対象」のドロップダウンには次の 2 つが現れます。このうち選ぶべきは main(現在)だけです。

表示 実体 選んだ結果
main(現在) ローカルの main これを選ぶ。 未コミット変更がレビュー対象になる
origin/main 存在しない 候補から消え、レビュー対象ファイルが 0 件になる

main(現在)を選ぶと、コミットされていない変更を含めるが自動で有効になります(レビュー対象が現在のブランチのときの Bob の既定動作です)。この状態でファイルを編集すると、レビュー対象ファイルに M バッジ付きで並びます。

image.png

つまりこの構成でレビューされるのは「main の最新コミットと、手元の未コミット変更の差分」です。リモートありの構成で「リモートの最新と手元を比較する」のとは対象が違う点に注意してください。

手順 4: レビューを実行する

あとは本編と同じです。main(現在)を選んだ状態でファイルに変更を加え、レビューを開始を押します。

本編では、f-string で SQL を組み立てるコードを追加して SQL インジェクションを検出させました。

import sqlite3


def main() -> None:
    conn = sqlite3.connect("sample.db")
    cursor = conn.cursor()

    cursor.execute(
        "create table if not exists shain (id integer primary key, name text)"
    )
    cursor.execute("delete from shain")
    cursor.execute("insert into shain (id, name) values (?, ?)", (1, "田中"))
    cursor.execute("insert into shain (id, name) values (?, ?)", (2, "佐藤"))

    target_id = 1
    sql_preview = f"select name from shain where id = {target_id}"
    cursor.execute(sql_preview)
    row = cursor.fetchone()
    print(row[0] if row else "該当なし")

    # target_id = 1
    # cursor.execute("select name from shain where id = ?", (target_id,))
    # row = cursor.fetchone()
    # print(row[0] if row else "該当なし")
    conn.commit()
    conn.close()


if __name__ == "__main__":
    main()

image.png

[画像] レビュー対象に main(現在)を選び、レビュー対象ファイルに sample_shain_select.pyM 付きで表示された状態

指摘は下部パネルの BOB FINDINGS タブに一覧表示され、そこから Bobで修正 で修正させることもできます。この流れは本編で詳しく書いているので、そちらを参照してください。

image.png

補足: ローカルだけでブランチ間の差分をレビューする

ここまでの構成でレビューされるのは未コミット変更だけです。本来の「ブランチ間の差分」をリモートなしで試すこともできます。参照を作ったあとに分岐を作ります。

git checkout -b feature
# feature ブランチで変更してコミット

この状態でレビューパネルを開くと、作成したローカルブランチが候補に並ぶことを確認できました。

image.png

feature で作業しながらレビュー対象に main を選べば、そのままブランチ間の差分をレビューできます。

つまり、ブランチ一覧の取得が通ってしまえば、ローカルブランチ同士の比較にリモートは要りません。前述の origin/main のような実体のない候補を避けたい場合も、この形が素直です。

元に戻す・あとからリモートを付ける

作った参照は削除できます。

git symbolic-ref -d refs/remotes/origin/HEAD

なお Windows では、削除のあとに次のようなプロンプトが繰り返し出ることがあります。

Deletion of directory '.git/logs/refs/remotes/origin' failed. Should I try again? (y/n) n
Deletion of directory '.git/refs/remotes/origin' failed. Should I try again? (y/n) n

git が参照を消したあと、空になったディレクトリを片付けようとして失敗している状態です。参照そのものはすでに削除されているので、n を入力して抜けて問題ありません。git branch -a から remotes/origin/HEAD が消えていれば削除は完了しています。

ディレクトリの削除に失敗するのは、フォルダを別のプロセスが掴んでいるためです。OneDrive などの同期対象フォルダ配下にリポジトリを置いている場合は起こりやすいので、空ディレクトリまで消したい場合は VS Code を閉じ、同期を一時停止してから手動で削除してください。残っていても無害です。

あとから本物のリモートを用意する場合は、参照を削除してから通常の手順を実行します。最後の git remote set-head origin -a が、今回手作業で作った参照をリモートの実際の既定ブランチに向けて作り直してくれます。

git symbolic-ref -d refs/remotes/origin/HEAD
git remote add origin https://github.example.com/your-account/260817reviewtest.git
git push -u origin main
git remote set-head origin -a

まとめ

  • git init から始めたローカルリポジトリでは、レビュー対象のブランチが取得できないことがある。 原因は Bob が見に来る refs/remotes/origin/HEAD という参照が存在しないこと
  • 回避策は git symbolic-ref refs/remotes/origin/HEAD refs/heads/main の 1 行。リモートの登録は不要で、参照だけで足りる
  • 実行後はウィンドウを再読み込みする
  • レビュー対象の候補に出る origin/main実体がないので選ばない。選ぶとレビュー対象ファイルが 0 件になる。main(現在)を選ぶ
  • この構成でレビューされるのは未コミット変更。「コミットされていない変更を含める」は自動で有効になる
  • 分岐を作ればローカルブランチ同士の比較もリモートなしでできる(候補に並ぶことを確認)
  • うまく動かないときは、まず git symbolic-ref refs/remotes/origin/HEAD --short が値を返すかを確認する

なお、公式ドキュメントに書かれているレビューの前提条件は「比較したいローカル/リモートブランチにアクセスできること」だけで、リモートの登録が必須とは書かれていません。本来はリモートなしの構成でも動くべきところなので、この挙動は将来のバージョンで変わる可能性があります。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?